1. 【pytorch转onnx】YOLOv3网络pt->onnx
在另外一篇博客中已经写了,只是在旭日3开发板上实操时用的是另外一个程序,故在此重新记录一下,详细转换过程参考如下链接
其中 from nets.yolo import YoloBody 可见 参考链接
2. Matlab能导出onnx格式吗
Matlab能导出onnx格式。
首先打开电脑上的“matlab”软件,此处以下图中的代码为例,绘制出一个三维图像。meshgrid函数用于生成网格点。可以使用自己喜欢的例子来制作动画。
在matlab工作输入:% 11是你保存时的文件名,需要加单引号,否则打不开。特别注意最好将这个文件复制到matlab工作文件夹。
如果你不知道是哪个文件夹,可以看看matlab左边的窗口,或者按下组合键Ctrl+O,或者打开菜单栏上面的Home->open。
优势特点:
(1) 高效的数值计算及符号计算功能,能使用户从繁杂的数学运算分析中解脱出来。
(2) 具有完备的图形处理功能,实现计算结果和编程的可视化。
(3) 友好的用户界面及接近数学表达式的自然化语言,使学者易于学习和掌握。
(4) 功能丰富的应用工具箱(如信号处理工具箱、通信工具箱等) ,为用户提供了大量方便实用的处理工具。
3. ONNX简介
Open Neural Network Exchange(ONNX,开放神经网络交换)格式,是一个用于表示深度学习模型的标准,可使模型在不同框架之间进行转移。
假设一个场景:现在某组织因为主要开发用TensorFlow为基础的框架,现在有一个深度算法,需要将其部署在移动设备上,以观测变现。传统地我们需要用caffe2重新将模型写好,然后再训练参数;试想下这将是一个多么耗时耗力的过程。
此时,ONNX便应运而生,Caffe2,PyTorch,Microsoft Cognitive Toolkit,Apache MXNet等主流框架都对ONNX有着不同程度的支持。这就便于了我们的算法及模型在不同的框架之间的迁移。
开放式神经网络交换(ONNX)是迈向开放式生态系统的第一步,它使AI开发人员能够随着项目的发展选择合适的工具。 ONNX为AI模型提供开源格式。 它定义了可扩展的计算图模型,以及内置运算符和标准数据类型的定义。 最初的ONNX专注于推理(评估)所需的功能。 ONNX解释计算图的可移植,它使用graph的序列化格式。 它不一定是框架选择在内部使用和操作计算的形式。 例如,如果在优化过程中操作更有效,则实现可以在存储器中以不同方式表示模型。
ONNX是一个开放式规范,由以下组件组成:
可扩展计算图模型的定义
标准数据类型的定义
内置运算符的定义
4. ONNX一个沟通各大AI框架的桥梁
ONNX全称Open Neural Network Exchange,是微软设计的一个开放式深度学习神经网络模型的格式。旨在通过一个统一的模型格式标准,建立一个强大的人工智能生态。
深度神经网络的实现是通过数据流图实现的,数据(张量等)从输入,流过一个个集选节点,最终在输出结点得到推理结果。不同的框架实现数据流图的的方式不尽相同,有的使用静态图,有的在运行的过程中动态创建。但是不管哪种方式,最终都会得到一个神经网络模型的结构图以及权重。通常,神经网络模型的结构、权重等信息不会一直在内存里,通常需要将它们保存到文件中,用于部署、转换等。而每一种框架都有他们自己的一套专有的模型表示方法,拥有自己的一套标准去操作、运行他们自己的模型。由于AI 研究正在迅猛发展当中,每种框架都有自己的侧重点,比如有的框架特别适合于做研究,能够快速的搭建验证模型;而有的框架则最特定硬件做了大量性能优化,特别适合生产部署。
这时候,一个通用的模型格式标准应运而生,它就是ONNX。有了这样一个统一的模型格式标准,你就可以使用能够快速的框架去验证你的模型,然后将模型导出到ONNX格式,再用有特殊优化的推理引擎进行推理或者转换到可以在移动端进行推理的特殊格式。
ONNX还有另一个变种,ONNX-ML,它额外增加了一些传统的标准机器学习操作。
ONNX是一个开放的标准,这个标准主要有以下三部分组成:
版本号有两种表示方法:简单数字表示和语义表示,用8个字节存储版本信息。
简单数字表示全部字节用于表示一个数,表现形式为XXX,如 0x0000000000000001 表示数字1;语义表示则将这八个字节分开,最高位两个字节表示主版本号,次高位两个字节表示此版本好,剩下四个字节表示补丁、编译等版本号,最终的表现形式为MAJOR.MINOR.PATCH,例如 0x0001000200000003 表示主版本号为1,此版本号为2,补丁版本号等为3。两种表示方法的区分方法是查看最高四个字节内容,如果最高四个字节为0,则使用的是简单数字表示;如果最高四个字节不为零,则使用的是语义表示。例如 0x0000000000000001 最高四个字节为0,所以表示这个版本号是用简单数字表示;而 0x000000010000000 最高四个字节不为0,则表示这是语义版本号。
值得注意的是,ONNX标准中规定,IR和OP的版本号必须用简单数字来表示,版本数值单调递增,而对于模型版本,并未作出规定,可以随意二选一。
处于模型结构顶层的是一个被称为Model的结构,它的主要目的是将一个包含模型所有执行元素的图和它的元数据关联起来。元数据可以在模型被读取的时候告诉读取方一些重要信息,比如版本、执行该模型所需要的操作集(Operators Set)等信息,读取方根据这些信息决定下一步是继续执行该模型还是选择报错等操作。另外,有些工具,例如模型查看工具等可以根据元数据告诉人们模型的信息和模型的作用等。Model的组成结构如下:
每个Model都必须指定它所属机构的域名,使用类似Java包结构的反向域名表示。此外,Model的 metadata_props 字段可以用于定义其他额外的元数据信息,例如下表定义了一些额外的元数据属性:
每个模型必须明确的指出它所以来的操作集,操作集定义了可用的操作以及他们的版本。模型通过他们的域定义了需要导入的操作集,如果没有特别指定,模型将默认导入默认的ONNX操作集。
操作集的属性如下:
图(Graph)中的任何一个操作(Operator)都必须是在模型导入了的操作集中有明确声明了的。
操作的属性如下:
图用于表示一个计算过程,它由元数据字段、模型参数以及计算结点三部分组成。计算结点按照一定拓扑结构组成了一个有向无环图,每个结点表示一个操作。每个结点可以有0到多个输入以及至少一个输出。
图的属性如下:
计算节点由结点名字、这个结点的操作的名字、输入的名字、输出的名字以及一系列属性组成。结点的输入输出和操作的输入输出通过位置相关联,例如第一个输入是上一个结点的输出,第二个输入是权重,第三个输入是偏置等,结点属性名字和操作属性通过名字相关联。
结点属性如下:
ONNX有两个变种:ONNX和ONNX-ML。ONNX只识别张量,ONNX-ML除了张量还能识别序列以及字典。
总的来说,ONNX就是定义了一套标准,这套标准使得不同机器学习框架的数据流图有了一个统一的表示。
它定义了如何将一个内存的模型序列化到磁盘,也定义了如何去读取这个序列化的模型进入内存。
[1] Open Neural Network Exchange - ONNX
5. Pytorch导出ONNX踩坑指南
相对与ONNX模型,Pytorch模型经常较为松散,API的限制也往往较为宽松。因此,在导出的过程中,不可避免地会遇到导出失败的问题。可以预见到,这块API可能在不久的将来会发生变化。
ONNX导出的基本操作比较简单。官网上的例子是:
可惜真要这么容易就好了
支持Batching需要制定Dynamic Axes,即可变的维度。
案例:
keep_initializers_as_inputs 这个参数是False的情况下,在Caffe2中报错:IndexError: _Map_base::at. 参考 https://github.com/onnx/onnx/issues/2458
问题比较复杂。貌似tensorflow也有类似问题。导出时添加参数do_constant_folding=True或许可以解决。
参考 https://github.com/NVIDIA/triton-inference-server/issues/1080
定长list会导出为一个tuple
Pytorch 1.4,ONNX 9不支持变长List的导出。之后的Pytorch版本有支持,需要更高版本的ONNX
Pytorch中,Expand未改动的dim可以指定为-1,导出到ONNX中时,需要手动指定每个dim的值。如:
Pytorch中,Squeeze一个不为1维的dim不会有任何效果。ONNX会报错
6. ONNX 开始
给出些 ONNX 模型使用的示例方法。
此为修改模型的。如果要修改某节点的,见参考 onnx_cut.py 的 _onnx_specify_shapes() 。
指明模型输入维度后,可自动推理后续节点的维度。
辅助找出指定名称的图属性。
辅助找出指定输入名称的节点列表。输出同样。
辅助找出图某属性所在列表位置。
辅助找出某区间的节点字典。
替换或修改某个节点的过程。
模型运行推理,得到输出的过程。