关于机器学习:如何将MindSpore模型转ONNX格式并使用OnnxRuntime推理全流程开发指导

1次阅读

共计 14778 个字符,预计需要花费 37 分钟才能阅读完成。

前言 1 本次 Onnx 模型推理工作不须要具体读原论文和源码,只须要分明模型网络结构即可。2 咱们只用找到须要映射的算子就能够开始开发,本文也会按照以下流程进行解说,残缺讲述本次 Onnx 模型推理工作的开发流程:
.png)
3 不须要开发的同学:通过模型导出及算子剖析后,如果发现所有算子都曾经实现,请间接从第五章 - 编译导出开始浏览。4 须要开发的同学:通过模型导出及算子剖析后,如果发现有算子未实现,可浏览此文档第四章 - 算子映射,此章节将在用 Pad 算子来介绍具体介绍开发流程中最罕用的办法和接口,心愿大家能急躁看完,这样就能够分明整个开发流程。5 此文档也有网页版:https://bbs.huaweicloud.com/b…,大家违心的话能够反对一下,刷一刷浏览量。6 如有谬误,欢送修改和反馈罕用网址 1 MindSpore 官网装置网址 2 MindSpore 官网 Model 仓库 3 MindSpore 官网模型 checkpoint 下载网址 4 MindSpore 官网模型转换教程 5 MindSpore 官网算子查问网址 6 Onnx 算子查问库 7 CNN+CTC ONNX 导出 onnx_exporter.cc 文件 PR8 CNN+CTC ONNX 导出脚本 + 推理脚本 PR9 如何将 MindSpore 模型转 ONNX 格局并应用 OnnxRuntime 推理 — 全流程领导博客整体流程一、环境配置二、MindSpore IR 导出三、算子剖析四、算子映射五、编译导出六、推理测试七、总结一、环境配置 1. 连贯服务器(1)ssh 跳转连贯应用服务器链接软件在同一个连贯会话中,顺次间断输出以下命令:① 跳转服务器 1:ssh xxx@xxx.xxx.xxx.xxx passwd: xxxxxxx
.png)
② 跳转服务器 2:ssh xxx@xxx.xxx.xxx.xxx passwd: xxxxxxx
.png)
③ Onnx 服务器:ssh xxx@xxx.xxx.xxx.xxx passwd: xxxxxxx
.png)
输出 ls,达到此界面即为连贯胜利!(2)VPN 连贯办法① 点击右下角网络(WiFi 那个标识),点击网络和 Internet 设置。
.png)
② 点击 VPN,增加 VPN(我曾经设置过一个,请疏忽)。
.png)
③ 设置 GPU 算子开发网络连接,输出如下用户名和明码,点击保留。VPN 信息:服务器地址:xxx.xxx.xxx.xxx 用户名:xxx 明码:xxxxxxxxxxxxx
.png)
④ 关上控制面板 - 网络连接,并抉择刚创立的 vpn 右键属性
.png)
⑤ 选择网络 -IPV4- 属性 - 高级,勾销勾选“在近程网络上应用默认网关”
.png)
 
.png)

.png)
⑥ 抉择平安,抉择容许应用这些协定,点击确定
.png)
⑦ 连贯 VPN 后间接连贯服务器
.png)
ssh xxx@xxx.xxx.xxx.xxx passwd: xxxxxxxx
.png)
输出 ls,达到此界面即为连贯胜利!2. 装置 mindspore(1)在服务器上创立本人的文件夹 mkdier xxxcd xxx(2)创立 conda 虚拟环境并激活 conda create -n xxx python=3.7 服务器如果拥挤的话可能须要一段时间。
.png)
source activate xxx
.png)
(3)按照官网命令下载安装 mindsporeMindspore 官网装置教程:https://www.mindspore.cn/install
.png)
3. clone model 库 git clone https://gitee.com/mindspore/m… 下载官网模型仓库:https://gitee.com/mindspore/m…,在 /models/official 门路下找到本人模型所属的类型,进而找到本人的模型源码。
.png)
浏览模型的 README.md 文件,理解模型的导出命令格局,不便前面 MindSpore IR 的导出。
.png)
4. 下载模型 checkpoint 模型 MindSpore IR 文件的导出须要用到训练好的 checkpoint 文件,而这个文件在云端有现成的,不须要本人训练,网址如下:https://mindspore.cn/resource… 在搜寻框搜寻本人的模型,下载对应的 checkpoint 文件
.png)

