前言
一、基础介绍
在PTQ模型后量化过程中,通常情况下造成精度损失的主要原因可能有以下几点:
敏感节点量化问题。模型中的一部分节点对量化比较敏感会引入较大误差;
节点量化误差累积问题。模型中各个节点的量化误差累积导致模型整体出现较大的校准误差,主要包含:权重量化导致的误差累积、激活量化导致的误差累积以及全量量化导致的误差累积。
- 获取节点量化敏感度;
- 获取模型累积误差曲线;
- 获取指定节点的数据分布;
- 获取指定节点输入数据通道间数据分布箱线图等。
- 校准模型和校准数据的准备。校准模型在模型转换过程中为常态化保存,无需用户额外操作,为模型转换的输出目录model_output下的calibrated_model;校准数据的保存需要用户在Yaml文件中的模型参数组中增加如下参数配置(配置后精度Debug功能同时开启,但需要用户重新编译一次模型,编译等级可以配置为O0以减少编译时间):
- 通过import horizon_nn.debug as dbg导入Debug模块(使用命令行则无需导入),加载校准模型和校准数据;
通过精度Debug工具提供的API或者命令行,对精度损失明显的模型进行分析。详细的流程以及分析见后文。
激活(activation)校准节点。激活校准节点的输入是当前节点的上一个节点的输出,并基于当前激活校准节点中保存的量化参数对输入数据进行量化和反量化后输出;
权重(weight)校准节点。权重校准节点的输入是模型的原始浮点权重,并基于当前权重校准节点中保存的量化参数对输入的原始浮点权重进行量化和反量化后输出。
分别获取权重校准节点和激活校准节点的量化敏感度;
根据step1的结果,分别取权重校准节点的top5和激活校准节点的top5绘制其数据分布;
针对step2获取的节点,分别绘制其通道间数据分布的箱线图;
绘制分别只量化权重和只量化激活的累积误差曲线。
首先根据累积误差曲线判断模型量化掉点是由激活量化导致的还是由权重量化导致的,确定是激活量化问题还是权重量化问题。如果激活和权重的单独量化误差不明显,可以判断是两者共同作用导致的。
对于激活量化问题,根据激活节点的量化敏感度排序确定敏感节点;对于权重量化问题,根据权重节点的量化敏感度排序确定敏感节点;对于激活和权重量化问题,计算普通节点的量化敏感度并排序,确定敏感节点。
- 获取量化敏感节点后,进行部分节点以较高精度量化或部分节点不量化测试。在J5工具链上,可以对敏感节点设置Int16量化,Int16量化调优工具的使用参考社区文章PTQ精度调优手段—设置Int16量化,同时也可以让敏感节点run_on_cpu。XJ3工具链暂不支持用户手动设置节点以Int16精度量化,可以让敏感节点run_on_cpu。
同时还可以根据敏感节点数据分布直方图以及通道间数据分布的箱线图来明确优化方向,例如激活敏感节点数据分布不均匀则可以通过优化模型结构来改善,权重敏感节点数据分布不均匀则建议使用QAT等。
- 指定单节点量化/不量化: 如下配置意为分别只量化`Conv_2`和`Conv_90`并保持其他节点不量化,计算累积误差曲线; 或分别解除量化`Conv_2`和`Conv_90`并保持其他节点量化,计算累积误差曲线。 **API配置方式为:**`quantize_node=['Conv_2', 'Conv_90']`/`non_quantize_node=['Conv_2', 'Conv_90']` **命令行配置方式为:**`-q ['Conv_2', 'Conv_90']`/`-nq ['Conv_2', 'Conv_90']`
- 指定多个节点量化/不量化: 如下配置意为分别只量化`Conv_2`以及只量化`Conv_2`和`Conv_90`并保持其他节点不量化,计算累积误差曲线; 或分别解除量化`Conv_2`以及解除量化`Conv_2`和`Conv_90`并保持其他节点量化,计算累积误差曲线。 **API配置方式为:**`quantize_node=[['Conv_2'], ['Conv_2', 'Conv_90']]`/`non_quantize_node=[['Conv_2'], ['Conv_2', 'Conv_90']]` **命令行配置方式为:**`-q [['Conv_2'], ['Conv_2', 'Conv_90']]`/`-nq [['Conv_2'], ['Conv_2', 'Conv_90']]`
- 按照量化敏感度排序选择节点量化/不量化:

