6. 量化

量化理论源于论文: Quantization and Training of Neural Networks for Efficient Integer-Arithmetic-Only Inference

该论文地址: https://arxiv.org/abs/1712.05877

本章介绍TPU-MLIR的量化设计, 重点在该论文在实际量化中的应用。

6.1. 基本概念

INT8量化分为非对称量化和对称量化。对称量化是非对称量化的一个特例, 通常对称量化的性能会优于非对称量化, 而精度上非对称量化更优。

6.1.1. 非对称量化

_images/quant_asym.png

图 6.1 非对称量化

如上图(非对称量化)所示, 非对称量化其实就是把[min,max]范围内的数值定点到[-128, 127]或者[0, 255]区间。

从int8到float的量化公式表达如下:

r=S(qZ)S=maxminqmaxqminZ=Round(minS+qmin)

其中r是真实的值, float类型; q是量化后的值, INT8或者UINT8类型;

S表示scale, 是float; Z是zeropoint, 是INT8类型;

当量化到INT8时, qmax=127,qmin=-128; UINT8时, qmax=255,qmin=0

反过来从float到int8的量化公式如下:

q=rS+Z

6.1.2. 对称量化

对称量化是非对称量化Z=0时的特例, 公式表达如下:

i8_value=f32_value×128thresholdf32_value=i8_value×threshold128

threshold是阈值, 可以理解为Tensor的范围是[-threshold, threshold]

这里 S=threshold/128, 通常是activation情况;

对于weight, 一般 S=threshold/127

对于UINT8, Tensor范围是[0, threshold], 此时 S=threshold/255.0

6.2. Scale转换

论文中的公式表达:

M=2nM0,M0[0.5,1],n

换个表述来说, 就是浮点数Scale, 可以转换成Multiplier和rshift, 如下表达:

Scale=Multiplier2rshift

举例说明:

y=x×0.1234=>y=x×0.9872×23=>y=x×(0.9872×231)×234=>y=x×2119995857134=>y=(x×2119995857)34

Multiplier支持的位数越高, 就越接近Scale, 但是性能会越差。一般硬件会用32位或8位的Multiplier。

6.3. 量化推导

我们可以用量化公式, 对不同的OP进行量化推导, 得到其对应的INT8计算方式。

对称和非对称都用在Activation上, 对于权重一般只用对称量化。

6.3.1. Convolution

卷积的表示式简略为: Y=X(n,ic,ih,iw)×W(oc,ic,kh,kw)+B(1,oc,1,1)

代入int8量化公式, 推导如下:

float:Y=X×W+Bstep0=>Sy(qyZy)=Sx(qxZx)×Swqw+Bstep1=>qyZy=S1(qxZx)×qw+B1step2=>qyZy=S1qx×qw+B2step3=>qy=S3(qx×qw+B3)+Zystep4=>qy=(qx×qw+bi32)Mi32>>rshifti8+Zy

非对称量化特别注意的是, Pad需要填入Zx

对称量化时, Pad填入0, 上述推导中Zx和Zy皆为0

在PerAxis(或称PerChannal)量化时, 会取Filter的每个OC做量化, 推导公式不变, 但是会有OC个Multiplier、rshift

6.3.2. InnerProduct

表达式和推导方式与(Convolution)相同

6.3.3. Add

加法的表达式为: Y=A+B

代入int8量化公式, 推导如下:

float:Y=A+Bstep0=>Sy(qyZy)=Sa(qaZa)+Sb(qbZb)step1()=>qy=(qaMa+qbMb)i16>>rshifti8step1()=>qy=requant(dequant(qa)+dequant(qb))

加法最终如何用智能深度学习处理器实现, 与处理器具体的指令有关。

这里对称提供的方式是用INT16做中间buffer;

在网络中,输入A、B已经是量化后的结果 qaqb,因此非对称是先反量化成float, 做加法后再重量化成INT8

6.3.4. AvgPool

平均池化的表达式可以简写为: Yi=j=0k(Xj)k,k=kh×kw

代入int8量化公式, 推导如下:

float:Yi=j=0k(Xj)kstep0:=>Sy(yiZy)=Sxj=0k(xjZx)kstep1:=>yi=SxSykj=0k(xjZx)+Zystep2:=>yi=SxSykj=0k(xj)(ZySxSyZx)step3:=>yi=(Scalef32j=0k(xj)Offsetf32)i8Scalef32=SxSyk,Offsetf32=ZySxSyZx

6.3.5. LeakyReLU

LeakyReLU的表达式可以简写为: Y={X,ifX0αX,ifX<0

代入int8量化公式, 推导如下:

float:Y={X,if X0αX,if X<0step0:=>Sy(qyZy)={Sx(qxZx),if qx0αSx(qxZx),if qx<0step1:=>qy={SxSy(qxZx)+Zy,if qx0αSxSy(qxZx)+Zy,if qx<0

对称量化时, Sy=thresholdy128,Sx=thresholdx128, 非对称量化时, Sy=maxyminy255,Sx=maxxminx255。通过BackwardCalibration操作后, maxy=maxx,miny=minx,thresholdy=thresholdx, 此时Sx/Sy = 1。

step2:=>qy={(qxZx)+Zy,if qx0α(qxZx)+Zy,if qx<0step3:=>qy={qxZx+Zy,if qx0Mi8>>rshifti8(qxZx)+Zy,if qx<0

当为对称量化时, Zx和Zy均为0。

6.3.6. Pad

Pad的表达式可以简写为: Y={X, origin locationvalue, padded location

代入int8量化公式, 推导如下:

float:Y={X, origin locationvalue, padded locationstep0:=>Sy(qyZy)={Sx(qxZx), origin locationvalue, padded locationstep1:=>qy={SxSy(qxZx)+Zy, origin locationvalueSy+Zy, padded location

通过ForwardCalibration操作后, maxy=maxx,miny=minx,thresholdy=thresholdx, 此时Sx/Sy = 1。

step2:=>qy={(qxZx)+Zy, origin locationvalueSy+Zy, padded location

对称量化时, Zx和Zy均为0, pad填入 round(value/Sy), 非对称量化时, pad填入round(value/Sy + Zy)。

6.3.7. PReLU

PReLU的表达式可以简写为: Yi={Xi,if Xi0αiXi,if Xi<0

代入int8量化公式, 推导如下:

float:Yi={Xi,if Xi0αiXi,if Xi<0step0:=>Sy(yiZy)={Sx(xiZx),if xi0SαqαiSx(xiZx),if xi<0step1:=>yi={SxSy(xiZx)+Zy,if xi0SαqαiSxSy(xiZx)+Zy,if xi<0

通过BackwardCalibration操作后, maxy=maxx,miny=minx,thresholdy=thresholdx, 此时Sx/Sy = 1。

step2:=>yi={(xiZx)+Zy,if xi0Sαqαi(xiZx)+Zy,if xi<0step3:=>yi={(xiZx)+Zy,if xi0qαiMi8(xiZx)>>rshifti8+Zy,if xi<0

一共有oc个Multiplier和1个rshift。当为对称量化时, Zx和Zy均为0。