.png)
根据模型 README 文档的倡议或要求,将 checkpoint 文件放到相应的门路下(若无要求则本人创立文件夹保留)
.png)
二、MindSpore IR 导出 1. mindir 文件导出(1)批改模型配置文件将 device_target 批改为 GPU(当然如果你用 CPU 版 mindspore 就改成 CPU)
.png)
(2)批改保留图选项 save_graphs 依照华为模型验收标准,这个属性应该是在 train 外面,如果不在请自行在源码中查找一下。
.png)
(3)导出 MindSpore IR 应用 README 文档中的命令,输出相应的参数,失去 MindSPore IR 文件,其格局为 xxx.mindir。python export.py –ckpt_file [CKPT_PATH] –file_format [EXPORT_FORMAT] –TEST_BATCH_SIZE [BATCH_SIZE]① 命令中的 CKPT_PATH 要具体到 checkpoint 文件,其余参数具体模型具体配置,以 cnnctc 为例:
.png)
CHPT_PATH = ./checkpoint/cnnctc_ascend_v160_mjstiiit_official_cv_acc85.97.ckpt② 命令中的 file_format 目前有三种 [ONNX,MINDIR,AIR],而咱们要开发 onnx 所以只有前面两种能够导出的模式,又因为 AIR 是 Ascend 版的,因而咱们只能抉择 MINDIR
.png)
输出命令后导出 cnnctc.mindir 文件:此节实现
.png)

.png)
2. mindir->ms 文件解密(1)MINDIR 是一个加密文件官网模型加密爱护文档中这样形容:https://www.mindspore.cn/mind…
.png)
大家查看网址后能够看到其中有这两个属性须要输出:
.png)
因而大家须要查看本人模型的 export.py 文件中有没有设置这两个值,如果没有就不论,有的话之后会用到。(2)MindSpore Lite 模型转换(之前的服务器在模型转换时会呈现权限有余的问题,2022.6.14 华为给的新服务器不晓得有没有这个状况,如果依然有问题大家能够更换咱们本人实验室的 GPU 服务器来实现这一步,我用的是 GPU 算子的服务器)这一大节的目标就是应用 MindSpore Lite 工具将 MINDIR 文件转化为明码的 MS 文件。官网教程网址:https://www.mindspore.cn/lite… 具体步骤如下:① 下载 MindSpore Lite 点击这个超链接,下载 MindSpore Lite1.7 Linux-x86_64 版本
.png)

.png)
下载后将其传输到服务器上,放在哪本人随便,记得就行:
.png)
② 解压 mindspore-lite-1.7.0-linux-x64.tar.gz 文件 tar -zxvf mindspore-lite-1.7.0-linux-x64.tar.gz
.png)
③ 环境设置将转换工具须要的动态链接库退出环境变量 LD_LIBRARY_PATH。export LD_LIBRARY_PATH=${PACKAGE_ROOT_PATH}/tools/converter/lib:${LD_LIBRARY_PATH}${PACKAGE_ROOT_PATH}是 mindspore-lite 解压后的门路。④ 进入转换工具所在目录执行如下命令,进入转换工具所在目录。cd ${PACKAGE_ROOT_PATH}/tools/converter/converter${PACKAGE_ROOT_PATH}是 mindspore-lite 解压后的门路。将第(1)节导出的 cnnctc.minir 文件传到此目录下
.png)
⑤ 执行转换应用如下命令进行模型转换:./converter_lite –fmk=MINDIR –modelFile=cnnctc.mindir –outputFile=cnnctc 转换命令能够设置一些参数,如果须要请自行查看官网教程。
.png)
转换实现后输入如下:
.png)
导出的 MS 文件:
.png)
⑥ Netron 可视化将导出的 cnnctc.ms 文件下载到本地,而后关上 Netron 在线官网:https://netron.app/
.png)
点击 Open Model,抉择下载到本地的 cnnctc.ms 文件,失去网络图如下:
.png)

.png)
此图中每一个方框就是咱们本次 onnx 须要映射的算子。三、算子剖析 1. 开发文件下载 clone mindspore 库 git clone https://gitee.com/EJaven/mind… 这里 clone 的是咱们团队的仓库:https://gitee.com/EJaven/mind…,之后能够从这里提 pr,当然也能够本人 fork 官网仓库而后提 pr。cd mindspore/mindspore/ccsrc/transform/express_ir/ 在此门路下能够找到咱们开发所用的这个 onnx_exporter.cc 文件。2. 算子统计根据第二章最初关上的 Netron 网络图,以 cnnctc 模型为例,统计其中用到的算子:MindSporeConv2DMaxPoolReLUTransposeReshapeMatMul 这些就是 cnnctc 中须要映射的算子。3. 算子查问找齐所有须要映射的算子之后咱们就能够去 mindspore/ccsrc/transform/expr ess_ir/onnx_exporter.cc 文件中查找这些算子是否曾经实现过。
.png)
同样以 cnnctc 模型为例,查问后果如下:Onnx 算子查问库 MindSpore 是否已实现?OnnxConv2D 是 ConvMaxPool 是 MaxPoolReLU 是 ReLUTranspose 是 TransposeReshape 是 ReshapeMatMul 是 MatMulPad 否,须要映射 PadAdd 是 Add 能够看到大部分算子曾经实现过,仅剩下 Pad 算子须要映射开发,那接下来就是钻研和剖析 MindSpore 中的 Pad 算子和 Onnx 中 Pad 算子的输出,输入以及属性之间存在哪些差别,而后依据剖析后果确定算子映射开发流程。4. 算子映射如果存在没有实现的算子,那接下来就是开发流程,大家能够先查阅华为官网给的 markdown 文件,理解根底后,再持续浏览此文档。至此咱们就实现了此次 onnx 我的项目的所有后期筹备工作,如果通过剖析发现你的模型中所有算子都曾经实现,可跳转到第五章 - 编译导出,若有须要开发的算子请持续程序浏览。四、算子映射 1. 基本概念(1)图华为官网对于图的定义如下:
.png)
实际上开发 onnx 并不需要齐全相熟和清晰图的概念,相同将图形象的了解为一个计算流程图会更好了解他的作用和调用流程,假如当初咱们须要计算如下表达式:F(x, y, z)=(x + y)* z – b,则其对应的计算流程图如下:
.png)
图 1 F(x, y, z)计算流程图图 1 中的每一个圆圈或者椭圆都是一个节点,而所有这些节点合起来就形成了咱们 F(x, y, z)这个函数的计算流程图,而“图”就是用计算机代码来示意和记录这种计算流程。而在这张图中,咱们能够看到有三种不同色彩的节点,对于咱们本次 onnx 映射来说他们就是最罕用到的三种节点:输出数值节点(橙色 x, y, z)、常量数值节点(灰色 b)和算子节点(蓝色 +, , -)。大家也留神到了我把图中的蓝色节点(+, , -)称之为算子而不是运算符,这就是因为其实这些运算符就是最根底最根本的算子,而咱们所用到的算子实际上就是这样根底的算子一直叠加起来的,也就是咱们调用的库办法和库函数。因而能够将图 1 转换为算子计算图 2:
.png)
图 2 算子计算图至此咱们就对“图”有了一个简略然而我集体感觉齐全够用了的了解,上面将节点合并为两类:数值节点和算子节点,并介绍节点的相干概念。(2)节点① 节点的 name 能够留神到图 2 中我除了把运算符(+, *, -)换成算子的名字外,还在每一个节点边上标了一个序号,这个序号能够了解为每个节点的惟一标识符,也就是计算机用来存储和记录运算流程的一个标记。这种标记在本次 onnx 算子映射中被设为这个节点的“name”,同时对于这张图来说存在一个变量用于存储其中所有节点的“name”,也就是官网文档中的:“node_map_ptr”< 节点,节点序号 >。② 数值节点后面的输出数值节点和常量数值节点都是用来存储数据数值的节点,其次要包含以下信息:Name(序号):该节点的惟一标识符(如果不好了解就全副了解为序号)。Value(数值):输出或者本人设定的常量的数值,如 1,10,1000 等。Type(类型):该节点所存储数值的数据类型。Output(输入):数值节点须要传输给其余节点进行计算,因而须要设定此节点的输入(即传什么给上游节点),实际上大多数状况都是 add_output(name),也就是把本人的序号传下去,到时候上游节点就能够通过 name 拜访数值了。③ 算子节点算子节点中定义了数据的计算逻辑,其计算局部是“算子开发”所须要做的事件,本次 onnx 映射仅仅只须要调整和映射以下信息即可:Name(序号):该节点的惟一标识符(如果不好了解就全副了解为序号)。OpType(算子类型):这个能够简略了解为此算子的名字,比方“+”他的 OpType 设为“Add”。Input(输出):定义此算子的输出是什么,行将什么数值节点或者其余算子节点的输入传给此算子,大部分状况下都是 add_input(name_xxx),即通知计算机我要序号为 name_xxx 的节点作为我的输出。Attr(属性):有些算子除了输出外还有属性值,属性值是在算子初始化的时候赋值的,而在此次我的项目中能够将其与输出看为同一个货色,只不过获取的办法不同罢了。Output(输入):定义此算子的输入是什么,行将什么数值传给上游算子,实际上大多数状况也是 add_output(name1),即此算子的输入就是其惟一标识符,上游算子须要调用的话能够 add_input(name1)来设置这个算子为输出。通过设置好每一个数值节点的 value,type,output 和算子节点的 input 和 output 信息后,整张图就连接起来了。2. 开发流程此次开发流程将以我本次 onnx 推理的 CNN+CTC 模型中短少的 Pad 算子为例,以性能形容 + 代码 + 映射对应图的模式解说开发中须要用到的办法,学会了这些办法后就能够通过拼接和组合实现其余算子的映射。(1)算子映射剖析① MindSpore Pad 算子接口分析 MindSpore 官网算子查问网址:https://www.mindspore.cn/docs…
.png)

.png)
这个算子其实非常简单,输出一个任意维度的 Tensor,依据初始化时赋值的 paddings 属性在对应的维度前和后减少 0 值,以 2 维 Tensor 为例:
.png)
输出 input_x 如下:
.png)
属性 paddings 如下:
.png)
input_x 的 shape 是(2,4),这个 paddings 属性取值的含意就是,在 input_x 的第 0 个维度减少 3(后面 1,前面 2),对于这个例子就是减少三行(下面 1 行,上面 2 行),而后在 input_x 的第 1 个维度(列)减少 3 列(右边 2 列,左边一列),所有减少的行和列全副填充数值 0,后果如下:
.png)
而 mode 属性值是设定填充的形式,分为三种,具体大家能够看官网案例,本次网络应用默认值故此处不剖析。Onnx Pad 算子接口分析 Onnx 算子查问网址:https://github.com/onnx/onnx/…
.png)

.png)
能够看到 Onnx 中也是有这个 Pad 算子,并且简略查阅后发现性能是雷同的,那么就进入下一步。② 差别剖析通过比照剖析咱们能够看出 MindSpore 中的 Pad 算子和 Onnx 中的 Pad 算子性能是雷同的,然而在输出和属性上存在差别,具体为:MindSpore 中用来设置减少维度的 paddings 是一个属性,而 Onnx 中起到雷同性能的 pads 是一个输出,因而咱们须要写 paddings 到 pads 的映射。
.png)

.png)
同时 paddings 要求是一个 shape 为 [N, 2](N 为 input_x 的维度)的 tuple,其第 D 行的第 0 个元素代表在 input_x 的第 D 维后面减少的数量,而第 1 个元素代表在前面减少的元素。而 pads 则必须为一个 1D 的 tensor 其 shape 为[2 * N],其数值模式为[dim1_begin, dim2_begin,…, dim1_end, dim2_end] 其中 dim1_begin 和 dim1_end 就代表在 input_x 的第 1 个维度前和后减少的数量。文字看的可能比拟晕,那咱们看上面的图:
.png)

