【RK3588 第三篇】模型精度优化指南、和精度问题查找

在对模型进行转化的过程中,会存在模型测试精度的下降。那么,究竟是哪个环节造成了精度的的降低呢?

采用什么方式可以快速的定位精度降低的点,以及快速调整,对非量化模型做对比呢?本文就是参照官方给出的内容,对这部分进行汇总。

本篇博客参考文档:

  1. 瑞芯微官方B站教程:RKNN模型精度优化指南
  2. RKNN SDK和官方文档下载:ROC-RK3588S-PC NPU使用

如果您觉得本篇文章对你有帮助,欢迎点赞 👍,让更多人看到,这是对我继续写下去的鼓励。本系列文章都不会收费,如果能再点击下方的红包打赏,给博主来一杯咖啡,那就太好了。💪

一、精度排查流程

下面这张图是来自于上面提供的视频的,强烈建议先去看看这个视频,配合着下面的图,更易于理解。

在这里插入图片描述

二、模型精度优化

在这里插入图片描述
模拟器精度排查,遵循两个“正确的前提”:

  1. 模拟器结果的正确是板端模型推理正确的前提;
  2. “fp16 模型” 的结果正确同样是“ 量化模型” 精度正确的前提

根据两个前提,“量化模型” 精度问题排查顺序:

  1. 需要在使用 rknnbuild 接口时, 将 do_quantization 参数设置为 False, 即可以将原始模型转换为“fp16 模型” 。如果“fp16 模型” 输出结果错误, 则需进行以下排查:

    • rknn 的 config 这个接口里:mean_values / std_values、input_size_list、inputs / outputs
    • rknninference 这个接口里: inputs 和 data_format。python 环境下,图像数据都是通过cv2.imread读取的,图像格式为 BGR,大部分的 caffe 模型不用改;其他的一般输入为 RGB,需要cv2.cvtColor(img, cv2.COLOR_BGR2RGB)将图像数据转为 RGB, 才可以传给rknninference接口进行推理。
    • 通过 cv2.imread 读取的图像数据的 layout 为 NHWC, 因为 data_format 的默认值为 NHWC, 因此不需要设置 data_format 参数;而如果模型的输入数据不是通过 cv2.imread 读取,此时用户就必须清楚知道输入数据的 layout 并设置正确的 data_format 参数,如果是图像数据,也要保证其 RGB 顺序与模型的输入 RGB 顺序一致
  2. 在经过“ fp16 模型” 的精度验证后, 排除了“ fp16 模型” 的错误可能, 就可以对模型进行量化, 并进一步对“ 量化模型” 进行精度分析。 如果在“量化模型” 遇到精度问题,将主要从以下几个方面进行排查:

    • quantized_dtype量化类型的选择,Toolkit2-1.3.0,默认值为 asymmetric_quantized-8asymmetric_quantized-16目前版本暂不支持。16-bit 量化和非量化(float16) 的运算性能差异不大,因此建议选择 fp16(rknn 的 build 接 口 的 do_quantization 设 为 False )的运算方式来代替16-bit量化;
    • quant_img_RGB2BGR,一般用于caffe 模型;
    • dataset,rknn 的 build 接口的量化校正集配置。 如果选择了和实际部署场景不大一致的校正集,则可能会出现精度下降的问题, 或者校正集的数量过多或过少都会影响精度( 一般选择 50~200张)
    • quantized_algorithm
    • quantized_method
    • optimization_level

更多内容,参考文档 NPU使用 Rockchip_User_Guide_RKNN_Toolkit2_CN-1.3.0.pdf第46页

2.1、精度分析工具

在这里插入图片描述
在这里插入图片描述
注意:

  1. 该接口只能在 build hybrid_quantization_step2 之后调用;
  2. load 原始模型应该为非量化的模型, 否则会调用失败
# Build model
    print('--> Building model')
    ret = rknn.build(do_quantization=QUANTIZE_ON, dataset=DATASET)  # DATASET来自于训练集,或验证集
    if ret != 0:
        print('Build model failed!')
        exit(ret)
    print('done')


    # Accuracy analysis
    print('--> Accuracy analysis')
    Ret = rknn.accuracy_analysis(inputs=['./data/0000010_20200929_F_045Y57.jpeg'],
                                 target='rk3588')
    if ret != 0:
        print('Accuracy analysis failed!')
        exit(ret)
    print('done')

rknn.build是为了构建 RKNN 模型,rknn.accuracy_analysis目的是对比fp32quant后,前后两种数据之间的量化误差。所以,原始的模型,作为参照物,应该使用非量化的模型。

terminal 打印内容( 一般认为余弦相似度低于 0.99 存在少许不一致, 低于 0.98 几乎可以认为该层结果就是错误的):

--> Accuracy analysis
Analysing : 100%|████████████████████████████████████████████████| 295/295 [00:00<00:00, 320.01it/s]
Preparing : 100%|████████████████████████████████████████████████| 295/295 [00:01<00:00, 209.50it/s]
AccuracyAnalysising : 100%|███████████████████████████████████████| 295/295 [01:40<00: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 (b5861e7@2020-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 (c193be371@2022-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:34<00:00,  8.73it/s]
Calculate Distance: 100%|█████████████████████████████████████████| 296/296 [02:11<00: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.999998 

2.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_quantization=False,就是fp16 精度;
  • rknn.configquantized_algorithm、、quantized_method、optimization_level目前都是使用的默认值,这个也可以进行修改,用处是提高精度。

2.5、混合量化

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
也可以设定proposal,会自动选择可能需要混合量化的层,如下设定:

在这里插入图片描述
在这里插入图片描述

三、QAT(Quantization Aware Training,量化感知训练)

如果混合量化后的精度,还是不够,或者运行性能不足,可以采用量化感知的方式,得到一个量化后的模型。再将这个模型转换成RKNN模型。

量化感知训练(Quantization Aware Training)是在模型中插入伪量化模块(fake_quant
module)模拟量化模型在推理过程中进行的舍入(rounding)和钳位(clamping)操作,从而在训练过程中提高模型对量化效应的适应能力,获得更高的量化模型精度 。

在这个过程中,所有计算(包括模型正反向传播计算和伪量化节点计算)都是以浮点计算实现的,在训练完成后才量化为真正的int8模型。

Pytorch官方从1.3版本开始提供量化感知训练API,只需修改少量代码即可实现量化感知训练。

在这里插入图片描述

四、总结

在上一篇RKNN的文章中,对量化与非量化的模型进行了占用内存和效率的对比,发现非量化的模型,占用内存更多和推理时间更长。

但是,非量化的结果,会比量化的精度降低更少。而对于由于量化降低的模型精度,可以参照本篇文章,一一排查,确认降低精度的点。

可以知道:
1.在3588的toolkit2-1.3.0下,量化默认就是int8,不支持float16,但是,非量化下,是可以到fp16的;(目前最高版本是1.5.0, 2023.07.04发布,同样不支持float16
2.rknn.configquantized_algorithm、quantized_method、optimization_level目前都是使用的默认值,这个也可以进行修改,用处是提高精度

2种方式可以改:

  1. 使用非量化的模型,这样就是fp16的版本,在非量化下,build后的模型accuracy_analysis准确度分析,能做到0.9999,与onnx版本基本一致,采用非量化rknn模型与预测,与本地pytorch做对比;
  2. 调整配置config内的quantized_algorithm、quantized_method、optimization_level参数

本篇只是做一个记录,对于实践测试发现的问题,也会在这里进行记录。如果你也关注这个问题,欢迎收藏、点赞。

评论 34
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

钱多多先森

你的鼓励,是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值