问题描述
问题
我正在使用TF的对象检测API训练和部署实例细分模型。我能够成功训练模型,将其打包到TF服务Docker映像(截至2020年10月为latest
标签)中,并通过REST接口处理推理请求。但是,从推理请求返回的数据量非常大(数百Mb)。当推理请求和处理不在同一台计算机上进行时,这是一个大问题,因为所有返回的数据都必须通过网络传输。
是否有一种方法可以减少输出数量(在模型导出期间或在TF服务图像内),以便在推理过程中缩短往返时间?
详细信息
我正在使用TF OD API(带有TF2)来训练Mask RCNN模型,该模型是this config的修改版本。我相信输出的完整列表在代码here中进行了描述。我在推理过程中得到的项目列表也粘贴在下面。对于具有100个对象建议的模型,如果我只是将返回的推论作为json写入磁盘,则该信息约为270 Mb。
inference_payload['outputs'].keys()
dict_keys(['detection_masks','rpn_features_to_crop','detection_anchor_indices','refined_Box_encodings','final_anchors','mask_predictions','detection_classes','num_detections','rpn_Box_predictor_features','class_predictions_with_background','proposal_Boxes','raw_detection_Boxes','rpn_Box_encodings','Box_classifier_features','raw_detection_scores','proposal_Boxes_normalized','detection_multiclass_scores','anchors','num_proposals','detection_Boxes','image_shape','rpn_objectness_predictions_with_background','detection_scores'])
我已经将推理请求中的图像编码为base64,因此通过网络访问时,请求有效负载不会太大。相比之下,推理响应是巨大的。我仅需要此响应中的4或5个项目,因此最好排除其余部分,并避免在网络上传递这么大的比特包。
我尝试过的事情
- 我尝试在导出(code example here)期间将
score_threshold
设置为较高的值,以减少输出数量。但是,这似乎只是对detection_scores
作了限制。仍然返回所有无关的推断信息。 - 我还尝试通过添加要删除的here键名来手动排除这些推断输出中的一些。这似乎也没有任何作用,我担心这是个坏主意,因为在评分/评估过程中可能需要其中一些键。
- 我也在这里和
tensorflow/models
仓库中搜索,但找不到任何东西。
解决方法
我找到了一个笨拙的解决方法。在导出过程(here)中,预测dict的部分组件被删除。我向 non_tensor_predictions
列表添加了其他项目,其中包含将在后处理步骤中删除的所有键。增加这个列表将我的推理输出从 ~200MB 减少到 ~12MB。
if self._number_of_stages == 3
块的完整代码:
if self._number_of_stages == 3:
non_tensor_predictions = [
k for k,v in prediction_dict.items() if not isinstance(v,tf.Tensor)]
# Add additional keys to delete during postprocessing
non_tensor_predictions = non_tensor_predictions + ['raw_detection_scores','detection_multiclass_scores','anchors','rpn_objectness_predictions_with_background','detection_anchor_indices','refined_box_encodings','class_predictions_with_background','raw_detection_boxes','final_anchors','rpn_box_encodings','box_classifier_features']
for k in non_tensor_predictions:
tf.logging.info('Removing {0} from prediction_dict'.format(k))
prediction_dict.pop(k)
return prediction_dict
我认为在创建 TF Serving 映像期间使用签名定义有一种更“正确”的方法来处理此问题,但这适用于快速而肮脏的修复。
,如果您使用 exporter_main_v2.py
文件导出模型,您可以尝试这种 hack 方式来解决这个问题。
只需在_run_inference_on_images
文件的exporter_lib_v2.py
函数中添加如下代码:
detections[classes_field] = (
tf.cast(detections[classes_field],tf.float32) + label_id_offset)
############# START ##########
ignored_model_output_names = ["raw_detection_boxes","raw_detection_scores"]
for key in ignored_model_output_names:
if key in detections.keys(): del detections[key]
############# END ##########
for key,val in detections.items():
detections[key] = tf.cast(val,tf.float32)
因此,生成的模型不会输出ignored_model_output_names
的值。
请告诉我这是否可以解决您的问题。
,我遇到了同样的问题。在exporter_main_v2代码中,声明输出应为:
and the following output nodes returned by the model.postprocess(..):
* `num_detections`: Outputs float32 tensors of the form [batch]
that specifies the number of valid boxes per image in the batch.
* `detection_boxes`: Outputs float32 tensors of the form
[batch,num_boxes,4] containing detected boxes.
* `detection_scores`: Outputs float32 tensors of the form
[batch,num_boxes] containing class scores for the detections.
* `detection_classes`: Outputs float32 tensors of the form
[batch,num_boxes] containing classes for the detections.
我已经提交了关于tensorflow对象检测github存储库的问题,希望我们能够从tensorflow开发团队获得反馈。
可以找到here
的github问题