.png)
这张图就能够很清晰的看出 paddings 和 pads 之间的对应关系,同时能够失去 paddings 到 pads 映射所须要做的事件:• MindSpore 属性 paddings 映射为 Onnx 输出 pads• 将 paddings 从 2D tuple 类型映射为 1D tensor 类型• 将 paddings 的数值正确映射为 pads 的数值而因为 CNN+CTC 网络中应用的是默认 mode 属性值 CONSTANT,往新增行列填充 0,故此处不剖析,同样也不须要映射,如果 mode 属性值设定了某个特定的数值则须要减少对 mode 属性的映射。至此咱们实现了对须要映射算子的剖析,上面就能够进入开发阶段了,如果对于应该在那一行或者哪里写相应的代码能够查看 CNN+CTC ONNX 导出的 PR 链接,其中有清晰的削减删改代码和代码行号:https://gitee.com/mindspore/m…(如果你发现须要映射的算子可能完满映射,即 MindSpore XXX 算子与 Onnx XXX 算子的输入输出完全一致,那么能够跳过此章,间接进入第 3 节官网案例剖析)。(2)申明映射办法在 OnnxExporter 类下申明类公有办法 ExportPrimXXX:
.png)

.png)
其中四个参数的含意别离为:• func_graph 是 MindSpore 的图。• node 是图中以后的节点,该函数中就是 Pad 算子节点。• node_map_ptr 存储图中所有节点 < 节点,节点序号 >。• graph_proto 是 ONNX 的图。(3)注册算子映射表在 OnnxExporter::ExportCNode 办法中注册算子映射表:
.png)

.png)
(4)实现映射办法实现第(2)步申明的映射办法 ExportPrimXXX:
.png)
(5)获取节点输出与属性获取 MindSpore Pad 算子第 1 个输出 input_x 的 name:
.png)

.png)
获取 MindSpore Pad 算子的属性 paddings 值:
.png)

.png)
(6)数值映射将 paddings(2D tuple)转化为 pads_sequence(1D vector),并实现数值映射
.png)

.png)
(7)增加数值节点将数值 pads_sequence 注册为数值节点 pads:
.png)

.png)
在 node_map_ptr 中注销 pads 常量数值节点并获取其 name:
.png)

.png)
在 ONNX 图 graph_proto 中新建一个常量数值节点 pads_node,并指定其输入为 pads 常量数值节点的 name:
.png)

.png)
为 pads_node 节点增加一个 value 数值属性,并将数值节点 pads 中的数值转换为 onnx::tensor 后赋值给 value:
.png)

.png)
(8)增加算子节点本次 Pad 算子映射不波及算子节点的增加,第 3 节的 BatchMatMul 算子 映射中会介绍如何增加算子节点。(9)Onnx 图增加算子节点在 node_map_ptr 中注销以后 MindSpore Pad 算子节点并获取其 name:
.png)

.png)
在 ONNX 图 graph_proto 中新建 ONNX Pad 算子节点:
.png)

.png)
指定 ONNX Pad 算子节点的输入为 MindSpore Pad 算子节点的输入(name)即 ms_pad_node_name:
.png)

.png)
指定 ONNX Pad 算子节点的第 1 个输出为 MindSpore Pad 算子的第 1 个输出 input_x 的 name 即 x_name:
.png)

.png)
指定 ONNX Pad 算子节点的第 2 个输出为(7)中创立的 pads 数值节点的 name 即 pads_name:
.png)

