引入
- 除了动态图转静态图的方式导出推理模型之外
- Paddle2.0中也正式内置了ONNX模型的导出功能
- 本文将通过一个实例演示一下如何将Paddle模型导出为ONNX模型
- 并在ONNXRunTime上完成模型的推理预测
ONNX
- Open Neural Network Exchange (ONNX) ,是一个机器学习模型的开放标准,方便不同框架之间进行模型交换
- 你可以在很多支持ONNX模型导出的框架上构建模型,然后导出ONNX模型进行预测部署

Paddle2ONNX
- 目前Paddle导出ONNX模型需要安装Paddle2ONNX进行额外支持
- Paddle2ONNX支持将PaddlePaddle模型格式转化到ONNX模型格式。
- 模型格式,支持Paddle静态图和动态图模型转为ONNX,可转换由save_inference_model导出的静态图模型。动态图转换目前处于实验状态,将伴随Paddle 2.0正式版发布后,提供详细使用教程
- 算子支持,目前稳定支持导出ONNX Opset 9~11,部分Paddle算子支持更低的ONNX Opset转换,详情可参考算子列表
- 模型类型,官方测试可转换的模型请参考模型库
- 更多详情请参考Paddle2ONNX的Github主页
$ pip install paddle2onnx
$ git clone https://github.com/paddlepaddle/paddle2onnx
$ cd paddle2onnx
$ python setup.py install
动态图ONNX模型导出
- 如果使用Paddle2.0构建的动态图模型,可以通过调用paddle.onnx.export()来实现ONNX模型的快速导出
- 大致的原理就是动转静在将静态图模型转换为ONNX模型,所以转换的代码上与动转静很相似
- 接下来就通过代码来演示一下导出的流程
import os
import time
import paddle
from u2net import U2NETP
model = U2NETP()
model.set_dict(paddle.load([path to the pretrained model]))
model.eval()
input_spec = paddle.static.InputSpec(shape=[None, 3, 320, 320], dtype='float32', name='image')
paddle.onnx.export(model, [path to the save onnx model], input_spec=[input_spec], opset_version=[opset version])
2021-01-09 17:12:24 [INFO] ONNX model saved in u2netp.onnx
静态图模型转换
- 除了动态图模型可以导出为ONNX模型
- 静态图的推理模型当然也可以转换为ONNX模型
- 通过命令行调用如下命令即可完成转换
- 更多细节请参考paddle2onnx官方Github文档
$ paddle2onnx \
--model_dir [model dir] \
--model_filename [model filename] \
--params_filename [params filename] \
--save_file [save file] \
--opset_version [opset version]
2021-01-09 17:12:28 [INFO] ONNX model saved in u2netp_static.onnx
模型可视化
- 通过VisualDL工具可以轻松的进行模型结构的可视化查看
- 选择刚才保存后缀为.onnx的模型文件
- 具体的可视化图像就像下图所示的那样:


模型测试
- 这里使用ONNXRunTime来进行ONNX模型验证测试
$ pip install onnxruntime
import time
import numpy as np
from onnxruntime import InferenceSession
model = InferenceSession([path to the save onnx model])
x = np.random.random((1, 3, 320, 320)).astype('float32')
d0, _, _, _, _, _, _ = model.run(output_names=None, input_feed={
'image': x})
print(d0.shape)
start = time.time()
d0, _, _, _, _, _, _ = model.run(output_names=None, input_feed={
'image': x})
end = time.time()
print('predict time: %.04f s' % (end - start))
(1, 1, 320, 320)
predict time: 0.7178 s
部署实例
- 接下来通过加入数据预处理和后处理来完成完整的模型推理部署
import cv2
import time
import numpy as np
import matplotlib.pyplot as plt
from onnxruntime import InferenceSession
from processor import preprocess, postprocess
img_path = [path to the input image]
output_dir = [output dir]
img = preprocess(img_path)
model = InferenceSession([path to the save onnx model])
start = time.time()
d0, _, _, _, _, _, _ = model.run(output_names=None, input_feed={
'image': img})
end = time.time()
print('predict time: %.04f s' % (end - start))
mask_path, result_path = postprocess(d0, img_path, output_dir)
img = np.concatenate([
cv2.imread(img_path),
cv2.imread(mask_path),
cv2.imread(result_path)
], 1)
plt.axis('off')
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.show()
predict time: 0.7305 s

总结
- Paddle2.0目前内置了导出ONNX模型的接口,可以较为方便的导出ONNX模型
- 对于之前的静态图模型,使用Paddle2ONNX工具也可以进行转换
- 使用ONNX模型进行推理部署也比较简单和方便
- 但目前仍有一些Paddle算子存在兼容性问题,导致一些模型无法正常的进行导出操作
- 总体体验还是不错的,也希望这个功能未来能够更加完善,支持更多算子