前提:github下载源码编译相关工具,感觉官方的文档说的很不清楚,不简洁!!!
1.模型转换
(1)参数说明
Usage: MNNConvert [OPTION...]
-h, --help Convert Other Model Format To MNN Model
-v, --version 显示当前转换器版本
-f, --framework arg 需要进行转换的模型类型, ex: [TF,CAFFE,ONNX,TFLITE,MNN,TORCH, JSON] --modelFile arg 需要进行转换的模型文件名, ex: *.pb,*caffemodel
--prototxt arg caffe模型结构描述文件, ex: *.prototxt
--MNNModel arg 转换之后保存的MNN模型文件名, ex: *.mnn
--fp16 将conv/matmul/LSTM的float32参数保存为float16
--benchmarkModel 不保存模型中conv/matmul/BN等层的参数,仅用于benchmark测试 --bizCode arg MNN模型Flag, ex: MNN
--debug 使用debug模型显示更多转换信息
--forTraining 保存训练相关算子,如BN/Dropout,default: false
--weightQuantBits arg arg=2~8,此功能仅对conv/matmul/LSTM的float32权值进行量化,仅优化模型大小,加载模型后会解码为float32,量化位宽可选2~8,运行速度和float32模型一致。8bit时精度基本无损,模型大小减小4倍,default: 0,即不进行权值量化
--compressionParamsFile arg 使用MNN模型压缩工具箱生成的模型压缩信息文件
--saveStaticModel 固定输入形状,保存静态模型, default: false
--inputConfigFile arg 保存静态模型所需要的配置文件, ex: ~/config.txt。文件格式为: input_names = input0,input1
input_dims = 1x3x224x224,1x3x64x64
--JsonFile arg 当-f MNN并指定JsonFile时,可以将MNN模型转换为Json文件
--info 当-f MNN时,打印模型基本信息(输入名、输入形状、输出名、模型版本等-
--testdir arg 测试转换 MNN 之后,MNN推理结果是否与原始模型一致。
arg 为测试数据的文件夹,生成方式参考 "正确性校验" 一节
--thredhold arg 当启用 --testdir 后,设置正确性校验的误差允可范围,若不设置,默认是 0.01
--saveExternalData 将权重,常量等数据存储在额外文件中,默认为`false`模型将减小一半,精度基本无损
(2)CAFFE
./MNNConvert -f CAFFE --modelFile XXX.caffemodel --prototxt XXX.prototxt --MNNModel XXX.mnn --bizCode biz
(3)ONNX
./MNNConvert -f ONNX --modelFile XXX.onnx --MNNModel XXX.mnn --bizCode biz
(4)PYTORCH
./MNNConvert -f TORCH --modelFile XXX.pt --MNNModel XXX.mnn --bizCode biz
注意:TorchScript模型要求使用torch.jit导出的模型,不要直接使用Pytorch的权重文件作为模型转换;导出模型的代码如下:
import torch
# ...# model is exported model
model.eval()
# trace
model_trace = torch.jit.trace(model, torch.rand(1, 3, 1200, 1200))
model_trace.save('model_trace.pt')
# script
model_script = torch.jit.script(model)model_script.save('model_script.pt')
2.算子支持列表
./MNNConvert -f CAFFE --OP
./MNNConvert -f TF --OP
./MNNConvert -f ONNX --OP
./MNNConvert -f TORCH --OP
3.检查模型正确性
testMNNFromTf.py :适用 pb
testMNNFromTflite.py :适用 tflite
testMNNFromOnnx.py :适用 onnx
testMNNFromTorch.py :适用 pt (torchscript)
3.1 Step1
将MNN目录下tools/scripts/的上述文件拷贝到build目录下
3.2 Step2
根据自己的模型进行检查,例如onnx模型
python3 testMNNFromOnnx.py 2d106det_sim.onnx(onnx模型名)
3.3 Setp3
出现TEST_SUCCESS表示MNN的模型转换与运行结果正确
example:
onnx/test.onnx
tensor(float)
['fc1']
inputs:
data
onnx/
outputs:
onnx/fc1.txt (1, 212)
onnx/
The device support dot:0, support fp16:0, support i8mm: 0
Start to Convert Other Model Format To MNN Model...
/MNN/tools/converter/source/onnx/onnxConverter.cpp:40: ONNX Model ir version: 7
Start to Optimize the MNN Net...
inputTensors : [ data, ]
outputTensors: [ fc1, ]
Converted Success!
Check convert result by onnx, thredhold is 0.01
data
output: fc1
fc1: (1, 212, )
TEST_SUCCESS
4.模型推理API
4.1导入MNN
import MNN
4.2加载MNN模型
interpreter = MNN.Interpreter("vis_transformer.mnn")
4.3配置config
config = {}
(1)低精度fp16推理,默认float32
config['precision'] = 'low'
(2)使用后端:cpu、gpu、opencl
config['backend'] = 'CPU'
(3)多线程
config['thread'] = 4
4.4创建解释器
session = interpreter.createSession(config)
4.5获取模型输入
# 获取所有输入 interpreter.getSessionInputAll()
input_tensor = interpreter.getSessionInput(session, "input.1")
4.6设置输入的shape
input_format = (1, 3, 224, 224)
4.7创建MNN的tensor对象
tmp_input = MNN.Tensor(input_format, MNN.Halide_Type_Float, input_data, MNN.Tensor_DimensionType_Caffe)
shape | input_format |
data_type | MNN.Halide_Type_Int MNN.Halide_Type_Int64 MNN.Halide_Type_Float MNN.Halide_Type_Double MNN.Halide_Type_Uint8 MNN.Halide_Type_String |
data | numpy格式数据 |
dimType | MNN.Tensor_DimensionType_Tensorflow MNN.Tensor_DimensionType_Caffe MNN.Tensor_DimensionType_Caffe_C4 |
4.8将拷贝tensor数据到自身
input_tensor.copyFrom(tmp_input)
4.9运行session做网络推理
interpreter.runSession(session)
4.10获取输出
# 获取多输出interpreter.getSessionOutputAll()
# 获取单输出interpreter.getSessionOutput()
infer_result = interpreter.getSessionOutput(session)
4.11获取数据操作
net_outs = np.array(infer_result.getData())
shape = input_tensor.getShape() | 获取tensor的shape,tuple类型(元素为int) |
data_type =input_tensor.getDataType() | 获取tensor的数据类型 |
data = input_tensor.getData() | 获取tensor数据,返回类型为tuple(flattened,一维) 如果tensor是通过getSessionInput / getSessionOutput获取,其dim type可能是CaffeC4 |
input_tensor.fromNumpy(np.zeros([2,2])) | 拷贝numpy数组的数据到Tensor |
input_tensor.copyFrom(tmp_tensor) | 拷贝另一tensor数据至自身 |