这里介绍下低比特量化的原理,之后再看下如何将fp32转换为int8。
模型量化是通过减少权重表示或激活所需的比特数来压缩模型,而网络剪枝研究模型权重中的冗余,并尝试删除/修剪冗余和非关键的权重。
其实模型量化的原理非常简单,我们知道FP32可以表示的范围为$$ \pm 1.4\times 10^{-45}\sim\pm 3.4\times 10^{38} $$
而int8可以表示的范围在[-128,127]。可以看到int8中一位数如果对应到fp32中将是很大一段区域。
模型量化是一种将浮点计算转换成低比特定点计算的技术,可以有效的降低模型计算强度、参数大小和内存消耗,但往往带来巨大的精度损失。
模型之所以会引入量化的原因在于神经网络一般对噪声(精度损失)不太敏感。
模型量化通过在定点和浮点数之间建立一种有效的数据映射关系,使得以较小的精度损失代价获取较好的收益。
而线性量化主要分为两种:
- 对称量化
- 非对称量化
其中对于int8来说,对称量化的取值范围是[-128,127],而非对称量化的取值范围是[0,255]。
模型量化的原理就是找到这种数据映射关系,其中浮点与定点数据的转换公式如下:
$$ Q=\frac{R}{S}+Z\ \Rightarrow Q-Z=\frac{R}{S}\ \Rightarrow R=(Q-Z)\times S $$
其中R表示输入的浮点数据,Q表示量化后的定点数据,Z表示零点的数值,S表示缩放因子的数值。
求解S和Z有很多种方法,比如下面最简单的一种线性量化求解方式(MinMax):
$$ S=\frac{R_{max}-R_{min}}{Q_{max}-Q_{min}}\ Z=Q_{max}-\frac{R_{max}}{S} $$
其中$R_{max}$表示输入浮点数数据中最大值,$R_{min}$表示输入浮点数数据中最小值。同理$Q_{max}$是最大的定点值。
下面我们来看一个例子加深其印象。假设神经网络某层权重的取值范围是[-1.0,1.0],使用对称量化方式,则将其代入上述公式从而有$$ S=\frac{1.0-(-1.0)}{127-(-128)}=\frac{2}{255}\ Z=127-\frac{1.0}{\frac{2}{255}}=127-127.5=-0.5 $$
当输入的FP32的值为0.5时有$$ Q=\frac{0.5}{\frac{2}{255}}-0.5=\frac{255-2}{4}=\frac{253}{4}\approx 63 $$
而对应的反量化过程为$$ R=(63+0.5)\times\frac{2}{255}=\frac{127}{255}\approx 0.498 $$
可以看到反量化后的值与输入的值0.5相差不大。
有了量化原理后,接下来就可以进行一些实际的应用了,比如QAT(感知量化训练,Aware Quantization Training)。其通过插入伪量化节点(fake quant)来模拟量化引入的误差。并在端侧推理的过程直接使用tensor中带有量化属性参数。
通过伪量化节点可以找到输入数据的分布,即找到min和max值。同时,模拟量化到低比特操作的时候的精度损失,把该损失作用到网络模型中,传递给损失函数,让优化器在训练过程中对该损失值进行优化。
而PTQ Dynamic(动态离线量化,Post Training Quantization Dynamic)仅将模型中特定算子的权重从FP32类型映射成INT8/16类型,其缩放因子是动态计算的,因此动态量化是几种量化方法中性能最差的。
另外一种PTQ Static也称为校正量化或数据集量化。其使用少量无标签校准数据,核心是计算量化比例因子,使用静态量化后的模型进行预测。在此过程中量化模型的缩放因子会根据输入数据的分布进行调整。
参考视频:
https://www.bilibili.com/video/BV1VD4y1n7AR https://blog.csdn.net/2502_92631100/article/details/149351615 https://www.bilibili.com/video/BV1s8411w7b9 https://www.bilibili.com/video/BV1HD4y1n7E1
