RKNN模型部署实战(3)—— 模型转换与性能调优
1. RKNN模型转换基础第一次接触RKNN模型转换的朋友可能会觉得这个过程有点复杂但其实只要掌握了核心步骤你会发现它就像搭积木一样简单。RKNN是Rockchip专门为自家NPU设计的模型格式通过RKNN-Toolkit工具链我们可以把常见的PyTorch、TensorFlow等框架训练的模型转换成能在Rockchip芯片上高效运行的格式。我刚开始做模型转换时经常遇到各种报错后来发现大部分问题都出在环境配置上。这里建议大家一定要使用Ubuntu系统18.04或20.04版本最稳定Python环境推荐3.6或3.8版本。安装RKNN-Toolkit时记得先装好依赖库否则后面会各种报错。模型转换的基本流程是这样的先加载原始模型比如PyTorch的.pt文件然后配置转换参数接着进行量化可选最后导出.rknn文件。听起来简单但每个环节都有不少坑等着我们。比如量化这个步骤如果数据集没选好转换后的模型精度可能会大幅下降。2. 量化参数优化实战量化是模型转换中最关键的环节之一它直接影响模型在设备上的推理速度和精度。简单来说量化就是把浮点参数转换成低精度的定点数这样可以减少模型大小、提升推理速度但代价是可能会损失一些精度。我在项目中遇到过量化后模型完全失效的情况检测框一个都出不来。后来发现是量化数据集的问题——用了和训练数据分布完全不同的图片。现在我的做法是从验证集中随机抽取200-300张有代表性的图片确保覆盖各种场景。比如做车辆检测时我会包含白天、夜晚、雨天等各种条件下的车辆图片。量化参数设置也有讲究。在rknn.config()中mean_values和std_values一定要和模型训练时用的参数一致。我见过有人直接抄官方示例的参数结果模型精度惨不忍睹。另外batch_size设置大一些比如200可以提高量化稳定性但如果内存不够可以设小点如10并增加epochs。# 量化配置示例 rknn.config( mean_values[[123.675, 116.28, 103.53]], # 必须与训练时一致 std_values[[58.395, 57.12, 57.375]], quantized_dtypeasymmetric_quantized-u8, # 非对称量化 quantized_algorithmnormal, # 也可以试试mmse算法 quantized_methodchannel )3. 模型预编译技巧预编译是个很有用的功能它能显著减少模型在设备上的首次加载时间。原理是把模型编译成更适合特定NPU硬件执行的格式。但要注意预编译后的模型只能在对应硬件上运行无法在模拟器测试。我在实际项目中发现对于RV1126这类性能较低的设备开启预编译(pre_compileTrue)能让模型加载时间从秒级降到毫秒级。但调试阶段建议先关闭等模型稳定后再开启。另外如果NPU驱动更新了预编译的模型需要重新生成。ret rknn.build( do_quantizationTrue, datasetquant_dataset.txt, # 量化数据集 pre_compileTrue # 开启预编译 )预编译还有个隐藏技巧如果模型要部署到多个同型号设备上只需要在一台设备上预编译生成的.rknn文件可以直接用在其他设备上能节省大量时间。4. 精度损失分析与解决模型转换后精度下降是最让人头疼的问题。根据我的经验精度损失通常来自三个方面量化误差、算子不支持、前后处理不一致。遇到精度下降时我建议先做对比测试用同样的输入数据分别跑原始模型和RKNN模型比较各层输出。RKNN-Toolkit提供了eval_perf和eval_memory接口可以评估每层的误差。如果发现某一层误差特别大可能就是问题所在。对于算子不支持的情况可以尝试以下解决方案修改模型结构替换不支持的算子联系Rockchip技术支持看是否有新版本支持实现自定义算子比较复杂新手慎用前后处理不一致也是个常见坑点。特别是通道顺序RGB/BGR和归一化参数一定要和训练时完全一致。我习惯在代码里加大量assert来验证这些参数避免低级错误。5. 性能调优实战模型转换完成后下一步就是性能调优了。RKNN提供了丰富的性能分析工具可以帮助我们找到瓶颈。首先关注eval_perf的输出看看哪层耗时最多。对于卷积网络通常是后面的大卷积层比较耗时。这时候可以尝试调整optimization_level0-3越高优化越激进修改量化方式试试动态定点量化调整输入尺寸适当减小# 性能评估示例 perf_result rknn.eval_perf(inputs[test_image], is_printTrue) memory_detail rknn.eval_memory()内存使用也很关键特别是对于内存有限的嵌入式设备。eval_memory可以显示各层内存占用。如果发现内存不足可以考虑减小batch_size使用模型分段技术将大模型拆成多个小模型优化模型结构减少中间结果6. 模型部署技巧模型转换调优完成后就该部署到设备上了。这里分享几个实用技巧首先是adb连接问题。有时候设备连接不稳定建议使用高质量的USB线检查设备ID是否正确重启adb服务模型加载也有讲究。首次加载会比较慢特别是没有预编译的大模型。可以在应用启动时预先加载模型而不是等到要用的时候才加载。推理时的输入数据要注意确保数据格式正确通常是NHWC数据类型匹配uint8/int8必要时使用inputs_pass_through参数# 设备端推理示例 outputs rknn.inference( inputs[input_data], data_formatnhwc, inputs_pass_through[0] # 透传模式 )7. 常见问题解决方案在实际项目中我遇到过各种奇怪的问题这里总结几个典型的问题1模型转换成功但推理结果全是乱码解决检查输入数据的预处理特别是归一化参数。有一次我忘了除255结果完全不对。问题2量化后小目标检测不到了解决增加量化数据集中小目标的样本比例或者尝试不同的量化算法。问题3模型在PC上测试正常但设备上运行崩溃解决很可能是内存不足。尝试减小输入尺寸或batch_size也可以用eval_memory检查内存使用。问题4推理速度比预期慢很多解决检查是否启用了NPU加速。有时候默认会回退到CPU执行。最后给个实用建议一定要保存每个版本的转换配置和结果。当出现问题时可以快速回退到稳定版本而不是从头开始。我习惯用Git管理这些配置文件每次修改都有记录。