RtinaFace Mxnet模型转TNN,附Reshape层踩坑

背景说明

我从下面这个位置获取到的RetinaFace模型是mxnet的:

TNN提供的模型转换选项如下:

{onnx2tnn,caffe2tnn,tf2tnn,tflite2tnn}

并不支持mxnet直接转换成tnn,那只能将mxnet模型先转换其他格式再转为tnn.

我尝试过从mxnet转为onnx但是会遇到各种问题:
如SoftmaxActivation、UpSampling等算子不支持、以及onnx和mxnet版本不匹配等等
更糟心的是千辛万苦解决了转换路上的问题得到的onnx模型居然不能正确加载或运行…
在此我记录一个能正确转换到tnn的方式,方便后来的人少走弯路,能抛砖引玉就更妙了


模型转换过程

先将mxnet转为caffe,再用tnn转换工具将caffe转为tnn
其实仔细看tnn给的pyhton转换脚本,它的转换过程是caffe->onnx->tnn
哦~,老套路,onnx做中间模型
所以总的转换路线为:

mxnet->caffe->onnx->tnn

我的环境

16.04.1-Ubuntu
Python 3.7.2 (default, Jan 26 2021, 16:01:45)
mxnet 1.7.0
caffe 1.0.0


mxnet to caffe

  • 0.下述操作注意换成自己的路径
  • 1.clone开源工具 MXNet2Caffe
git clone https://github.com/cypw/MXNet2Caffe
  • 2.打开prototxt_basic.py,将输入维度改为要转换的模型对应的维度
txt_file.write('    shape: { dim: 1 dim: 3 dim: 320 dim: 320 }\n')
  • 3.通过json2prototxt.py将json转为prototxt
   python3.7 ./json2prototxt.py --mx-json model_mxnet/mnet.25-symbol.json --cf-prototxt model_caffe/mnet.25.prototxt
  • 4.运行mxnet2caffe.py,将params转为caffemodel
python3.7 ./mxnet2caffe.py --mx-model model_mxnet/mnet.25 --cf-prototxt model_caffe/mnet.25.prototxt --cf-model model_caffe/mnet.25.caffemodel
  • 5.一切顺利的话,我们得到两个文件:mnet.25.caffemodel 、 mnet.25.prototxt

caffe to tnn [Reshape层踩坑]

  • 1.获取tnn模型转换工具:
   docker pull turandotkay/tnn-convert
  • 2.将caffe转为tnn.注意下述命令能转化出tnn模型,但是face_rpn_cls_score_reshape_stride32/16/8 三个输出结果是错误的
docker run --volume=$(pwd):/workspace -it turandotkay/tnn-convert:latest python3 ./converter.py caffe2tnn /workspace/mnet.25.prototxt /workspace/mnet.25.caffemodel 

模型结果错误排查

  • 0.这个太耗时了,想起了苦涩的排查过程

  • 1.算法结果输出有三类, 其中结果正确的是face_rpn_bbox_pred_stride、face_rpn_landmark_pred_strid, 错误的是face_rpn_cls_prob_reshape_stride

  • 2.进行输出层比对,发现SoftmaxCaffe层上下有两个Reshape操作的shape参数错误,如下图所示(比对模型的关键是找一个能正确输出结果的模型,比如正确caffe模型)
    face_rpn_cls_score_reshape_stride32
    face_rpn_cls_prob_reshape_stride32

  • 3.caffe 中两个shape参数:
    在这里插入图片描述
    在这里插入图片描述


修复方法

  • 1.查看mnet.25.prototxt文件,发现Reshape层参数形式如下:
  type: "Reshape"
  reshape_param {
    shape {
      dim:  2
      dim:  -1
      dim:  0
    }
    axis: 1  
  }
  • 2.参考[caffe-Reshape层配置], mnet.25.prototxt文件的Reshape层参数是忽略了NCHW中的"N".那把它添加上,"N"设置为1( 只添加 dim: 1),改成如下形式(注意一共要改6处,搜索type: “Reshape”):
  type: "Reshape"
  reshape_param {
    shape {
      dim:  1
      dim:  2
      dim:  -1
      dim:  0
    }
    axis: 1  
  }

3.修改的文件另存为mnet.25.reshape.prototxt, 重新转换

docker run --volume=$(pwd):/workspace -it turandotkay/tnn-convert:latest python3 ./converter.py caffe2tnn /workspace/mnet.25.reshape.prototxt /workspace/mnet.25.caffemodel
  1. 经过测试,模型转化正确并能正确出结果
    在这里插入图片描述

思考

  • 1.经过上面对caffe的Reshape层的修改,转换出的tnn模型便可以正确解析,所以说明tnn对Reshape参数解析有问题?
  • 我们来看两次转换时产生的中间模型onnx,左边是修改前的,右边是修改后的,可以看到修改后确实多了一个维度(从2x20X10变为1x2x20x10),看来是tnn解析onnx时需要完整的输入nchw四个维度信息,否则解析会出错.当然这个推论需要详细了解caffe、onnx、tnn解析模型的代码才能确定.
    在这里插入图片描述

结案 2021/03/18

上述思考的推理在git上得到tnn成员的回答,感谢这些开源作者的奉献,回复神速
结论: 截止目前 master 分支的代码确实要求模型的输入以及中间每一层都要保持 nchw 四维
详细问答在: [git issues]

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值