我在ONNX格式(分类号为V1.2.1的V1.2.1)的图像分类模型上使用Python 2.7,MXNet V1.3.0 ML框架运行推理,在该模型中我一次将图像馈入推理器。我该怎么办才能异步运行多个图像的推理,但还要等待所有图像完成?
我正在从30 FPS的视频中提取帧作为.jpeg图像。例如,当我在长度为20s的视频上运行该过程时,它将生成600张.jpeg图像。现在,我遍历这些图像的列表,并将它们的相对路径传递给以下函数,然后从目标图像进行推断。
def infer(self, target_image_path):
target_image_path = self.__output_directory + '/' + target_image_path
image_data = self.__get_image_data(target_image_path) # Get pixel data
'''Define the model's input'''
model_metadata = onnx_mxnet.get_model_metadata(self.__model)
data_names = [inputs[0]
for inputs in model_metadata.get('input_tensor_data')]
Batch = namedtuple('Batch', 'data')
ctx = mx.eia() # Set the context to elastic inference
'''Load the model'''
sym, arg, aux = onnx_mxnet.import_model(self.__model)
mod = mx.mod.Module(symbol=sym, data_names=data_names,
context=ctx, label_names=None)
mod.bind(data_shapes=[(data_names[0], image_data.shape)],
label_shapes=None, for_training=False)
mod.set_params(arg_params=arg, aux_params=aux,
allow_missing=True, allow_extra=True)
'''Run inference on the image'''
mod.forward(Batch([mx.nd.array(image_data)]))
predictions = mod.get_outputs()[0].asnumpy()
predictions = predictions[0].tolist()
'''Apply emotion labels'''
zipb_object = zip(self.__emotion_labels, predictions)
prediction_dictionary = dict(zipb_object)
return prediction_dictionary
预期的行为是异步地为每个图像运行推理,但还要等待整个批处理完成。
答案 0 :(得分:2)
您不应该做的一件事就是为每个图像加载模型。应该加载一次模型,然后对所有600张图像进行推断。
例如,您可以像这样重构代码:
def load_model(self):
'''Load the model'''
model_metadata = onnx_mxnet.get_model_metadata(self.__model)
data_names = [inputs[0]
for inputs in model_metadata.get('input_tensor_data')]
Batch = namedtuple('Batch', 'data')
ctx = mx.eia() # Set the context to elastic inference
'''Load the model'''
sym, arg, aux = onnx_mxnet.import_model(self.__model)
mod = mx.mod.Module(symbol=sym, data_names=data_names,
context=ctx, label_names=None)
mod.bind(data_shapes=[(data_names[0], image_data.shape)],
label_shapes=None, for_training=False)
mod.set_params(arg_params=arg, aux_params=aux,
allow_missing=True, allow_extra=True)
return mod
def infer(self, mod, target_image_path):
target_image_path = self.__output_directory + '/' + target_image_path
image_data = self.__get_image_data(target_image_path) # Get pixel data
'''Run inference on the image'''
mod.forward(Batch([mx.nd.array(image_data)]))
predictions = mod.get_outputs()[0].asnumpy()
predictions = predictions[0].tolist()
'''Apply emotion labels'''
zipb_object = zip(self.__emotion_labels, predictions)
prediction_dictionary = dict(zipb_object)
return prediction_dictionary
MXNet在异步引擎上运行,您不必等待图像完成处理即可加入新引擎。
MXNet中的某些调用是异步的,例如,当您调用mod.forward()
时,此调用将立即返回,并且不等待计算结果。其他调用是同步的,例如mod.get_outputs()[0].asnumpy()
会将数据复制到CPU,因此它必须是同步的。在每个迭代之间进行同步调用会减慢处理速度。
假设您有权访问image_paths列表,则可以像这样处理它们,以最大程度地减少等待时间,并仅在最后添加一个同步点:
results = []
for target_image_path in image_paths:
image_data = self.__get_image_data(target_image_path) # Get pixel data
'''Run inference on the image'''
mod.forward(Batch([mx.nd.array(image_data)]))
results.append(mod.get_outputs()[0])
predictions = [result.asnumpy()[0].tolist() for result in results]
您可以在这里阅读有关MXNet异步编程的更多信息:http://d2l.ai/chapter_computational-performance/async-computation.html
更好的是,如果您知道有N张图像要处理,则可以将它们分批(例如16张)以提高处理的并行性。但是,这样做会增加内存消耗。由于您似乎使用的是弹性推断上下文,因此您的整体内存将受到限制,我建议坚持使用较小的批处理大小,以免出现内存不足的风险。