Pytorch转ncnn

pytorch模型转ncnn

  • ncnn是腾讯公司发布的一款深度学习框架,ncnn 是一个为手机端极致优化的高性能神经网络前向计算框架。
  • 虽然ncnn对于底层CPU运算加速十分明显,尤其是ARM内核的处理器,但是对于大部分深度学习任务来说,使用python+深度学习框架来进行深度模型探索、训练时间性价比更高。
  • 但是最终将模型转到移动端计算时,还是要考虑到移动端的算力,可以从轻量化模型(MobileNet、ShuffleNet等)、权值量化、并行计算、GPU加速、计算框架等去考虑移动端加速
  • 使用pytorch训练模型,再将模型转换为ncnn

转换的几个思路

pytorch转onnx转ncnn

第一种方式最容易想到,onnx全称Open Neural Network Exchange,本身设计的目的就是用来进行模型之间的相互转换,但是目前不支持ncnn转换。github地址:https://github.com/onnx/onnx

Pytorch转ncnn_第1张图片
image

pytorch转caffe转ncnn

ncnn官方似乎对caffe模型情有独钟,师兄在找我要模型的时候,都是直接说要caffe模型而不是ncnn模型,由此可见caffe与ncnn的亲密程度了,不过这也极有可能是因为caffe模型在移动端的优化做的也比较好。
其他pytorch转caffe工具,比如pytorch2caffe,github地址:https://github.com/longcw/pytorch2caffe,但是实际测试后感觉效果不理想

pytorch直接转ncnn

ncnn官方的源码中,pytorch转ncnn的推荐方法是使用PytorchConverter github地址:https://github.com/starimeL/PytorchConverter,经过多种方案测试无数次次后验证该方法可行

Pytorch转ncnn_第2张图片
image

PytorchConverter将Pytorch转换为ncnn过程

版本要求(训练和转换时都必须满足这个版本要求)

  • pytorch : torch==0.2
  • torchvision==0.1.8

转换过程

  1. 将PytorchConverter源码通过git克隆到本地
  2. 打开run.py,可以看到其代码中内置了ResNet、MobileNet等,通过模仿其转换MobileNet的过程,可以写出自己的转换代码
  3. 运行run.py将自己的pytorch模型转换为ncnn模型

踩坑记录

  1. pytorch版本不要太高,否则生成的模型的层名和ncnn转换时无法对应上,导致转换出错
  2. nn.logsoftmax()函数不支持,因此将NLL LOSS+logsoftmax转用CrossEntropy+softmax。参考:https://blog.csdn.net/hao5335156/article/details/80607732。再次验证后,发现能够得到正常结果的是NLL + logsoftmax,虽然在模型转换时,logsoftmax不支持,但是由于logsoftmax只在训练时起作用,所以可以在训练测试正常使用Logsoftmax,在模型转换时再换为softmax,因为softmax没有参数,所以原来保存的参数仍然你可以正常加载,且不影响最终特征层的输出。
  3. pytorch的pooling函数对奇数特征图长宽处理时,会将最外一层去掉,强制将特征图转换为偶数;而ncnn在处理时,会将奇数长宽强制+1后再处理。如果不注意这个问题,会导致最终进入全连接层时矩阵维度不对导致无法相乘,在ncnn c++模型测试代码中会出现其他层都有输出,但是一到全连接层时,程序直接崩溃。解决办法是在pooling函数的参数列表中加入 ceil_mode=True。参考:https://github.com/pytorch/pytorch/issues/6842#issuecomment-383332045
    Pytorch转ncnn_第3张图片
    image
  4. pytorch中的ReLU6激活函数PytorchConverter不支持转换,可以改用RuLU或者LeakyReLU
  5. PytorchConverter工具对python版本貌似没有要求,我测试过python2.7和3.6版本都可以正常使用,但是torch和torchvision的版本必须控制
  6. 还是推荐使用python3.x版本,python2.7中整数除以整数只会整除,本人被这个问题卡了一整个上午;而python3中整数除以整数自动得到小数(不得不说太贴心了~)
  7. torch==0.2中,softmax和logsoftmax函数都不支持dim参数,直接去掉即可,因为最终到全连接层这儿的时候,只有一个维度了,所以做softmax的时候,也只有一个维度可以使用

你可能感兴趣的:(Pytorch转ncnn)