.png)
映射实现后:
.png)
3. 官网案例剖析官网案例就不画图了,以性能形容加代码的办法剖析,同时映射办法的申明和算子注册也不赘述,间接剖析外围映射代码。(1)一对一(齐全对应):MS Conv2D -> Onnx Conv① 映射剖析官网案例,就不剖析了,后果就是 MindSpore Conv2D 和 Onnx Conv 的输出和属性可能齐全对应上,那么就只须要写一段代码,把雷同作用的参数名映射一下就好了:
.png)
(2)一对一(不齐全对应):MS ExpandDims -> Onxx Reshape① 映射剖析 MindSpore ExpandDims 算子 -> ONNX Reshape 算子 , 输入输出能够对应,属性含意不同,无奈间接对应, ExpanDims 输出 axis(int)是要扩大维度的轴,Reshape 输出 shape 是扩大后的维度,须要在转换时作非凡解决。因而咱们明确映射所须要做的事:• 获取 MindSpore ExpandDims 算子的输出 axis 并联合输出 input_x 的 shape 计算出扩维之后的 new_shape,而这个 new_shape 就是 Onnx Reshape 算子所须要的输出 shape。② 获取节点输出与属性获取 MindSpore ExpandDims 算子的第 1 个输出 input_x 和第 2 个输出 axis:
.png)
③ MindSpore 输出 axis 映射为 Onnx 输出 shape 获取 MindSpore 第 1 个输出 input_x 的 shape 值 x_shape:
.png)
通过 MindSpore 的输出 axis 和 x_shape 推导出正确的 Onnx 输出 new_shape,具体算法不剖析,如果感兴趣能够本人查看:
.png)
④ 增加数值节点将数值 new_shape 注册为数值节点 shape:
.png)
在 node_map_ptr 中注销 shape 常量数值节点并获取其 name(name_shape):
.png)
在 ONNX 图 graph_proto 中新建一个常量数值节点 node_proto,并指定其输入为常量数值节点的 name(name_shape):
.png)
为 node_proto 节点增加一个 value 数值属性,并将数值节点 shape 中的数值转换为 onnx::tensor 后赋值给 value:
.png)
⑤ Onnx 图增加算子节点在 node_map_ptr 中注销以后 MindSpore ExpandDims 算子节点并获取其 name:
.png)
在 ONNX 图 graph_proto 中新建 ONNX Reshape 算子节点:
.png)
指定 ONNX Reshape 算子节点的输入为 MindSpore ExpandDims 算子节点的输入(name)即 node_name:
.png)
指定 ONNX Pad 算子节点的第 1 个输出为 MindSpore ExpandDims 算子的第 1 个输出 input_x 的 name 即 input_x:
.png)
指定 ONNX Pad 算子节点的第 2 个输出为④中创立的 shape 数值节点的 name 即 name_shape:
.png)
至此实现映射(3)一对多:MS BatchMatMul -> ONNX Transpose + MatMul① 映射剖析 MindSpore 的 BatchMatMul 算子 有 transpose_a,transpose_b 属性,管制是否将输出转置,ONNX 的 MatMul 算子 无转置属性,因而,须要判断 BatchMatMul 的 transpose_a,transpose_b 属性是否为 true,如果为 true,则须要在 MatMul 对应输出前增加 Transpose 算子作转换。因而咱们能够明确须要做的事:• 获取 MindSpore BatchMatMul 算子的属性 transpose_a 和 transpose_b• 获取 MindSpore BatchMatMul 算子的输出 input_x 和 input_y• 若 transpose_a 为 true,则须要减少一个 Onnx Transpose 节点将输出 input_x 进行转置• 若 transpose_b 为 true,则须要减少一个 Onnx Transpose 节点将输出 input_y 进行转置② 获取节点输出与属性获取 MindSpore BatchMatMul 算子的第 1 个输出 input_x 和第 2 个输出 input_y:
.png)
获取 MindSpore BatchMatMul 算子的第 1 个属性 transpose_a 和第 2 个属性 transpose_b:
.png)
③ 若 transpose_a 为 True 则在 input_x 后减少 Transpose 算子节点获取输出 input_x 的 shape:
.png)
在 node_map_ptr 中注销一个 transpose_input_x_name 常量数值节点来存储转置后的 input_x 数值:
.png)
在 ONNX 图 graph_proto 中新建 ONNX Transpose 算子节点 transpose_inputx_node_proto,并且指定其输出为 MindSpore BatchMatMul 算子节点的第 1 个输出 input_x,输入为方才创立的常量节点 transpose_input_x_name:
.png)
为 transpose_inputx_node_proto 节点增加一个 perm 数值属性,并根据 input_x 的 shape 为其赋值:
.png)
至此对 input_x 进行转置的 Onnx Transpose 算子节点增加实现。④ 若 transpose_b 为 True 则在 input_y 后减少 Transpose 算子节点获取输出 input_y 的 shape:
.png)
在 node_map_ptr 中注销一个 transpose_input_y_name 常量数值节点来存储转置后的 input_y 数值:
.png)
在 ONNX 图 graph_proto 中新建 ONNX Transpose 算子节点 transpose_inputy_node_proto,并且指定其输出为 MindSpore BatchMatMul 算子节点的第 1 个输出 input_y,输入为方才创立的常量节点 transpose_input_y_name:
.png)
为 transpose_inputy_node_proto 节点增加一个 perm 数值属性,并根据 input_y 的 shape 为其赋值:
.png)
至此对 input_y 进行转置的 Onnx Transpose 算子节点增加实现。⑤ Onnx 图增加算子节点在 node_map_ptr 中注销以后 MindSpore BatchMatMul 算子节点并获取其 name(node_name):
.png)
在 ONNX 图 graph_proto 中新建 ONNX MatMul 算子节点:
.png)
指定 ONNX Reshape 算子节点的输入为 MindSpore BatchMatMul 算子节点的输入(name)即 node_name:
.png)
上面这行代码我也不晓得啥意思,如果有同学晓得了请分割我批改:
.png)
若 transpose_a 为 True,则阐明 input_x 须要转置,那么指定 ONNX MatMul 算子节点的第 1 个输出为转置后的常量数值节点 transpose_input_x_name;若为 False,则阐明 input_x 不须要转置,那么指定 ONNX MatMul 算子节点的第 1 个输出为原始的 input_x:
.png)
若 transpose_b 为 True,则阐明 input_y 须要转置,那么指定 ONNX MatMul 算子节点的第 1 个输出为转置后的常量数值节点 transpose_input_y_name:若为 False,则阐明 input_y 不须要转置,那么指定 ONNX MatMul 算子节点的第 1 个输出为原始的 input_y:
.png)
至此实现映射。五、编译导出 1. MindSpore 编译在 MindSpore 门路下输出以下命令开始编译:sh build.sh -e gpu -j32 首次编译须要下载很多第三方包所以很慢,之后再次编译就很快了。编译报错则依据报错批改,编译胜利则显示如下界面:
.png)
2. MindSpore 包重装置或 Python 运行门路设置(举荐)(1)MindSpore 包重装置编译完的 MindSpore 包会生成在 mindspore/build/package/ 门路下:
.png)
能够在 mindspore 门路下输出以下命令重新安装 mindspore 包:pip uninstall build/package/xxx.whlpip install build/package/xxx.whl(2)Python 运行门路设置输出以下命令设置 Python 运行门路:export PYTHONPATH=/disk1/user14/wzb/test/mindspore/build/package:$PYTHONPATH 把其中的门路换成本人编译的 mindspore 寄存的绝对路径,通过这种形式能够防止反复卸载再装置 mindspore 包的麻烦,只须要设置一次后就能够间接调用每次编译进去的新 mindspore 包了。3. Onnx 模型导出更新完 MindSpore 包后,在 Models 文件夹中本人模型门路下调用 README 文件中的 export 命令,设置导出格局 –file_format 为 ONNX,若胜利导出则在模型门路下生成 xxx.onnx 文件:
.png)
若报错则依据报错信息批改算子映射文件 onnx_exporter.cc 并反复(1)(2)(3)步骤,直到可能导出 ONNX 文件为止。六、推理测试 1. 数据集下载(1)根据 Models README 下载查看 Models 中 README 文件中对于数据集的形容,通过其给出的超链接下载数据集并放在对应的门路下:
.png)
(2)根据模型原论文源码中的 README 下载若发现 Models 的 README 文件给出的超链接中数据集太大、下载很慢或者保留在谷歌云盘上须要翻墙,那么能够查阅一下模型原论文中给出的源码链接,查看源码中 README 提供的数据下载地址。比方我的 CNN+CTC 模型 Models 中给出的超链接是用谷歌云盘存储的,并且把训练集、验证集和测试集打包在一起,导致数据集高达 18G,又须要翻墙,间接下载常常中断:
.png)
多次尝试未果后,我查阅了原论文的代码并且找到了其 readme 文件中给出的数据集下载链接:
.png)
点开后我发现了原作者的数据集中既有 Models 中给出的汇合包,还有独自的训练集、验证集和测试集压缩包,因为咱们只波及推理所以只须要下载测试集压缩包即可,其大小只有 160M,下载十分顺利:
.png)
2. MindSpore 模型推理(1)MindSpore 推理这一步骤只须要参照本人 Models 模型中的 README 文件中对于 MindSpore 模型 eval 的阐明即可,只是须要留神有些模型的脚本可能因为 MindSpore 的更新导致一些算子的用法产生了扭转,如果报错能够本人看着批改一下:
.png)
3. Onnx 模型推理(1)Onnx 推理文件 Onnx 推理文件就是应用 onnxruntime 接口导入第二章中导出的 onnx 文件,而后传入合乎网络要求的输出,最终输入 Onnx 离线推理的模型精度。这一步骤实际上很简略,次要蕴含两步,残缺推理文件能够参考此 PR 中的 eval.py 和 infer_cnnctc_onnx.py:https://gitee.com/mindspore/m…① 数据获取 dataloader 应用 Models 模型 eval 脚本中的数据集 dataloader 获取数据,而后将其从 MindSpore::Tesnor 转化为 Onnx 个别的输出 numpy 格局:
.png)

