• 使用卷积神经网络进行图像分类
  • CIFAR-100数据集上基于Vision Transformer 实现图片分类
  • GAMMA比赛多模态眼底图像数据集下基于EfficientNet和ResNet构造fundus_img和oct_img的分类模型
  • MosMedData: 新冠肺炎胸部 CT扫描数据集上基于3D-CNN实现二分类
  • 基于图片相似度的图片搜索
  • 基于U-Net卷积神经网络实现宠物图像分割
  • 通过OCR实现验证码识别
  • 通过Sub-Pixel实现图像超分辨率
  • 人脸关键点检测
  • 点云处理:实现PointNet点云分类
  • 点云处理:实现PointNet点云分割
  • 自然语言处理
  • 用N-Gram模型在莎士比亚文集中训练word embedding
  • IMDB 数据集使用BOW网络的文本分类
  • 使用预训练的词向量完成文本分类任务
  • 使用注意力机制的LSTM的机器翻译
  • 基于Transformer实现英语到西班牙语的翻译任务
  • 使用序列到序列模型完成数字加法
  • 使用协同过滤实现电影推荐
  • 强化学习——Actor Critic Method
  • 强化学习——Advantage Actor-Critic(A2C)
  • 强化学习——Deep Deterministic Policy Gradient (DDPG)
  • 强化学习——DQN玩合成大西瓜
  • 用飞桨框架2.0造一个会下五子棋的AI模型
  • 通过AutoEncoder实现时序数据异常检测
  • Jena Climate时间序列数据集上使用LSTM进行温度的预报
  • 证券数据集下使用LSTM模型预测A股走势
  • 使用动转静完成以图搜图
  • 生成式对抗网络
  • 图像风格迁移模型-CycleGAN
  • 通过DCGAN实现人脸图像生成
  • MNIST数据集下用Paddle框架的动态图模式玩耍经典对抗生成网络(GAN)
  • 城市街景分割数据集下使用对抗网络Pix2Pix根据掩码生成街景
  • API 文档
  • 代码贡献流程
  • 新增 API 开发&提交流程
  • 贡献前阅读
  • 开发 API Python 端
  • 开发 C++ 算子
  • API 设计和命名规范
  • API 文档书写规范
  • API 单测开发及验收规范
  • 算子性能优化 提交流程
  • 算子性能优化 方法介绍
  • 算子性能优化 验收规范
  • Kernel Primitive API
  • API 介绍
  • API 介绍 - IO
  • API 介绍 - Compute
  • API 介绍 - OpFunc
  • API 示例
  • 示例 - ElementwiseAdd
  • 示例 - Reduce
  • 示例 - Model
  • 算子数据类型扩展 提交流程
  • 算子数据类型扩展 验收规范
  • 低精度算子开发贡献指南
  • 低精度算子支持开发规范
  • 低精度算子单测开发规范
  • 曙光开发指南
  • 曙光智算平台-Paddle 源码编译和单测执行
  • Paddle 适配 C86 加速卡详解
  • Paddle 框架下 ROCm(HIP)算子单测修复指导
  • 硬件接入飞桨后端指南
  • 硬件接入飞桨后端方案介绍
  • 训练硬件 Custom Device 接入方案介绍
  • 自定义 Runtime
  • Device 接口
  • Memory 接口
  • Stream 接口
  • Event 接口
  • 集合通讯接口
  • Profiler 接口
  • 自定义 Kernel
  • Kernel 函数声明
  • Kernel 实现接口
  • Context API
  • Tensor API
  • Exception API
  • Kernel 注册接口
  • 新硬件接入示例
  • 文档贡献指南
  • 规范和参考信息
  • 报错信息文案书写规范
  • 代码风格检查指南
  • Paddle CI 测试详解
  • 常见问题与解答
  • 2.0 升级常见问题
  • 安装常见问题
  • 数据及其加载常见问题
  • 组网、训练、评估常见问题
  • 模型保存常见问题
  • 参数调整常见问题
  • 分布式训练常见问题
  • 其他常见问题
  • 2.4.2 Release Note
  • 一、ONNX 简介

    开放神经网络交换(Open Neural Network Exchange,简称 ONNX),是一种针对机器学习所设计的开放式的文件格式,用于存储训练好的模型。借助它支持不同的人工智能框架(如 Pytorch、MXNet)采用相同格式存储模型数据并交互。

    没有 ONNX 模型之前,采用各个框架训练的模型只能通过特定的转换工具进行转换。有了 ONNX 协议后,无论使用何种框架训练模型,训练完毕后都可以将模型转换为 ONNX 这种统一的格式进行存储。这就大大方便了算法及模型在不同框架之间的迁移。

    目前官方支持加载 ONNX 模型并进行推理的深度学习框架,除飞桨外,还有 PyTorch、MXNet、Caffe2、ML.NET、TensorRT 和 Microsoft CNTK 等主流框架都对 ONNX 有着不同程度的支持;并且 TensorFlow 也非官方的支持 ONNX。除深度学习框架外,大多推理引擎或者国产硬件,比如如 RK、地平线、鲲云等也都支持加载 ONNX 模型进行推理,如果需要在这类硬件上部署,可通过 Paddle2ONNX 将飞桨模型导出成 ONNX 后进行部署。

    二、Paddle2ONNX 安装

    Paddle2ONNX 作为飞桨提供的模型转换工具,可以将飞桨模型转换为 ONNX 格式, Paddle2ONNX 的安装非常简单,只需要输入以下命令就可以完成 Paddle2ONNX 的安装。

    python -m pip install paddle2onnx
            

    三、获取 Paddle2ONNX 模型库

    Paddle2ONNX 目前提供了包括图像分类、图像分割、目标检测、文字识别四个类别的模型和部署示例代码,供开发者进行参考使用,可以点击链接获取。其他更多的飞桨官方模型套件的各类常用模型,可以到对应的官方 Repo 下进行下载,然后再进行转换。

    四、飞桨转 ONNX 教程

    在本教程中,我们将描述如何将飞桨模型转换为 ONNX 格式,然后使用 ONNXRuntime 运行它。具体操作分以下两种场景:

  • 如果使用飞桨训练模型,并将其导出为 ONNX 格式,请参考 4.1 节导出为 ONNX 模型。

  • 如果是从 PaddleOCR、PaddleClas 或 PaddleHub 等 Repo 中下载的部署模型,或者是通过飞桨训练好并保存的部署模型,则参考 4.2 节转换为 ONNX 模型。

  • 4.1 飞桨训练模型导出为 ONNX 模型

    本小节以 MNIST 手写数字识别网络作为例子,展示如何将训练模型导出为 ONNX 模型。

    『手写数字识别任务』比较简单,普通的神经网络就能达到很高的精度,以下代码直接来自前面的手写数字识别任务,无需修改。

    import paddle
    from paddle.vision.transforms import Normalize
    transform = Normalize(mean=[127.5], std=[127.5], data_format='CHW')
    # 下载数据集并初始化 DataSet
    train_dataset = paddle.vision.datasets.MNIST(mode='train', transform=transform)
    test_dataset = paddle.vision.datasets.MNIST(mode='test', transform=transform)
    # 模型组网并初始化网络
    lenet = paddle.vision.models.LeNet(num_classes=10)
    model = paddle.Model(lenet)
    # 模型训练的配置准备,准备损失函数,优化器和评价指标
    model.prepare(paddle.optimizer.Adam(parameters=model.parameters()),
                  paddle.nn.CrossEntropyLoss(),
                  paddle.metric.Accuracy())
    # 模型训练
    model.fit(train_dataset, epochs=5, batch_size=64, verbose=1)
    # 模型评估
    model.evaluate(test_dataset, batch_size=64, verbose=1)
             

    完成以上代码,就可以训练这个模型。请注意,此模型未完全训练以获得良好的准确性,此处仅用于演示目的。 使用飞桨完成模型训练之后,要导出模型,需要调用 paddle.onnx.export 接口,在导出模型时我们需要使用 paddle.static.InputSpec API 指定输入的 shape,如果输入中某一维为动态的,可以将该维指定为 None,在本例中我们设置第一维为动态,表示推理过程中该维可变。

    使用飞桨完成模型训练之后,转换成 ONNX 格式只需要调用 paddle.onnx.export 接口,便会在指定的路径下生成 ONNX 模型。关于 paddle.onnx.export 接口更详细的使用方法,请参考 API 文档 。 添加如下脚本,可以在 onnx.save 下生成 lenet.onnx 模型。

    # export to ONNX
    save_path = 'onnx.save/lenet' # 需要保存的路径
    x_spec = paddle.static.InputSpec([None, 1, 28, 28], 'float32', 'x') # 为模型指定输入的形状和数据类型,支持持 Tensor 或 InputSpec ,InputSpec 支持动态的 shape。
    paddle.onnx.export(lenet, save_path, input_spec=[x_spec], opset_version=11)
             

    4.2 飞桨部署模型转为 ONNX 模型

    如果模型是从 PaddleOCR、PaddleClas 或 PaddleHub 等 Repo 中下载的部署模型,或者将飞桨模型保存为部署模型,均可以使用 Paddle2ONNX 的命令行进行转换。

    本小节以 PaddleClas 提供的 MobileNetV3 分类模型作为例子,演示转换的过程。

    1.首先可以使用如下命令下载保存下来的飞桨模型并解压,如果你已经有下载好的飞桨部署模型,则可以跳过此步骤。解压成功后在 mobilenetv3 文件夹下有飞桨的模型和参数文件。

    wget https://bj.bcebos.com/paddle2onnx/model_zoo/mobilenetv3.tar.gz
    tar xvf mobilenetv3.tar.gz
             

    2.接下来可以使用 Paddle2ONNX 命令行工具将 MobileNetV3 转换为 ONNX 格式。转换成功后会生成 model.onnx 模型。命令相关的说明请参考:Paddle2ONNX 命令行参数说明

    paddle2onnx --model_dir mobilenetv3 --model_filename inference.pdmodel --params_filename inference.pdiparams --save_file model.onnx --enable_dev_version True --opset_version 13 --enable_onnx_checker True
              

    (1) 检查 ONNX 模型的有效性

    可以使用如下脚本验证导出的 ONNX 模型是否合理,包括检查模型的版本、图的结构、节点及其输入和输出。如下脚本的输出为 None 则表示模型转换正确。

    # 导入 ONNX 库
    import onnx
    # 载入 ONNX 模型
    onnx_model = onnx.load("model.onnx")
    # 使用 ONNX 库检查 ONNX 模型是否合理
    check = onnx.checker.check_model(onnx_model)
    # 打印检查结果
    print('check: ', check)
    # 随机生成输入,用于验证飞桨和 ONNX 的推理结果是否一致
    x = np.random.random((1, 3, 224, 224)).astype('float32')
    # predict by ONNXRuntime
    ort_sess = onnxruntime.InferenceSession("model.onnx")
    ort_inputs = {ort_sess.get_inputs()[0].name: x}
    ort_outs = ort_sess.run(None, ort_inputs)
    print("Exported model has been predicted by ONNXRuntime!")
    # predict by Paddle
    model = paddle.jit.load("mobilenetv3/inference")
    model.eval()
    paddle_input = paddle.to_tensor(x)
    paddle_outs = model(paddle_input)
    print("Original model has been predicted by Paddle!")
    # compare ONNXRuntime and Paddle results
    np.testing.assert_allclose(ort_outs[0], paddle_outs.numpy(), rtol=1.0, atol=1e-05)
    print("The difference of results between ONNXRuntime and Paddle looks good!")
              

    运行结果如下,可以看到飞桨模型和导出的 ONNX 模型在输入相同时计算结果一致:

    ONNXRuntime 的 API 和相关文档请查阅:ONNXRuntime 文档

    4.4 使用 ONNX 模型进行推理

    导出的 ONNX 模型可以用支持 ONNX 模型的推理引擎进行推理,比如 ONNXRuntime 或 TensorRT 等。本节将用 ONNXRuntime 和 4.2 节导出的 ONNX 模型来进行展示如何使用 ONNXRuntime 对 ONNX 模型进行推理预测。

    为了使用 ONNXRuntime 运行模型,需要使用所选配置参数为模型创建一个推理会话(这里我们使用默认配置)。可以使用如下命令,安装依赖、下载推理脚本和测试图片。

    # 安装 ONNXRuntime 用于 ONNX 模型的推理
    pythom -m pip install onnxruntime
    # 下载推理用的 infer.py 脚本
    wget https://raw.githubusercontent.com/PaddlePaddle/Paddle2ONNX/develop/model_zoo/classification/infer.py
    # 下载测试用的图片
    wget https://github.com/PaddlePaddle/Paddle2ONNX/raw/develop/model_zoo/classification/images/ILSVRC2012_val_00000010.jpeg
             

    以下脚本是 ONNX Runtme 使用 ONNX 模型推理的必要步骤,只需将前后处理改为实际应用场景下的逻辑便可使用,4.1 中的手写数字识别模型导出为 ONNX 格式之后,只需将图像前后处理逻辑加入进来便可用于部署。

    # 导入 ONNX 包
    import onnxruntime
    # 加载 ONNX 模型生成推理用 sess
    sess = onnxruntime.InferenceSession("model.onnx")
    # 数据预处理
    data = preprocess(image_path)
    # 使用 ONNXRuntime 推理
    result, = sess.run(None, {"inputs": data})
    # 推理结果后处理
    postprocess(result)
             

    使用如下命令运行脚本,使用 ONNXRuntime 推理。

    # 使用 ONNX 模型和 ONNXRuntime 推理,对图片进行分类
    python infer.py --model model.onnx --image_path images/ILSVRC2012_val_00000010.jpeg
             

    输入图片和最终的推理结果如下,可以看到准确的预测出输入的图片是一只贵宾犬。

    # 分类出的前 5 个类别
    TopK Indices:  [265 153 850 332 283]
    # 前 5 个类别的置信度
    TopK Scores:  [0.4966848  0.25181034 0.15389322 0.01496286 0.01342606]
             

    备注:各类别 id 与明文标签请参考ImageNet 标签

    五、注意事项

  • 目前 Paddle2ONNX 已经支持 170 多个飞桨算子,多数飞桨的模型都可顺利导出为 ONNX 格式,如果在转换中遇到不支持的 OP,请到 Paddle2ONNX Repo 下提 Issue,我们都会尽快支持。

  • PaddleSlim 量化模型导出 ONNX,参考量化导出说明文档:量化模型导出说明,如在导出 ONNX 过程遇到问题,欢迎通过Paddle2ONNX开源项目 Issue 方式反馈。

  • 使用 ONNXRuntime 验证转换模型, 请注意安装最新版本,最低要求 1.10.0 版本。查询 ONNXRuntime 版本可以使用如下命令:

  • python -m pip show onnxruntime
            

    该命令的输出如下,Version 则为 ONNXRuntime 的版本:

  • 模型转换过程会将飞桨的算子逐一转换为 ONNX 的算子。由于 ONNX 的算子随版本迭代不断升级,不同的推理引擎对 ONNX 算子版本支持也不完全一致,因此,使用 Paddle2ONNX 对飞桨模型进行转换时,需要指定 ONNX 的算子版本,此参数应根据待部署的推理引擎进行设置,在转换中可以使用 Paddle2ONNX 的 opset_version 选项进行指定,具体设置方法请参见参数选项

  •