【理论知识】实际部署中 onnx的简单理解

1. 定义及概述

        Open Neural Network Exchange(ONNX,开放神经网络交换)格式,是一个用于表示深度学习模型的标准,可使模型在不同框架之间进行转移。

        ONNX是一种针对机器学习所设计的开放式的文件格式,用于存储训练好的模型。定义了一个可扩展的计算图模型,以及内置运算符和标准数据类型的定义  。它使得不同的人工智能框架(如Pytorch, MXNet)可以采用相同格式存储模型数据并交互。 ONNX的规范及代码主要由微软,亚马逊 ,Facebook 和 IBM 等公司共同开发。

        目前官方支持加载ONNX模型并进行推理的深度学习框架有: Caffe2, PyTorch, MXNet,ML.NET,TensorRT 和 Microsoft CNTK,并且 TensorFlow 也非官方的支持ONNX。

支持onnx的工具也比较多,比如netron可以直接打开onnx文件,实现模型结构的可视化

【理论知识】实际部署中 onnx的简单理解_第1张图片

2. onnx与其他格式模型的转换

根据推理端需要使用的框架,再进行一次转换。

        从很多使用的角度来说,onnx承担了中间过渡的作用,开发人员首先在pytorch等通用框架进行模型训练,然后将模型导出为onnx格式;之后还需要将onnx转换为tensorrt、ncnn等支持的.engine  .bin   .param格式

        之前我在部署yolov5+deepsort过程中,就是使用pytorch->onnx->tensorrt来进行部署的,github上很多开源项目都是这样的流程。我实验室的师兄现在远程实习,需要部署在CPU上的模型也是通过onnx进行的转化。      (7条消息) [jetson浅试] yolov5+deepsort+Tensorrt C++部署(Xavier AGX)_qqsuiying的博客-CSDN博客

3. protobuf        

        onnx是通过protobuf这一序列化结构数据来存储神经网络的权重信息。

        protobuf 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化(或者说序列化)。它很适合作为数据存储或者交换格式。Protobuf协议是一个以*.proto后缀文件为基础的,这个文件描述了用户自定义的数据结构。ONNX是基于Protobuf来做数据存储和传输,那么自然onnx.proto就是ONNX格式文件了,接下来我们就分析一下ONNX格式。

4. onnx格式分析

        ONNX中最核心的部分就是onnx.proto,文件可以在github下载https://github.com/onnx/onnx/blob/master/onnx/onnx.proto)

        它定义了ONNX这个数据协议的规则和一些其它信息,在这个文件里面以message关键字开头的对象是我们需要关心的。这里列一下最核心的几个对象并解释一下它们之间的关系。

  • ModelProto
  • GraphProto
  • NodeProto
  • ValueInfoProto
  • TensorProto
  • AttributeProto

        当我们加载一个onnx文件后,我们即获得了一个ModelProto,它包含一些版本信息、生产者信息和一个最重要的GraphProto。在GraphProto里面又包含了四个repeated数组,它们分别是node(NodeProto类型),input(ValueInfoProto类型),output(ValueInfoProto类型)和initializer(TensorProto类型),其中node中存放了模型中所有的计算节点,input存放了模型的输入节点,output存放了模型中所有的输出节点,initializer存放了模型的所有权重参数。

        想要完整表述一个神经网络,既需要知道神经网络中各个节点的信息,也需要知道各节点间的拓扑关系。在onnx中,每个计算节点都需要有input和output两个数组,这两个数组都是string类型,通过input和output之间的指向关系,就可以构建出深度学习的拓扑图。(另外,GraphProto中的input不仅包含了输入节点,还包含了 模型所有的权重。例如,conv层中的w权重实体是保存在initializer汇总,那么相应的也会有一个同名的输入在input中,其背后的逻辑应该是把权重也看成模型的输入,并通过initializer中的权重实体来对这个输入做初始化,即一个赋值的过程。)

        最后,每个计算节点中还包含了一个AttributeProto数组,用来描述该节点的属性,比如Conv节点或者说卷积层的属性包含grouppadstrides等等,每一个计算节点的属性,输入输出信息都详细记录在https://github.com/onnx/onnx/blob/master/docs/Operators.md

5. onnx.helper

        现在我们知道ONNX是把一个网络的每一层或者说一个算子当成节点node,使用这些Node去构建一个Graph,即一个网络。最后将Graph和其它的生产者信息,版本信息等合并在一起生成一个Model,也即是最终的ONNX模型文件。 在构建ONNX模型的时候,https://github.com/onnx/onnx/blob/master/onnx/helper.py这个文件非常重要,我们可以利用它提供的make_nodemake_graphmake_tensor等等接口完成一个ONNX模型的构建,一个示例如下:

import onnx
from onnx import helper
from onnx import AttributeProto, TensorProto, GraphProto


# The protobuf definition can be found here:
# https://github.com/onnx/onnx/blob/master/onnx/onnx.proto


# Create one input (ValueInfoProto)
X = helper.make_tensor_value_info('X', TensorProto.FLOAT, [3, 2])
pads = helper.make_tensor_value_info('pads', TensorProto.FLOAT, [1, 4])

value = helper.make_tensor_value_info('value', AttributeProto.FLOAT, [1])


# Create one output (ValueInfoProto)
Y = helper.make_tensor_value_info('Y', TensorProto.FLOAT, [3, 4])

# Create a node (NodeProto) - This is based on Pad-11
node_def = helper.make_node(
    'Pad', # node name
    ['X', 'pads', 'value'], # inputs
    ['Y'], # outputs
    mode='constant', # attributes
)

# Create the graph (GraphProto)
graph_def = helper.make_graph(
    [node_def],
    'test-model',
    [X, pads, value],
    [Y],
)

# Create the model (ModelProto)
model_def = helper.make_model(graph_def, producer_name='onnx-example')

print('The model is:\n{}'.format(model_def))
onnx.checker.check_model(model_def)
print('The model is checked!')

这个官方示例为我们演示了如何使用onnx.helpermake_tensormake_tensor_value_infomake_attributemake_nodemake_graphmake_node等方法来完整构建了一个ONNX模型。需要注意的是在上面的例子中,输入数据是一个一维Tensor,初始维度为[2],这也是为什么经过维度为[1,4]的Pad操作之后获得的输出Tensor维度为[3,4]。另外由于Pad操作是没有带任何权重信息的,所以当你打印ONNX模型时,ModelProtoGraphProto是没有initializer这个属性的。

6. onnx-simplifier

        引用大佬的一个经典例子,通过pytorch转onnx中reshape算子的问题,来说明onnx-simplifier的处理过程。

        详细可参考ONNX学习笔记 - 知乎 (zhihu.com)中的0x5部分

参考链接

(7条消息) ONNX简介_知更鸟k的博客-CSDN博客_onnx

ONNX学习 - 知乎 (zhihu.com)

ONNX学习笔记 - 知乎 (zhihu.com)及其扩展参考

  • 【1】使用ONNX部署深度学习和传统机器学习模型 - 知乎
  • 【2】https://oldpan.me/archives/talk-about-onnx
  • 【3】https://blog.csdn.net/chengzi_comm/article/details/53199278
  • 【4】https://www.jianshu.com/p/a24c88c0526a
  • 【5】https://bindog.github.io/blog/2020/03/13/deep-learning-model-convert-and-depoly/
  • 【6】 https://github.com/daquexian/onnx-simplifier

你可能感兴趣的:(深度学习实际部署,深度学习,神经网络,cnn,计算机视觉)