.png)
② 网络替换:MindSpore Net -> Onnx 将 Models 模型 eval 脚本中对于网络的定义替换成 Onnx 中 onnxruntime 导入的网络:MindSpore:
.png)
Onnx:
.png)
(2)Onnx 推理脚本推理脚本就是仿照 eval 脚本写一个能够用 bash 调用的.sh 文件,使得用户能够通过 bash 命令一键推理,具体可参考此 PR 中的 run_infer_onnx.sh:https://gitee.com/mindspore/m…
.png)
4. PR 提交(1)Leader 创立分支分割小组 Leader fork 官网 MindSpore 和 Models 仓库并给每个模型创立分支。(2)下载新 MindSpore 和 Models 仓库下载小组用来提交 PR 的新 MindSpore 和 Models 仓库:git clone https://gitee.com/xxxx/mindsp… clone https://gitee.com/xxxx/models…(3)更新替换文件进入 MindSpore 和 Models 门路后切换到本人的分支:git checkput cnnctc
.png)
将本人须要批改的文件传入新下载的 MindSpore 和 Models 文件夹对应门路下进行替换。(4)上传代码应用如下命令提交 pr:① 查看已批改文件:git status
.png)

.png)
② 提交到本地仓库:根据①中输入的已批改文件,核查是否均是本人批改的,如果是则间接 git add . 若不全是则一个个的 git add xxxx 文件。MindSPore 仓库:git add .git commit -am ” ONNX converter: CNN+CTC support”
.png)
保留并退出:点击 ESC,而后按住 shift 和”:”,输出 wq,回车 Models 仓库:git add .git commit -am ” ONNX infer: CNN+CTC support” 保留并退出:点击 ESC,而后按住 shift 和”:”,输出 wq,回车③ 提交到近程仓库分支:git push origin cnnctc
.png)
5. 创立 PR 分割 Leader 创立 PR,或本人返回提交代码的仓库创立 PR:
.png)

.png)

.png)
6. 门禁测试① 开启测试在本人 PR 的评论区输出 /retest 即可开启测试:
.png)
点击零碎主动评论中的 Link 超链接即可关上门禁界面:
.png)

② 测试后果报错后会中断门禁测试,在评论区找报错信息,点击报错评论中的超链接即可查看门禁报错信息:

一段代码谬误会以两段雷同代码的不同格局输入,上面一段为本人以后写的代码,而下面一段为门禁系统的修改意见,只须要依照下面一段改就行了(字有点小放大点看)。

如果通过则零碎主动回复如下:

七、总结本次 Onnx 模型推理和导出我的项目整体难度不大,因为大部分模型都是基于卷积神经网络,各种模型中的算子具备高度重复性,因而可能有很多人选到的模型是所有算子都曾经实现的,这种状况下只须要根据指南实现精度推理和交付件编写即可。若开发中遇到问题(如 ckpt 文件精度不对,须要申请训练资源)请分割华为负责工程师吴工(吴逸群)。预祝大家本次 Onnx 我的项目开发顺利,早日提交交付件,都能评上金质量奖!!!

正文完
 0