【RK3588 第三篇】模型精度优化指南、和精度问题查找
在对模型进行转化的过程中会存在模型测试精度的下降。那么究竟是哪个环节造成了精度的的降低呢采用什么方式可以快速的定位精度降低的点以及快速调整对非量化模型做对比呢本文就是参照官方给出的内容对这部分进行汇总。本篇博客参考文档瑞芯微官方B站教程RKNN模型精度优化指南RKNN SDK和官方文档下载ROC-RK3588S-PC NPU使用如果您觉得本篇文章对你有帮助欢迎点赞让更多人看到这是对我继续写下去的鼓励。本系列文章都不会收费如果能再点击下方的红包打赏给博主来一杯咖啡那就太好了。一、精度排查流程下面这张图是来自于上面提供的视频的强烈建议先去看看这个视频配合着下面的图更易于理解。二、模型精度优化模拟器精度排查遵循两个“正确的前提”模拟器结果的正确是板端模型推理正确的前提“fp16 模型” 的结果正确同样是“ 量化模型” 精度正确的前提根据两个前提“量化模型” 精度问题排查顺序需要在使用rknn的build接口时 将do_quantization参数设置为False 即可以将原始模型转换为“fp16 模型”。如果“fp16 模型”输出结果错误 则需进行以下排查rknn的 config 这个接口里mean_values / std_values、input_size_list、inputs / outputsrknn的inference这个接口里inputs 和 data_format。python 环境下图像数据都是通过cv2.imread读取的图像格式为BGR大部分的caffe模型不用改其他的一般输入为RGB需要cv2.cvtColor(img, cv2.COLOR_BGR2RGB)将图像数据转为 RGB 才可以传给rknn的inference接口进行推理。通过cv2.imread读取的图像数据的layout 为 NHWC 因为data_format的默认值为NHWC 因此不需要设置data_format参数而如果模型的输入数据不是通过cv2.imread读取此时用户就必须清楚知道输入数据的 layout 并设置正确的 data_format 参数如果是图像数据也要保证其 RGB 顺序与模型的输入 RGB 顺序一致在经过“ fp16 模型” 的精度验证后 排除了“ fp16 模型” 的错误可能 就可以对模型进行量化 并进一步对“ 量化模型” 进行精度分析。 如果在“量化模型” 遇到精度问题将主要从以下几个方面进行排查quantized_dtype量化类型的选择Toolkit2-1.3.0默认值为asymmetric_quantized-8asymmetric_quantized-16目前版本暂不支持。16-bit量化和非量化float16的运算性能差异不大因此建议选择fp16rknn 的 build 接 口 的do_quantization设 为False的运算方式来代替16-bit量化quant_img_RGB2BGR一般用于caffe 模型datasetrknn 的 build 接口的量化校正集配置。 如果选择了和实际部署场景不大一致的校正集则可能会出现精度下降的问题 或者校正集的数量过多或过少都会影响精度 一般选择 50200张quantized_algorithmquantized_methodoptimization_level更多内容参考文档 NPU使用Rockchip_User_Guide_RKNN_Toolkit2_CN-1.3.0.pdf第46页2.1、精度分析工具注意该接口只能在build或hybrid_quantization_step2之后调用load原始模型应该为非量化的模型 否则会调用失败# Build modelprint(-- Building model)retrknn.build(do_quantizationQUANTIZE_ON,datasetDATASET)# DATASET来自于训练集或验证集ifret!0:print(Build model failed!)exit(ret)print(done)# Accuracy analysisprint(-- Accuracy analysis)Retrknn.accuracy_analysis(inputs[./data/0000010_20200929_F_045Y57.jpeg],targetrk3588)ifret!0:print(Accuracy analysis failed!)exit(ret)print(done)rknn.build是为了构建RKNN模型rknn.accuracy_analysis目的是对比fp32和quant后前后两种数据之间的量化误差。所以原始的模型作为参照物应该使用非量化的模型。terminal打印内容 一般认为余弦相似度低于 0.99 存在少许不一致 低于 0.98 几乎可以认为该层结果就是错误的-- Accuracy analysis Analysing : 100%|████████████████████████████████████████████████| 295/295 [00:0000:00, 320.01it/s] Preparing : 100%|████████████████████████████████████████████████| 295/295 [00:0100:00, 209.50it/s] AccuracyAnalysising : 100%|███████████████████████████████████████| 295/295 [01:4000:00, 3.91it/s] I target set by user is: rk3588 I Starting ntp or adb, target is RK3588 I Start adb... I Connect to Device success! I NPUTransfer: Starting NPU Transfer Client, Transfer version 2.1.0 (b5861e72020-11-23T11:50:36) D NPUTransfer: Transfer spec local:transfer_proxy D NPUTransfer: Transfer interface successfully opened, fd 3 D RKNNAPI: D RKNNAPI: RKNN VERSION: D RKNNAPI: API: 1.3.0 (121b661 build: 2022-04-29 11:07:20)(null) D RKNNAPI: DRV: rknn_server: 1.3.0 (121b661 build: 2022-04-29 11:11:57) D RKNNAPI: DRV: rknnrt: 1.3.0 (c193be3712022-05-04T20:16:22) D RKNNAPI: D NPUTransfer: Transfer client closed, fd 3 adbd is already running as root /data/dumps/: 897 files pulled. 35.7 MB/s (1749757536 bytes in 46.729s) Save Tensors to txt: 100%|████████████████████████████████████████| 299/299 [00:3400:00, 8.73it/s] Calculate Distance: 100%|█████████████████████████████████████████| 296/296 [02:1100:00, 4.17it/s] # quant_error: calculate the quantize errors. # entire: errors between golden and simulator. # per_layer: compare to entire, the input of each layer is come from golden # runtime_error: calculate the runtime errors. # simu_err: errors between simulator and runtime. # golden_err: errors between golden and runtime. layer_name quant_error runtime_error entire per_layer simu_err golden_err -------------------------------------------------------- images 1.000000 1.000000 1.000000 1.000000 254 1.000000 1.000000 1.000000 1.000000 256 1.000000 1.000000 0.999999 0.999999 257 0.999999 1.000000 0.999990 0.999991 259 1.000000 1.000000 0.999993 0.999993 260 1.000000 1.000000 0.999994 0.999994 262 1.000000 1.000000 0.999995 0.999995 263 1.000000 1.000000 0.999994 0.999994 265 1.000000 1.000000 0.999993 0.999993 266 1.000000 1.000000 0.999994 0.999995 268 0.999999 1.000000 0.999994 0.999994 269 1.000000 1.000000 0.999997 0.9999982.2、检查数据输入2.3、检查rknn.config配置参数和量化方法2.4、量化配置参数精度对比FP32也叫做 float32两种叫法是完全一样的全称是Single-precision floating-point(单精度浮点数)FP16也叫做 float16两种叫法是完全一样的全称是Half-precision floating-point(半精度浮点数)注意toolkit2-1.3.0下量化默认就是int8不支持float16目前最高版本是1.5.0, 2023.07.04发布同样不支持float16不启用量化do_quantizationFalse就是fp16精度rknn.config中quantized_algorithm、、quantized_method、optimization_level目前都是使用的默认值这个也可以进行修改用处是提高精度。2.5、混合量化也可以设定proposal会自动选择可能需要混合量化的层如下设定三、QATQuantization Aware Training量化感知训练如果混合量化后的精度还是不够或者运行性能不足可以采用量化感知的方式得到一个量化后的模型。再将这个模型转换成RKNN模型。量化感知训练Quantization Aware Training是在模型中插入伪量化模块fake_quantmodule模拟量化模型在推理过程中进行的舍入rounding和钳位clamping操作从而在训练过程中提高模型对量化效应的适应能力获得更高的量化模型精度 。在这个过程中所有计算包括模型正反向传播计算和伪量化节点计算都是以浮点计算实现的在训练完成后才量化为真正的int8模型。Pytorch官方从1.3版本开始提供量化感知训练API只需修改少量代码即可实现量化感知训练。四、总结在上一篇RKNN的文章中对量化与非量化的模型进行了占用内存和效率的对比发现非量化的模型占用内存更多和推理时间更长。但是非量化的结果会比量化的精度降低更少。而对于由于量化降低的模型精度可以参照本篇文章一一排查确认降低精度的点。可以知道1.在3588的toolkit2-1.3.0下量化默认就是int8不支持float16但是非量化下是可以到fp16的目前最高版本是1.5.0, 2023.07.04发布同样不支持float162.rknn.config中quantized_algorithm、quantized_method、optimization_level目前都是使用的默认值这个也可以进行修改用处是提高精度2种方式可以改使用非量化的模型这样就是fp16的版本在非量化下build后的模型accuracy_analysis准确度分析能做到0.9999与onnx版本基本一致采用非量化rknn模型与预测与本地pytorch做对比调整配置config内的quantized_algorithm、quantized_method、optimization_level参数本篇只是做一个记录对于实践测试发现的问题也会在这里进行记录。如果你也关注这个问题欢迎收藏、点赞。