专栏感知PTQ精度调优手段—YOLOv8x设置Int16量化

PTQ精度调优手段—YOLOv8x设置Int16量化

芯链情报局2023-05-31
227
1

前言:

在我们进行模型后量化的过程中,往往会面临在模型性能和模型精度之间权衡的问题。具体来说,我们希望模型的全部或者绝大多数算子运行在BPU上,以Int8的精度量化,从而使模型在板端部署时有着更快的推理速度,有着更好的性能(例如较低的Latency和较高的FPS)。但是对于少数的模型,算子以Int8的精度量化会累积较多的量化误差,从而使整个模型面临潜在的量化精度损失风险,例如量化后的目标检测模型可能会面临漏框和误检的问题。而解决这一权衡问题的思路也很直观,我们可以将对Int8量化敏感的算子退而求其次,使用更高的量化精度进行量化,例如使用Int16精度量化,此举可以有效地减少算子在量化时累积较多的量化误差。然而使用更高的量化精度量化算子必然会带来模型的性能损失,这就需要我们合理地选择需要进行Int16量化的算子。

那么该如何合理地选择Int16量化的算子以达到模型性能和模型精度的平衡呢?具体做法是依据后量化模型转换过程中给出的余弦相似度Cosine Similarity和其他指标如MSE,对Int8量化敏感的算子进行排序,将Int8量化误差大的算子采用Int16量化,在此过程中不断评测中间模型的性能和精度,直至达到平衡。而对于”平衡“这一概念则取决于开发者,即是愿意牺牲模型一定的性能去换取高精度还是愿意牺牲模型一定的精度去换取高性能。

本文接下来将在J5上使用YOLOv8x模型演示如何开启后量化的Int16量化功能,并展示使用Int16量化功能对模型性能和精度带来的影响。

环境与依赖:

  • 获取最新的OpenExplorer工具链开发包

  • hbdk>=3.44.3

  • horizon-nn>=0.17.1

Int16量化功能开启前:

首先从初始开始,我们配置YOLOv8x模型转换的yaml文件,完成第一次转换编译后发现模型共有2个算子运行在CPU上,为“/model.22/dfl/Softmax”和“/model.22/Mul_2”。接着我们配置yaml文件中run_on_bpu参数将这2个算子强制运行在BPU上,此外calibration_type选择default,optimize_level设置为最高优化O3,上述部分配置如下:

转换成功后利用中间产物original_float_model和optimized_float_model对齐模型输入输出数据并检验前后处理的正确性,确保可以生成正确的可视化结果且两模型推理结果保持一致,例如下图(后处理中bbox置信度阈值和IoU阈值均设置为0.2且在之后都保持不变):

浮点模型推理结果浮点模型推理结果
接着我们测试calibrated_model和quantized_model,发现模型推理无可视化结果,如下:
定点模型推理结果定点模型推理结果
此时评测模型在J5板端性能如下:

FPS

Latency/ms

单核:38.154102/双核:74.087635

26.427231

此时的模型性能为最优,但精度最低,几乎为0。

开启Int16量化功能:

1、如何开启Int16量化功能

在模型转换yaml文件calibration_parameters参数组中增加optimization参数,例如:

即可使算子类型为Add的节点以Int16精度量化。同理,想要使其他类型算子的节点以Int16精度量化,修改上面示例的算子类型即可。值得注意的是,这里针对的是同类型算子的节点,而不是单个节点,针对单个节点的Int16量化暂未开放。

在模型转换过程中,如果有个别节点不支持Int16量化或者不支持Int16输入或输出,转换工具会使这些节点保留原Int8精度量化。

2、全类型Int16量化

为了更加直观地体现Int16量化对模型性能的影响,这里探索一种极端的情况,即把模型所有支持Int16量化的算子全部采用Int16量化,optimization参数配置如下:

修改后重新进行模型转换,使用生成的calibrated_model和quantized_model进行推理,成功生成了可视化结果,如下:

Int16量化后的定点模型推理结果Int16量化后的定点模型推理结果
此时模型的精度最优,定点模型精度为:[IoU=0.50:0.95]=0.431;[IoU=0.50]=0.636。那么它的性能又会怎么样呢,在板端实测的模型性能对比如下:

性能指标

FPS

Latency/ms

开启Int16量化前

单核:38.154102/双核:74.087635

26.427231

全类型Int16量化

单核:11.419144/双核:21.690922

88.851227

开启全类型Int16量化后相比开启前,单核FPS降低了70.07%,双核FPS降低了70.72%,时延Latency增长了236.21%!!!但是别灰心,开启全类型Int16量化后的模型是性能最差的情况,我们可以关闭一些Int16量化的节点,牺牲一定的精度来换取性能的提升。

3、部分类型Int16量化

对YOLOv8x模型后量化过程进行Debug分析(PTQ Debug工具依赖最新发布的OpenExplorer开发包,详细使用方法可参见https://developer.horizon.ai/forumDetail/146176821770229921)。查看校准模型calibrated_model,模型中大量的HzSwish节点会以Int8查表的方式进行量化,过程中会累积较大的量化误差,如下:
calibrated_modelcalibrated_model
因此有必要将HzSwish节点做Int16量化以减少量化误差。此外发现部分Mul节点Int8量化的MSE较高,因此也可以做Int16量化(考虑到Conv节点做Int16量化可能会造成较大的性能损失,故先从Mul节点开始尝试),如下:
节点量化敏感度信息节点量化敏感度信息
当然同学们也可以尝试将其他节点做Int16量化,来体会Int16量化对模型性能和精度的影响。按照本文的设置,yaml文件中optimization参数配置如下:

对量化后的定点模型做精度的评测,和全类型Int16量化对比,结果如下:

量化类型

定点模型精度

全类型Int16量化

[IoU=0.50:0.95] = 0.431/[IoU=0.50] = 0.636

部分类型Int16量化

[IoU=0.50:0.95] = 0.384/[IoU=0.50] = 0.593

模型精度最多降低了10.9%,在预料之中,但是我们获得的性能增长呢,见下表:

性能指标

FPS

Latency/ms

开启Int16量化前

单核:38.154102/双核:74.087635

26.427231

部分类型Int16量化

单核:34.162637/双核:66.035364

29.559324

全类型Int16量化

单核:11.419144/双核:21.690922

88.851227

可见相比于开启全类型的Int16量化,调整之后的部分类型Int16量化牺牲了较少的精度而获得了性能上巨大的提升!!!

总结:

通过本文的演示,相信读者对于如何在后量化中开启Int16量化功能以及Int16量化对于模型性能和精度上的影响有了较为清晰的认识。在实际操作中,还需结合地平线工具链给出的算子量化相似度相关信息,以达到合理选择Int16算子的目的,从而能使模型在后量化中取得性能和精度的平衡。

感知
征程5
+1
评论1
0/1000
  • Lv.1

    您好,我是目前在调研J5开发板的yolov8实际表现,能问一下您这个FPS测试图片大小吗,以及目前J5有官方部署教程和方法吗,我在论坛内未搜索到,谢谢您得帮助

    2024-02-28
    0
    0