前言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我的项目开发顺利,早日提交交付件,都能评上金质量奖!!!