TF 对象检测:推理负载的 return 个子集
TF object detection: return subset of inference payload
问题
我正在使用 TF 的对象检测训练和部署实例分割模型 API。我能够成功地训练模型,将其打包成 TF Serving Docker 图像(截至 2020 年 10 月的 latest
标签),并通过 REST 接口处理推理请求。但是,从推理请求返回的数据量非常大(数百 Mb)。当推理请求和处理不在同一台机器上发生时,这是一个大问题,因为所有返回的数据都必须通过网络。
有没有办法 trim 减少输出数量(在模型导出期间或在 TF 服务图像中),以便在推理期间允许更快的往返时间?
详情
我正在使用 TF OD API(使用 TF2)训练 Mask RCNN 模型,它是 this config. I believe the full list of outputs is described in code 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 个项目,因此最好排除其余项目并避免通过网络传递如此大的位包。
我尝试过的事情
- 我尝试在导出过程中将
score_threshold
设置为更高的值 (code example here) 以减少输出数量。然而,这似乎只是门槛detection_scores
。仍然返回所有无关的推理信息。
- 我还尝试通过添加要删除的键的名称来手动排除其中一些推理输出 here。这似乎也没有任何效果,我担心这是一个坏主意,因为在 scoring/evaluation.
期间可能需要其中一些密钥
- 我也在此处和
tensorflow/models
存储库上进行了搜索,但我什么也没找到。
我 运行 遇到了同样的问题。在 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 开发团队得到反馈。
可以找到github问题here
我找到了一个棘手的解决方法。在导出过程中(here),删除了预测字典的一些组件。我在 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 服务映像期间使用签名定义来处理此问题有一种更“正确”的方法,但这适用于快速但肮脏的修复。
如果您正在使用 exporter_main_v2.py
文件导出您的模型,您可以尝试这种 hack 方式来解决这个问题。
只需在 exporter_lib_v2.py
文件的 _run_inference_on_images
函数中添加以下代码:
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
的值。
如果这可以解决您的问题,请告诉我。
另一种方法是更改已保存模型的签名:
model = tf.saved_model.load(path.join("models", "efficientdet_d7_coco17_tpu-32", "saved_model"))
infer = model.signatures["serving_default"]
outputs = infer.structured_outputs
for o in ["raw_detection_boxes", "raw_detection_scores"]:
outputs.pop(o)
tf.saved_model.save(
model,
export_dir="export",
signatures={"serving_default" : infer},
options=None
)
问题
我正在使用 TF 的对象检测训练和部署实例分割模型 API。我能够成功地训练模型,将其打包成 TF Serving Docker 图像(截至 2020 年 10 月的 latest
标签),并通过 REST 接口处理推理请求。但是,从推理请求返回的数据量非常大(数百 Mb)。当推理请求和处理不在同一台机器上发生时,这是一个大问题,因为所有返回的数据都必须通过网络。
有没有办法 trim 减少输出数量(在模型导出期间或在 TF 服务图像中),以便在推理期间允许更快的往返时间?
详情
我正在使用 TF OD API(使用 TF2)训练 Mask RCNN 模型,它是 this config. I believe the full list of outputs is described in code 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 个项目,因此最好排除其余项目并避免通过网络传递如此大的位包。
我尝试过的事情
- 我尝试在导出过程中将
score_threshold
设置为更高的值 (code example here) 以减少输出数量。然而,这似乎只是门槛detection_scores
。仍然返回所有无关的推理信息。 - 我还尝试通过添加要删除的键的名称来手动排除其中一些推理输出 here。这似乎也没有任何效果,我担心这是一个坏主意,因为在 scoring/evaluation. 期间可能需要其中一些密钥
- 我也在此处和
tensorflow/models
存储库上进行了搜索,但我什么也没找到。
我 运行 遇到了同样的问题。在 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 开发团队得到反馈。
可以找到github问题here
我找到了一个棘手的解决方法。在导出过程中(here),删除了预测字典的一些组件。我在 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 服务映像期间使用签名定义来处理此问题有一种更“正确”的方法,但这适用于快速但肮脏的修复。
如果您正在使用 exporter_main_v2.py
文件导出您的模型,您可以尝试这种 hack 方式来解决这个问题。
只需在 exporter_lib_v2.py
文件的 _run_inference_on_images
函数中添加以下代码:
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
的值。
如果这可以解决您的问题,请告诉我。
另一种方法是更改已保存模型的签名:
model = tf.saved_model.load(path.join("models", "efficientdet_d7_coco17_tpu-32", "saved_model"))
infer = model.signatures["serving_default"]
outputs = infer.structured_outputs
for o in ["raw_detection_boxes", "raw_detection_scores"]:
outputs.pop(o)
tf.saved_model.save(
model,
export_dir="export",
signatures={"serving_default" : infer},
options=None
)