Insightface MxNet转成TNN模型
1.项目配置:
虚拟环境:infightfaceenv
环境信息:
mxnet 1.4.0
cuda 10.0.130
onnx 1.3.0 (最初使用1.6.0, 会出现报错:
Unrecognized attribute: spatial for operator BatchNormalization
后修改为1.3.0 )
netron (模型可视化)
2.MXNET转成ONNX模型
参考:链接: Insightface中ArcFace MxNet2ONNX踩坑.
下载模型arcface模型
来自左博开源的链接: mobilefacenet-res2-6-10-2-dim512
转换代码convert.py:
import numpy as np
import mxnet
from mxnet.contrib import onnx as onnx_mxnet
sym='./model-symbol.json'
params='./model-0000.params'
#NCHW
input_shape = [(1,3,112,112)]
onnx_file = './modelnew_onnx.onnx'
#返回转换后的onnx模型的路径
converted_model_path = onnx_mxnet.export_model(sym, params, input_shape, np.float, onnx_file)
成功后利用netron查看,新建viewonnx.py
import netron
modelPath = './modelnew_onnx.onnx'
netron.start(modelPath)
3.ONNX转TNN模型
onnxruntime: 0.2.1
protobuf: 3.14.0
docker-ce:
ubuntu中安装安装 Docker Engine-Community(社区版)
更新apt:
sudo apt-get update
安装最新的Docker CE和containerd:
sudo apt-get install docker-ce docker-ce-cli containerd.io
验证安装成功:
sudo docker run hello-world
docker镜像位于/var/lib/docker
docker命令进行转换
docker run --volume=$(pwd):/workspace -it tnn-convert:latest python3 ./converter.py onnx2tnn /workspace/new_onnx.onnx
-optimize
-v v3.0
-align
-input_file /workspace/in.txt
-ref_file /workspace/ref.txt
参数选择:
1.其中-optimize参数(可选) 可以对模型进行优化,官方强烈建议开启这个选项,在当前框架中我开启这个选项模型转换失败时,去掉 “-optimize” 参数重新尝试成功,如有需求尝试使用该参数
2.align 参数(可选) 可以通过 -align 参数指定,将 转换得到的 TNN 模型和原模型进行对齐,确定 TNN 模型是否转换成功。当前仅支持单输入单输出模型和单输入多输出模型。 align 只支持 FP32 模型的校验,所以使用 align 的时候不能使用 half
input_file 参数(可选) 可以通过 -input_file 参数指定模型对齐所需要的输入文件的名称,输入需要遵循如下格式。
ref_file 参数(可选) 可以通过 -ref_file 参数指定待对齐的输出文件的名称,输出需遵循如下格式。生成输出的代码可以参考
4 报错信息
1.参数类型错误
[ONNXRuntimeError] : 1 : FAIL : Load model from /workspace/new_onnx.onnx failed:
Type End to different types (tensor(double) and tensor(float) in node (conv0).
原因:_minusscalar0层的参数,代表图像均值。当其为小数的时候,mxnet内部解析小数可能默认为double类型。导致转换之后scalar_op1的type为float64,而conv0_weight的type是float32
在onnx中操作的类型需要要求一致,详情见链接: onnx手册
解决办法1:对于训练过的模型里参数有问题的部分
a)修改graph.input中对应节点的type。b)若节点存在初始值,需要同时修改graph.initializer中的type.
解决方法2:修改convert.py代码
#将float改为float32
converted_model_path = onnx_mxnet.export_model
(sym, params, input_shape, np.float32, onnx_file)
2.[ShapeInferenceError] First input does not have rank 2
转换中出现如下报错:
[ONNXRuntimeError] : 1 : FAIL : Load model from /workspace/new_onnx.onnx failed:
Node (pre_fc1) Op (Gemm) [ShapeInferenceError] First input does not have rank 2
看出onnx2tnn镜像中调用onnxruntime
原因:BatchNormalization出来output的维度为4,而FC层所接受的输入维度是2,这两者之间差了一个Flatten操作,但是MXNet(可能不限于MXNet)隐含的帮我们完成了这个步骤。
解决方法:在mxnet包的源码中手动添加一个flatten层
链接: Add Flatten before Gemm.
添加位置:python/mxnet/contrib/onnx/mx2onnx/_op_translations.py
后初步尝试成功
---------- convert model, please wait a moment ----------
Converter ONNX to TNN Model
Converter ONNX to TNN model succeed!
后续待更新