前言
最近一段时间在搞模型量化(之前量化基础为0),基本上查到了90%以上的成熟量化方案,QAT的方案真的非常不成熟,基本没有开源好用的方案。赛灵思挺成熟但仅针对自己的框架,修改代价太大了。阿里的框架不成熟,至少我在看代码的时候,他还在Fix-Bug。ONNX挺成熟,但使用人数基本没有,其作为IR工具,很少有人拿他来训练。。。。量化资料虽然多,但基本都是跑一个分类模型,至于检测的量化少之又少。
目前状态
环境:
- MMDetectionV2.15,已重构
- MQBenchV0.3,修改部分代码,修复部分BUG
- 后端Torch–V1.9.1
- 后端Tensorrt–V8.2
- 后端ONNX-ONNXRuntime–V1.19
简单试验YOLOX-Nano
- FP32:mAP17.5%
- QAT(未加载PQT):直接训练无法收敛、clip-grad收敛到较大loss无法下降。mAP无
- QAT(PQT)(无Augment):mAP12.2%
- QAT(PQT)(Augment):mAP18.4%
- QAT(INT8):mAP18.4%
试验的方式和阿里加速团队基本一致,从试验结果来看整体流程较为完整。
量化理论
量化的理论较为简单(前向推理加速未涉及):
- r r r Float32 data
- q q q Quant data
- S S S Scale
- Z Z Z ZeroPoint
$$
\begin{array}{c}
r=S(q-Z) \
\end{array}
$$
q = round ( r S + Z ) q=\operatorname{round}\left(\frac{r}{S}+Z\right) q=round(Sr+Z)
$$
\begin{array}{c}
S=\frac{r_{\max }-r_{\min }}{q_{\max }-q_{\min }} \
\end{array}
$$
Z = round ( q max − r max S ) Z=\operatorname{round}\left(q_{\max }-\frac{r_{\max }}{S}\right) Z=round(qmax−Srmax)
基本所有的论文都是围绕以上四个公式进行的,未对具体论文进行总结,仅看代码给出的几个简单的例子:
- Scale稳定性
由于scale的变化幅度过大会对训练造成严重的震荡,所有较低频率的修改scale才能促进训练。
def scale_smooth(tensor: torch.Tensor):
log2t = torch.log2(tensor)
log2t = (torch.round(log2t) - log2t).detach() + log2t
return 2 ** log2t
- Scale和ZP的计算
这部分是优化最多且最有效的,因为一个好的初始化至关重要
- 都是比较简单,**代码**一看便明了
- 最大最小值
- 均值方差
- 直方图
- Clip
- …
- Learn/Fixed
Scale/ZP是训练还是固定?
训练的情况非常花时间,因为量化节点已经得插入上百个,如果再加上训练,速度慢的可怜