添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

ONNX是开放式神经网络(Open Neural Network Exchange)的简称,主要由微软和合作伙伴社区创建和维护。很多深度学习训练框架(如Tensorflow, PyTorch, Scikit-learn, MXNet等)的模型都可以导出或转换为标准的ONNX格式,采用ONNX格式作为统一的界面,各种嵌入式平台就可以只需要解析ONNX格式的模型而不用支持多种多样的训练框架,本文主要介绍如何通过代码或JSON文件的形式来构造一个ONNX单算子模型或者整个graph,以及使用ONNX Runtime进行推理得到算子或模型的计算结果。

一. ONNX文件格式

ONNX文件是基于Protobuf进行序列化。了解Protobuf协议的同学应该知道,Protobuf都会有一个*.proto的文件定义协议,ONNX的该协议定义在 https://github.com/onnx/onnx/blob/master/onnx/onnx.proto3 文件中。

从onnx.proto3协议中我们需要重点知道的数据结构如下:

  • ModelProto:模型的定义,包含版本信息,生产者和GraphProto。
  • GraphProto: 包含很多重复的NodeProto, initializer, ValueInfoProto等,这些元素共同构成一个计算图,在GraphProto中,这些元素都是以列表的方式存储,连接关系是通过Node之间的输入输出进行表达的。
  • NodeProto: onnx的计算图是一个有向无环图(DAG),NodeProto定义算子类型,节点的输入输出,还包含属性。
  • ValueInforProto: 定义输入输出这类变量的类型。
  • TensorProto: 序列化的权重数据,包含数据的数据类型,shape等。
  • AttributeProto: 具有名字的属性,可以存储基本的数据类型(int, float, string, vector等)也可以存储onnx定义的数据结构(TENSOR, GRAPH等)。

二. Python API

2.1 搭建ONNX模型

ONNX是用DAG来描述网络结构的,也就是一个网络(Graph)由节点(Node)和边(Tensor)组成,ONNX提供的helper类中有很多API可以用来构建一个ONNX网络模型,比如make_node, make_graph, make_tensor等,下面是一个单个Conv2d的网络构造示例:

