# Paddle2ONNX功能开发文档
# 目录
- [1. 简介](#1)
- [2. Paddle2ONNX推理过程开发](#2)
- [2.1 准备环境](#2.1)
- [2.2 转换模型](#2.2)
- [2.3 开发数据预处理程序](#2.3)
- [2.4 开发ONNX模型推理程序](#2.4)
- [2.5 开发数据后处理程序](#2.5)
- [2.6 验证ONNX推理结果正确性](#2.6)
- [3. FAQ](#3)
## 1. 简介
Paddle2ONNX 支持将 PaddlePaddle 模型格式转化到 ONNX 模型格式,算子目前稳定支持导出 ONNX Opset 9~11,部分Paddle算子支持更低的ONNX Opset转换。
本文档主要介绍飞桨模型如何转化为 ONNX 模型,并基于 ONNXRuntime 引擎的推理过程开发。
更多细节可参考 [Paddle2ONNX官方教程](https://github.com/PaddlePaddle/Paddle2ONNX/blob/develop/README_zh.md)
## 2. Paddle2ONNX推理过程开发
基于Paddle2ONNX的推理过程可以分为6个步骤,如下图所示。
其中设置了2个核验点,分别为
* 准备推理模型
* 验证推理结果正确性
### 2.1 准备环境
**【数据】**
从验证集或者测试集中抽出至少一张图像,用于后续推理过程验证。
**【环境】**
需要准备 Paddle2ONNX 模型转化环境,和 ONNX 模型预测环境
- 安装 Paddle2ONNX
```
python -m pip install paddle2onnx
```
- 安装 ONNXRuntime
```
# 建议安装 1.9.0 版本,可根据环境更换版本号
python -m pip install onnxruntime==1.9.0
```
### 2.2 转换模型
- Paddle 模型动转静导出
**【基本内容】**
`模型动转静`方法可以将训练得到的动态图模型转化为用于推理的静态图模型,具体可参考[Linux GPU/CPU 模型推理开发文档](https://github.com/PaddlePaddle/models/blob/release%2F2.2/docs/tipc/train_infer_python/infer_python.md#2.2)中第2.2章节。
**【实战】**
参考MobileNetV3的Paddle2ONNX [说明文档](../../mobilenetv3_prod/Step6/deploy/onnx_python/README.md) 中的第2.2章节。
- ONNX 模型转换
**【基本内容】**
使用 Paddle2ONNX 将Paddle静态图模型转换为ONNX模型格式:
```
paddle2onnx --model_dir=${your_inference_model_dir}
--model_filename=${your_pdmodel_file}
--params_filename=${your_pdiparams_file}
--save_file=${output_file}
--opset_version=10
--enable_onnx_checker=True
```
- 参数说明:
- ${your_inference_model_dir}指的是Paddle模型所在目录.
- ${your_pdmodel_file}指的是网络结构的文件.
- ${your_pdiparams_file}指的是模型参数的文件.
- ${output_file}指的是需要导出的onnx模型.
- ${opset_version}指的是ONNX Opset,目前稳定支持9~11,默认是10.
- ${enable_onnx_checker}指的是否检查导出为ONNX模型的正确性.
更多关于参数的用法,可参考 [Paddle2ONNX官方教程](https://github.com/PaddlePaddle/Paddle2ONNX/blob/develop/README_zh.md)
**【实战】**
参考MobileNetV3的Paddle2ONNX [说明文档](../../mobilenetv3_prod/Step6/deploy/onnx_python/README.md) 中的第2.2章节
**【核验】**
执行完毕后,将产出${output_file} ONNX 模型文件,其中文件后缀为`.onnx`。
### 2.3 开发数据预处理程序
**【基本内容】**
读取指定图像,对其进行数据变换,转化为符合模型推理所需要的输入格式。
使用ONNX模型进行推理时,使用的数据预处理方法,和使用Paddle Inference进行推理时的预处理方法一样。
### 2.4 开发ONNX模型推理程序
ONNX作为开源的神经网络交换格式,得到大多数推理引擎的部署支持。在本文档中我们采用微软开源的ONNXRuntime推理引擎,进行转换后模型的正确性较验。
**【基本内容】**
初始化`ONNXRuntime`库并配置相应参数, 并进行预测
```
from onnxruntime import InferenceSession
# 加载ONNX模型
sess = InferenceSession('${your_onnx_model_name}.onnx')
# 模型预测
ort_outs = sess.run(output_names=None, input_feed={sess.get_inputs()[0].name: ${input_data})
```
**【注意事项】**
${input_data} 是预处理后的数据,作为网络的输入,数据是ndarray类型。
### 2.5 开发数据后处理程序
在完成ONNX模型进行推理后,基于不同的任务,需要对网络的输出进行后处理,这部分和使用Paddle Inference进行模型推理后的后处理方法一样。
### 2.6 验证ONNX推理结果正确性
**【基本内容】**
`ONNXRuntime`预测结果和`Paddle Inference`预测结果对比
```
import os
import time
import paddle
# 从模型代码中导入模型
from paddlevision.models import mobilenet_v3_small
# 实例化模型
model = mobilenet_v3_small('${your_paddle_model_name}.pdparams')
# 将模型设置为推理状态
model.eval()
# 对比ONNXRuntime和Paddle预测的结果
paddle_outs = model(paddle.to_tensor(${input_data}))
diff = ort_outs[0] - paddle_outs.numpy()
max_abs_diff = np.fabs(diff).max()
if max_abs_diff < 1e-05:
print("The difference of results between ONNXRuntime and Paddle looks good!")
else:
relative_diff = max_abs_diff / np.fabs(paddle_outs.numpy()).max()
if relative_diff < 1e-05:
print("The difference of results between ONNXRuntime and Paddle looks good!")
else:
print("The difference of results between ONNXRuntime and Paddle looks bad!")
print('relative_diff: ', relative_diff)
print('max_abs_diff: ', max_abs_diff)
```
**【注意事项】**
${input_data} 是预处理后的数据,和 ONNXRuntime 的输入一样。
ort_outs 是 ONNXRuntime 的输出结果
paddlevision 模块位于MobileNetV3_prod/Step6目录下
**【核验】**
执行完毕后,如果 max_abs_diff < 1e-05,那么意味着,ONNXRuntime和Paddle Inference的输出是一致的。
**【实战】**
参考MobileNetV3的Paddle2ONNX [说明文档](../../mobilenetv3_prod/Step6/deploy/onnx_python/README.md) 中的第2.3章节
## 3. FAQ
如果您在使用该文档完成Paddle模型转ONNX的过程中遇到问题,可以给在[这里](https://github.com/PaddlePaddle/Paddle2ONNX/issues)提一个ISSUE,我们会高优跟进。