十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

MNN 模型转换工具 MNNConvert 实战指南:多格式转换、图优化、量化压缩与正确性校验

MNN 模型转换工具 MNNConvert 实战指南:多格式转换、图优化、量化压缩与正确性校验 MNN 模型转换工具 MNNConvert 实战指南多格式转换、图优化、量化压缩与正确性校验【免费下载链接】MNNMNN: A blazing-fast, lightweight inference engine battle-tested by Alibaba, powering high-performance on-device LLMs and Edge AI.项目地址: https://gitcode.com/GitHub_Trending/mn/MNNMNN 的模型转换工具 MNNConvert 负责将 TensorFlow、TFLite、Caffe、ONNX、TorchScript 等格式的模型转换为 MNN 推理格式.mnn是模型部署到 MNN 引擎前的必经环节。本文围绕 官方转换文档 完整展开从各参数含义与取舍、各格式的标准转换命令、--testdir正确性校验体系到 MNN 与 Json 的双向转换、模型 Dump 与 MNN2QNNModel 等进阶工具帮助读者完整掌握模型上端侧转换、压缩与问题排查的全流程。工具入口与源码结构MNNConvert 的可执行文件由 tools/converter/CMakeLists.txt 在MNN_BUILD_CONVERTER选项开启时构建入口实现位于 tools/converter/source/MNNConverter.cppint main(int argc, char *argv[]) { modelConfig modelPath; // parser command line arg auto res MNN::Cli::initializeMNNConvertArgs(modelPath, argc, argv); if (!res) { return modelPath.cliExitCode; } // Convert return MNN::Cli::convertModel(modelPath) ? 0 : 1; }从源码结构看所有命令行参数由 tools/converter/include/cli.hpp 中定义的Cli类解析到modelConfig结构随后统一走Cli::convertModel完成转换。转换器按框架拆分为独立模块均位于tools/converter/source/下tensorflow/、onnx/、tflite/、caffe/、torch/、optimizer/图优化、compression/量化压缩等对应的转换器类声明在 tools/converter/include 目录中如onnxConverter.hpp、torchConverter.hpp。需要注意两点构建前提TorchScript 转换需要显式开启-DMNN_BUILD_TORCHON见 tools/converter/CMakeLists.txt 中MNN_BUILD_TORCH选项默认关闭TF/TFLite/ONNX/Caffe 转换依赖 ProtobufCMake 会优先使用仓库内置的3rd_party/protobuf否则find_package(Protobuf REQUIRED)。从源码编译的完整流程可参考 docs/compile/other.md若通过pip install MNN安装可直接使用内置的mnnconvert见 docs/tools/python.md。MNNConvert 参数说明以下为官方文档给出的完整参数列表./MNNConvert -h输出是日常转换最核心的参考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 --batch arg 如果模型时输入的batch是动态的可以指定转换后的batch数 --keepInputFormat 是否保持原始模型的输入格式默认为是 --optimizeLevel arg 图优化级别默认为1 - 0 不执行图优化仅针对原始模型是MNN的情况 - 1 保证优化后针对任何输入正确 - 2 保证优化后对于常见输入正确部分输入可能出错 --optimizePrefer arg 图优化选项默认为0 - 0正常优化 - 1优化后模型尽可能小 - 2优化后模型尽可能快 --prototxt arg caffe模型结构描述文件, ex: *.prototxt --MNNModel arg 转换之后保存的MNN模型文件名, ex: *.mnn --fp16 将conv/matmul/LSTM的float32参数保存为float16 模型将减小一半精度基本无损运行速度和float32模型一致 --bizCode arg MNN模型Flag, ex: MNN --debug 使用debug模型显示更多转换信息 --forTraining 保存训练相关算子如BN/Dropoutdefault: false --weightQuantBits arg arg2~8此功能仅对conv/matmul/LSTM的float32权值进行量化 仅优化模型大小加载模型后会解码为float32量化位宽可选2~8 不开启动态量化的情况下运行速度和float32模型一致。8bit时精度基本无损模型大小减小4倍 default: 0即不进行权值量化 --weightQuantAsymmetric 与weightQuantBits结合使用决定是否用非对称量化默认为true --compressionParamsFile arg 使用MNN模型压缩工具箱生成的模型压缩信息文件或根据用户提供的量化参数来生成对应的量化模型量化参数文件可参考tools/converter/user_provide_quant_params.json 。如果文件不存在且开启了weightQuantBits等量化功能会在相应路径生成模型压缩信息文件(json格式)可后续编辑 --saveStaticModel 固定输入形状保存静态模型 default: false --targetVersion arg 兼容旧的推理引擎版本例如1.2f --customOpLibs arg 用户自定义Op库用于TorchScript模型中自定义算子的实现如libmy_add.so --info 当-f MNN时打印模型基本信息输入名、输入形状、输出名、模型版本等 --authCode arg 认证信息指定模型的认证信息可用于鉴权等逻辑 --inputConfigFile arg 保存静态模型所需要的配置文件, ex: ~/config.txt。文件格式为 input_names input0,input1 input_dims 1x3x224x224,1x3x64x64 --testdir arg 测试转换 MNN 之后MNN推理结果是否与原始模型一致。 arg 为测试数据的文件夹生成方式参考 正确性校验 一节 --thredhold arg 当启用 --testdir 后设置正确性校验的误差允可范围 若不设置默认是 0.01 --JsonFile arg 当-f MNN并指定JsonFile时可以将MNN模型转换为Json文件 --alignDenormalizedValue arg 可选值{0, 1} 默认为1, 当float(|x| 1.18e-38)会被视为0 --detectSparseSpeedUp 检测权重是否使用稀疏化加速/压缩有可能减少模型大小但增大模型转换时间 --saveExternalData 将权重常量等数据存储在额外文件中默认为0也就是false --useGeluApproximation 在进行Gelu算子合并时使用Gelu的近似算法默认为1 也就是true --useOriginRNNImpl LSTM和GRU算子是否使用原始算子实现默认关闭。若开启性能可能提升但无法进行LSTM/GRU的量化重点参数详解--optimizeLevel与--optimizePrefer图优化的两个正交维度。--optimizeLevel控制优化的激进程度默认的 1 级保证任意输入下优化结果都正确2 级只保证常见输入正确换取更强的优化空间0 级则完全跳过图优化仅对源模型本身就是 MNN 的场景有意义。--optimizePrefer在优化时选择偏向0 为常规优化1 偏向模型体积最小2 偏向推理速度最快。图优化的具体实现位于 tools/converter/source/optimizer 模块。--weightQuantBits纯体积优化的权值量化。官方文档特别强调该选项仅对 conv/matmul/LSTM 的 float32 权值做 2~8 bit 量化只优化模型大小——加载模型时权值会解码回 float32因此运行速度与 float32 模型一致8bit 时精度基本无损模型大小约减小 4 倍。可与--weightQuantAsymmetric默认true组合控制是否采用非对称量化。--compressionParamsFile与压缩工具箱联动的量化参数文件。该参数可传入 MNN 模型压缩工具箱生成的 json 压缩信息文件或用户自建的量化参数文件格式参考仓库中的 tools/converter/user_provide_quant_params.json。若文件不存在且开启了--weightQuantBits等量化功能转换器会在该路径自动生成一份可编辑的量化参数 json供二次调优后重新转换——这是先探测、后定制的两阶段量化流程。--fp16与权值量化互不冲突的存储压缩。将 conv/matmul/LSTM 的 float32 参数以 float16 存储模型体积减半、精度基本无损、运行速度与 float32 模型一致属于零性能代价的压缩手段可与--weightQuantBits分别评估后组合使用。--keepInputFormat与后端数据布局的取舍。官方文档说明2指出如果使用 Interpreter-Session C 接口开发由于 NC4HW4 布局便于与 ImageProcess 结合转换时可加--keepInputFormat0让模型使用 MNN 自动内存布局。--saveStaticModel--inputConfigFile静态形状模型。需要固定输入形状时例如部分 NPU 后端只支持静态形状用--saveStaticModel保存静态模型并通过--inputConfigFile提供的配置文件指定输入名与形状格式为input_names input0,input1 input_dims 1x3x224x224,1x3x64x64--testdir/--thredhold转换时的就地正确性校验。指定--testdir指向一组测试数据文件夹后转换器会对比 MNN 推理结果与原始模型结果--thredhold设置误差允许范围默认为 0.01。测试数据的生成方式见下文正确性校验一节。TorchScript 专属参数。--customOpLibs可传入用户自定义 Op 的 so 库如libmy_add.so用于 TorchScript 模型中自定义算子的转换--useOriginRNNImpl决定 LSTM/GRU 是否走原始算子实现——开启后性能可能提升但代价是无法对 LSTM/GRU 做量化。各格式模型转换到 MNNTensorFlow to MNN./MNNConvert -f TF --modelFile XXX.pb --MNNModel XXX.mnn --bizCode biz注意*.pb必须是 frozen model不能使用 saved_model。TensorFlow Lite to MNN./MNNConvert -f TFLITE --modelFile XXX.tflite --MNNModel XXX.mnn --bizCode bizCaffe to MNN./MNNConvert -f CAFFE --modelFile XXX.caffemodel --prototxt XXX.prototxt --MNNModel XXX.mnn --bizCode bizCaffe 模型需要同时提供权重文件与--prototxt网络结构描述文件。ONNX to MNN./MNNConvert -f ONNX --modelFile XXX.onnx --MNNModel XXX.mnn --bizCode bizTorchScript to MNN./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)MNN to Json / Json to MNN想了解 MNN 模型的具体结构与输入输出信息时可将模型转为 Json 查阅./MNNConvert -f MNN --modelFile XXX.mnn --JsonFile XXX.json反过来可以对 Json 进行编辑修改后再转回 MNN 模型达到修改微调模型的目的./MNNConvert -f JSON --modelFile XXX.json --MNNModel XXX.mnn正确性校验为便于开发者排查问题MNN 针对 PB / Tflite / Onnx / TorchScript 提供了一组正确性校验脚本位于 tools/script 目录检查 MNN 推理结果是否与原始模型一致testMNNFromTf.py适用 pbtestMNNFromTflite.py适用 tflitetestMNNFromOnnx.py适用 onnxtestMNNFromTorch.py适用 pt (torchscript)注意事项如果模型是动态输入形状MNN 在脚本中默认不固定部分为 1有可能在 Tensorflow / OnnxRuntime / Torch 验证阶段报错。此时需要修改脚本中对应的输入部分比如testMNNFromOnnx.py中的run_onnx(self)函数把输入替换为有效的输入形状和内容。对于由 TorchScript 转换的模型一般都需要自行修改testMNNFromTorch.py中的输入信息来测试。如果模型输出层是 Identity 产生的会因为 MNN 图优化的缘故丢失此时需要校验上一层的输出即在脚本后接输出名来测试如python3 ../tools/script/testMNNFromTf.py XXX.pb $NAME$。前置环境测试 pb / tflite安装tensorflowpip install tensorflow测试 onnx安装onnxruntimepip install onnxruntime测试 torchscript安装torchpip install torch【可选】MNN 模型转换工具编译完成编译后产生MNNConvert可执行文件使用方式在 MNN 的build目录包含MNNConvert下运行python3 ../tools/script/testMNNFromTf.py SRC.pb # Onnx 为 testMNNFromOnnx.pyTflite 类似若最终结果为TEST_SUCCESS则表示 MNN 的模型转换与运行结果正确。若路径下没有编译好的MNNConvert可执行文件脚本会回退使用 pymnn 进行校验。以 ONNX 为例的完整实例来自官方文档的真实运行日志cd build cmake -DMNN_BUILD_CONVERTERON .. make -j4 python ../tools/script/testMNNFromOnnx.py mobilenetv2-7.onnx # 模型转换后推理并与ONNXRuntime结果对比 Dir exist onnx/test.onnx tensor(float) [output] inputs: input onnx/ outputs: onnx/output.txt (1, 1000) onnx/ Test onnx Start to Convert Other Model Format To MNN Model... [21:09:40] /Users/wangzhaode/copy/AliNNPrivate/tools/converter/source/onnx/onnxConverter.cpp:40: ONNX Model ir version: 6 Start to Optimize the MNN Net... 108 op name is empty or dup, set to Const108 109 op name is empty or dup, set to BinaryOp109 110 op name is empty or dup, set to Unsqueeze110 112 op name is empty or dup, set to Unsqueeze112 97 op name is empty or dup, set to Unsqueeze97 98 op name is empty or dup, set to Const98 inputTensors : [ input, ] outputTensors: [ output, ] Converted Success! input output: output output: (1, 1000, ) TEST_SUCCESS默认只支持限定数值范围的输入随机生成如需修改请自行修改脚本。出错定位与解决出现Test Error或者 MNN 的 crash 可直接反馈提 issue 或到钉钉群反馈。如需自查脚本提供 debug 功能可方便定位出错的 layer / op示例python3 testMNNFromOnnx.py SRC.onnx DEBUG。以 ONNX 为例的错误排查过程假设转换器中某算子实现被人为改错官方文档以将 Binary_ADD 实现修改为错误实现作实验运行脚本后输出TESTERROR表明模型可以转换但推理结果有错误python ../tools/script/testMNNFromOnnx.py mobilenetv2-7.onnx ... output: (1, 1000, ) TESTERROR output value error : absMaxV:5.814904 - DiffMax 32.684010 Error for output output Save mnn result to .error director对于推理出错的情况可以逐层校验定位错误层官方文档示例采用类似二分的方式逐层验证# test layer output 365: ERROR python ../tools/script/testMNNFromOnnx.py mobilenetv2-7.onnx 365 ... 365: (1, 32, 28, 28, ) TESTERROR 365 value error : absMaxV:3.305553 - DiffMax 5.069034 Error for output 365 Save mnn result to .error director # binary search test layers ... # test layer output 339: ERROR, 339s inputs is [489, 498] python ../tools/script/testMNNFromOnnx.py mobilenetv2-7.onnx 339 ... TESTERROR 339 value error : absMaxV:3.704849 - DiffMax 5.504766 # test layer output 489: SUCCESS python ../tools/script/testMNNFromOnnx.py mobilenetv2-7.onnx 489 ... TEST_SUCCESS # test layer output 498: SUCCESS python ../tools/script/testMNNFromOnnx.py mobilenetv2-7.onnx 498 ... TEST_SUCCESS # so bug is layer 339对 ONNX 模型还可以使用自动定位功能在模型参数后加DEBUG脚本会执行基于支配树的二分查找直至找到错误层python ../tools/script/testMNNFromOnnx.py mobilenetv2-7.onnx DEBUG ... Test Node : Conv_14 True ### First Error Node is : Add_15算子支持列表查询各框架下转换器支持的算子列表可以直接通过--OP打印用于判断某算子是否被覆盖./MNNConvert -f CAFFE --OP ./MNNConvert -f TF --OP ./MNNConvert -f ONNX --OP ./MNNConvert -f TORCH --OP模型打印Dump 成可读的类 Json 格式将 MNN 模型文件 dump 成可读的类 json 格式文件方便对比原始模型参数也可以对模型进行修改。可以使用MNNConvert或MNNDump2Json将模型转换成 Json 文件修改后还可以使用MNNConvert或MNNRevert2Buffer将 Json 文件转回 MNN 模型MNNDump2Json/MNNRevert2Buffer两个可执行文件分别由 tools/converter/source/MNNDump2Json.cpp 和 tools/converter/source/MNNRevert2Buffer.cpp 构建./MNNDump2Json mobilenet_v1.mnn mobilenet_v1.json # do some change in mobilenet_v1.json ./MNNRevert2Buffer mobilenet_v1.json mobilenet_v1_new.mnnDump 结果展示了完整的网络结构例如cat mobilenet_v1.json { oplists: [ { type: Input, name: data, outputIndexes: [ 0 ] , main_type: Input, main: { dims: [ 1, 3, 224, 224 ] , dtype: DT_FLOAT, dformat: NC4HW4 } , defaultDimentionFormat: NHWC } , { type: Convolution, name: conv1, inputIndexes: [ 0 ] , outputIndexes: [ 1 ] , main_type: Convolution2D, main: { common: { dilateX: 1, dilateY: 1, strideX: 2, strideY: 2, kernelX: 3, kernelY: 3, padX: 1, padY: 1, group: 1, outputCount: 32, relu: true, padMode: CAFFE, relu6: false, inputCount: 0 } , weight: [ -0.0, -0.0, 0.0, -0.0, ... ] , bias: [ -0.000004, 0.694553, 0.416608, ... ] } , defaultDimentionFormat: NHWC } , ... ] , tensorName: [ data, conv1, conv2_1/dw, conv2_1/sep, ... ] , sourceType: CAFFE, bizCode: AliNNTest, tensorNumber: 0, preferForwardType: CPU }从示例可以看到Json 中记录了每个 op 的类型与连接关系inputIndexes/outputIndexes、卷积的完整参数stride、padding、group、outputCount、relu 等以及 weight/bias 数值末尾还带有sourceType、bizCode等全局元信息——这正是用Json 中转方式微调模型时可靠操作的依据。Python 版 mnnconvertMNN 提供预编译的 MNNConvert Python 工具mnnconvertpip install MNN后即可在 Python 中完成格式转换具体用法参考 docs/tools/python.md。MNN2QNNModel生成 QNN 后端的替代模型与离线产物功能该工具针对特定的高通硬件架构为原始的 MNN 模型生成 MNN-QNN 后端需要的替代模型以及 QNN 离线产物。目前支持静态形状的模型以及有限输入形状组合的模型。运行环境要求该工具必须在 x86_64 架构的 Linux 系统上运行部分 QNN SDK 中的离线工具必须在此环境中运行。编译添加额外的 CMAKE 变量并编译-DMNN_QNNON -DMNN_QNN_CONVERT_MODEON -DMNN_WITH_PLUGINOFF -DMNN_BUILD_TOOLSON -DMNN_SUPPORT_TRANSFORMER_FUSEON用法./MNN2QNNModel qnnSDKPath socId hexagonArch srcMNNPath outputDir [totalShapeNum] [inputShape1] [inputShape2] ...参数配置说明参数说明是否必须qnnSDKPathQNN SDK 的根目录路径。是socId目标 SoC 的 ID。常用 ID 参考8Gen2 -43, 8Gen3 -57, 8 Elite -69。其他型号请参考高通官方文档。是hexagonArchHexagon 架构版本。常用架构参考8Gen2 -73, 8Gen3 -75, 8 Elite -79。其他型号请参考高通官方文档。是srcMNNPath待转换的原始 MNN 模型文件路径.mnn文件。是outputDir用于存放生成产物的目录。工具会在此目录下生成一个新的.mnn文件替代模型和一个.bin文件QNN 离线产物。是[totalShapeNum]需要支持的动态输入形状的总数量。否[inputShapeN]具体的输入形状配置。根据totalShapeNum的数量提供相应个数的形状描述。形状信息可以是以下两种格式之一1.形状字符串例如1x3x512x512。对于多输入模型用下划线_分隔例如1x3x512x512_1x256。2.MNN 文件路径提供一个包含所需输入信息的.mnn文件路径。否示例假设 QNN SDK 路径为/path/to/qnn/sdk目标设备为 8Gen3socId57, hexagonArch75原始模型为model.mnn输出目录为/path/to/output使用默认输入形状进行转换./MNN2QNNModel /path/to/qnn/sdk 57 75 model.mnn /path/to/output为单输入模型指定单种输入形状./MNN2QNNModel /path/to/qnn/sdk 57 75 model.mnn /path/to/output 1 1x3x256x256为单输入模型指定多种输入形状./MNN2QNNModel /path/to/qnn/sdk 57 75 model.mnn /path/to/output 2 1x3x256x256 1x3x512x512为多输入模型指定多种输入形状./MNN2QNNModel /path/to/qnn/sdk 57 75 model.mnn /path/to/output 2 1x3x256x256_1x100 1x3x512x512_1x200产物工具执行成功后会在指定的outputDir目录下生成两个文件文件名由原始模型名、SoC ID 和 Hexagon 架构版本共同决定格式为原始模型名_socId_hexagonArch.suffix替代模型.mnn文件文件名格式为原始模型名_socId_hexagonArch.mnn。QNN 离线产物.bin文件包含优化后的模型和权重文件名格式为原始模型名_socId_hexagonArch.bin。例如上述示例的产物位于/path/to/output/目录下/path/to/output/ ├── model_57_75.mnn # 替代模型 └── model_57_75.bin # QNN离线产物关于如何使用这些产物可进一步参考 QNN 离线构图模式的使用说明。compilefornpuLLM 相关模型的分段 NPU 转换对于较复杂的模型可以通过compilefornpu及对应的npu_convert.py分段转换为 NPU。该工具目前仅在 LLM 相关模型的转换中使用属于 LLM 端侧部署链路中的专用转换工具。小结MNN 的转换工具体系以 MNNConvert 为核心覆盖格式转换 → 图优化 → 体积压缩 → 正确性验证 → 结构级修改的完整链路格式转换支持 TF(frozen pb)、TFLite、Caffe、ONNX、TorchScript需-DMNN_BUILD_TORCHON与 MNN/Json 互转体积优化可组合使用--fp16体积减半、--weightQuantBits加载时解码速度不变与--compressionParamsFile两阶段定制量化参数见 tools/converter/user_provide_quant_params.json正确性校验用 tools/script 下的testMNNFrom*.py脚本对比原始框架推理结果支持指定层校验与DEBUG支配树自动定位结构级调试用MNNDump2Json/MNNRevert2Buffer完成 MNN ↔ Json 双向转换面向高通 NPU 的MNN2QNNModel则负责生成 QNN 替代模型与离线产物。理解这些工具参数背后的取舍——优化级别与正确性保证、量化对体积和速度的不同影响、静态/动态形状约束——是高效完成模型端侧部署与问题定位的关键。【免费下载链接】MNNMNN: A blazing-fast, lightweight inference engine battle-tested by Alibaba, powering high-performance on-device LLMs and Edge AI.项目地址: https://gitcode.com/GitHub_Trending/mn/MNN创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表