import onnx
from onnx import helper
from onnx import TensorProto
import numpy as np
weight = np.random.randn(36)
X = helper.make_tensor_value_info('X', TensorProto.FLOAT, [1, 2, 4, 4])
W = helper.make_tensor('W', TensorProto.FLOAT, [2, 2, 3, 3], weight)
B = helper.make_tensor('B', TensorProto.FLOAT, [2], [1.0, 2.0])
Y = helper.make_tensor_value_info('Y', TensorProto.FLOAT, [1, 2, 2, 2])
node_def = helper.make_node(
    'Conv', # node name
    ['X', 'W', 'B'],
    ['Y'], # outputs
    # attributes
    strides=[2,2],
graph_def = helper.make_graph(
    [node_def],
    'test_conv_mode',
    [X], # graph inputs
    [Y], # graph outputs
    initializer=[W, B],
mode_def = helper.make_model(graph_def, producer_name='onnx-example')
onnx.checker.check_model(mode_def)
onnx.save(mode_def, "./Conv.onnx")

搭建的这个Conv算子模型使用netron可视化如下图所示:

这个示例演示了如何使用helper的make_tensor_value_info, make_mode, make_graph, make_model等方法来搭建一个onnx模型。

相比于PyTorch或其它框架,这些API看起来仍然显得比较繁琐,一般我们也不会用ONNX来搭建一个大型的网络模型,而是通过其它框架转换得到一个ONNX模型。

2.2 Shape Inference

很多时候我们从pytorch, tensorflow或其他框架转换过来的onnx模型中间节点并没有shape信息,如下图所示:

我们经常希望能直接看到网络中某些node的shape信息,shape_inference模块可以推导出所有node的shape信息,这样可视化模型时将会更友好:

import onnx
from onnx import shape_inference
onnx_model = onnx.load("./test_data/mobilenetv2-1.0.onnx")
onnx_model = shape_inference.infer_shapes(onnx_model)
onnx.save(onnx_model, "./test_data/mobilenetv2-1.0_shaped.onnx")

可视化经过shape_inference之后的模型如下图:

2.3 ONNX Optimizer

ONNX的optimizer模块提供部分图优化的功能,例如最常用的:fuse_bn_into_conv,fuse_pad_into_conv等等。

查看onnx支持的优化方法:

from onnx import optimizer
all_passes = optimizer.get_available_passes()
print("Available optimization passes:")
for p in all_passes:
    print(p)
print()

应用图优化到onnx模型上进行变换:

passes = ['fuse_bn_into_conv']
# Apply the optimization on the original model
optimized_model = optimizer.optimize(onnx_model, passes)

将mobile net v2应用fuse_bn_into_conv之后,BatchNormalization的参数合并到了Conv的weight和bias参数中,如下图所示:

三. ONNX Runtime计算ONNX模型

onnx本身只是一个协议,定义算子与模型结构等,不涉及具体的计算。onnx runtime是类似JVM一样将ONNX格式的模型运行起来的解释器,包括对模型的解析、图优化、后端运行等。

安装onnx runtime:

python3 -m pip install onnxruntime
import onnx
import onnxruntime as ort
import numpy as np
import cv2
def preprocess(img_data):
    mean_vec = np.array([0.485, 0.456, 0.406])
    stddev_vec = np.array([0.229, 0.224, 0.225])
    norm_img_data = np.zeros(img_data.shape).astype('float32')
    for i in range(img_data.shape[0]):
         # for each pixel in each channel, divide the value by 255 to get value between [0, 1] and then normalize
        norm_img_data[i,:,:] = (img_data[i,:,:]/255 - mean_vec[i]) / stddev_vec[i]
    return norm_img_data
img = cv2.imread("test_data/dog.jpeg")
img = cv2.resize(img, (224,224), interpolation=cv2.INTER_AREA)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
input_data = np.transpose(img, (2, 0, 1))
input_data = preprocess(input_data)
input_data = input_data.reshape([1, 3, 224, 224])
sess = ort.InferenceSession("test_data/mobilenetv2-1.0.onnx")
input_name = sess.get_inputs()[0].name
result = sess.run([], {input_name: input_data})
result = np.reshape(result, [1, -1])
index = np.argmax(result)
print("max index:", index)
使用 ONNX 导出和 运行 模型 本教程系列将涵盖txtai的主要用例,这是一个 AI 驱动的语义搜索平台。该系列的每章都有相关代码,可也可以在colab 中使用。 colab 地址 https://dev.to/neuml/tutorial-series-on-txtai-ibg ONNX 运行 时为机器学习 模型 提供了一种通用的序列化 格式 。 ONNX 支持多种不同的平台/语言,并具有有助于减少推理时间的内置功能。PyTorch 对将 Torch 模型 导出到 ONNX 具有强大的支持。这使得可以将 Hugging Face Transformer 和/或其他下游 模型 直接导出到 ONNX 。 ONNX 开辟了一条使用多种语言和平台进行直接推理的途径。例如, 模型 可以直接在 Android 上 运行 以限制发送到第三方服务的数据。 ONNX 是一个令人兴奋的发展,充满希望。 使用 C++ 的 OpenCV 接口调用 ONNX 格式 的 PyTorch 深度学习 模型 进行预测(Windows, C++, PyTorch, ONNX , Visual Studio, OpenCV) onnx 的基本操作一、 onnx 的配置环境二、获取 onnx 模型 的输出层三、获取中节点输出数据四、 onnx 前向InferenceSession的使用1. 创建实例,源码分析2. 模型 推理run,源码分析五、遇到的一些问题 最近在对 模型 进行量化时候, 模型 格式 转变为 onnx 模型 了,因此需要对 onnx 进行加载、 运行 以及量化(权重/输入/输出)。故,对 onnx 模型 的相关操作进行简单的学习,并写下了这边博客,若有错误请指出,谢谢。 一、 onnx 的配置环境 onnx 的环境主要包含两个包 onnx 和 onnx runtime,我们 ONNX 提供了一个C ++库,可用于在 ONNX 模型 上执行任意优化,以及越来越多的预打包优化过程列表。 主要动机是在许多 ONNX 后端实现之间共享工作。 并非所有可能的优化都可以直接在 ONNX 图上实现-有些需要附加的特定于后端的信息-但是很多可以,我们的目标是与 ONNX 一起提供所有此类传递,以便可以通过单个函数调用重复使用。 您可能有兴趣调用提供的通行证,或实施新的通行证(或两者都有)。 您可以从PyPI安装 onnx optimizer: pip3 install onnx optimizer 请注意,如果遇到问题,您可能需要先升级点子: pip3 install -U pip 如果要从源代码 构建 : git clone --recursive https://github.com/ onnx /optimizer onnx optimizer cd onnx optim 文章目录 ONNX 介绍 ONNX 与Protobuf ONNX 数据结构 ONNX 模型 解析 ONNX 模型 构建 及推理 ONNX 模型 修改节点删除:节点修改: ONNX 介绍 ONNX 是一种针对机器学习所设计的开放式的文件 格式 ,用于存储训练好的 模型 。它使得不同的人工智能框架(如Pytorch, MXNet)可以采用相同 格式 存储 模型 数据。简而言之, ONNX 是一种便于在各个主流深度学习框架中迁移 模型 的中间表达 格式 。 ONNX 与Protobuf ONNX 采用序列化数据结构协议protobuf来存储 模型 信息。我们可以通过protobuf 为什么要说 ONNX , ONNX 又是个什么东西,经常要部署神经网络应用的童鞋们可能会 ONNX 会比较熟悉,我们可能会在某一任务中将Pytorch或者TensorFlow 模型 转化为 ONNX 模型 ( ONNX 模型 一般用于中间部署阶段),然后再拿转化后的 ONNX 模型 进而转化为我们使用不同框架部署需要的类型。 典型的几个线路: Pytorch -> ONNX -> TensorRT Pytorch -> ONNX -> TVM TF – onnx – ncnn 模型 部署入门系列教程持续更新啦,在前两期教程中,我们学习了PyTorch 模型 转 ONNX 模型 的方法,了解了如何在原生算子表达能力不足时,为 PyTorch 或 ONNX 自定义算子。一直以来,我们都是通过 PyTorch 来导出 ONNX 模型 的,基本没有单独探究过 ONNX 模型 的构造知识。 不知道大家会不会有这样一些疑问: ONNX 模型 在底层是用什么 格式 存储的?如何不依赖深度学习框架,只用 ONNX 的 API 来构造一个 ONNX 模型 ?如果没有源代码,只有一个 ONNX 模型 ,该如何对这个 模型 .