浅谈深度学习模型量化

【GiantPandaCV】本次简要的总结了模型量化研究的一些问题,介绍了量化存在的量化误差与其总体上解决量化误差的一些方法。主要讨论了5种非线性量化的方法。

量化任务的简要总结: 1、量化映射方法,也就是将float-32映射到Int数据类型,每个间隔是相等的还是不相等的,这里就是均匀量化(uniform quantization)和非均匀量化(non-uniform quantization),也可以叫作线性量化和非线性量化

2、关于映射到整数是数值范围是有正负数,还是都是正数,这里就是对称量化(有正负数)和非对称量化(全是正数),非对称量化就有zero-point,zero-point的主要作用是用于做padding。

3、原精度即浮float-32,量化到什么样的数据类型,这里就有float和int;到底要选择量化后的是多少个bit,这里就有1-bit(二值网络)、2-bit(三值网络)、3-bit、4-bit、5-bit、6-bit、7-bit、8-bit,这几种量化后的数值类型是整型。

4、是固定所有网络都是相同的bit-width,还是不同的,这里就有混合精度量化(Mixed precision)

5、是从一个已经训练好的模型再进行量化,还是有fine tune的过程或者直接是从头开始训练一个量化的模型,这里就有Post-training quantization(后量化,即将已经训练完的模型参数进行量化)、quantization-aware training(量化感知训练,即在从头开始训练中加入量化)和quantization-aware fine tune(在fine tune训练中加入量化)。

我们与剪枝来做一个不恰当的对比

上面的(3)选择什么样的bit-width来做量化,对应的是剪枝的压缩率,即要剪枝多少参数;

上面的(4)是所有参数统一一个bit表示还是采用混合精度量化,对应的剪枝就是结构化剪枝和非结构化;

上面的(5)有没有fine tune操作,对应的剪枝就是《training from starch》和三步剪枝方法(train-prune-fine tune);

量化误差到底来自于哪里?

1、从float-32到Int数据类型,其中有一个round的操作,这里肯定会有误差; 2、激活函数的截断; 3、溢出时候的处理也有可能带来误差。

那么继续来讨论一下量化遇到的问题是什么:

1、weight和activation的数据分布呈现出一个类拉普拉斯分布或者类高斯分布,数据分布是一个钟型分布,大部分数据集中在中间,两头的数据比较少。如果采用均与量化(uniform quantization),由于是等间隔的,那么中间密集分布的数据的分辨率低。举个例子,假如总共10个值,fp32_x={10,-10,0.11,0.21,0.15,0.05,-0.14,-0.22,-0.08,-0.35},采用对称均匀分布量化,(10-(-10))/(255)= 20/255,Int8_x={127,-127,1,3,2,1,-2,-3, -1,-5},可以看到,0.05和0.11被量化同一个int-8的数值1,而且量化后的数值大部分集中在了[-5,3],而其余的数值没有用到。如何解决这个问题?很简单,给密集的区域用比较多的Int数值表示(增大分辨率),稀疏的区域用比较少的Int数值表示;这就是一个不等间距间隔,称为非均与量化(non-uniform quantization)或非线性量化。

2、另外一个问题就是每一层的数值范围不一定都相同,activation在不同层的数值范围会不一样,这就会产生另外一个问题,动态值域问题,dynamic range。这个dynamic range如何影响量化效果呢?比如8-bit的均与分布量化,值域[-2, 2]的单位间隔是(2-(-2))/255 = 4/ 255,值域[-6, 6]的单位间隔是(6-(-6))/255 = 12/ 255,明显前面的分辨率更高。还是由于数据分布钟型分布,即可abs(数值)大的占据的比例很小,因此,这里可以采用截断的方式提高来量化的分辨率。

3、round会肯定会带来误差,怎么处理呢?Stochastic rounding,因为其期望是x,可以减少round的误差.

Round (x)=\left\{\begin{array}{ll}\lfloor x\rfloor & \text { with probability } 1-(x-\lfloor x\rfloor) \\ \lfloor x\rfloor+1 & \text { with probability } x-\lfloor x\rfloor\end{array}\right.

证明:

E(x)= (1-(x-\lfloor x\rfloor)) * \lfloor x\rfloor + (x-\lfloor x\rfloor)*(\lfloor x\rfloor+1)
= \lfloor x\rfloor - (x-\lfloor x\rfloor) * \lfloor x\rfloor + (x-\lfloor x\rfloor)*\lfloor x\rfloor + (x-\lfloor x\rfloor)
= \lfloor x\rfloor + x-\lfloor x\rfloor = x

其中\lfloor x \rfloor是向下取整,即取不大于x的最大整数 4、如果是量化感知训练,会遇到另外一个新的问题,就是量化这个操作的导数为0,在backwards的时候,梯度在后向传播中传不到后面。怎么办?(1)STE(Straight-Through Estimator ),直通估算器,即将该操作的梯度设置为1,那么梯度就可以传递下去,\frac{\partial \mathbf{w}_{q}}{\partial \mathbf{w}}=\frac{\partial q(\mathbf{w})}{\partial \mathbf{w}} \underset{S \widetilde{T} E}{\approx} \frac{\partial I(\mathbf{w})}{\partial \mathbf{w}}=1;(2)设计一个光滑可导且导数不为零的量化,比如Lq-Net和DSQ(Differentiable Soft Quantization)

在这里插入图片描述

以上就是总结的量化知识点和存在的一些问题,可能列举的还不够完善,希望大家提出宝贵的建议。 下面先来讨论非均匀量化/非线性量化,参考文章如下: 1、《Convolutional Neural Networks using Logarithmic Data Representation》 2016
2、 Powers-of-two quantization,这个方法我还没找到原论文
3、《Quantization Networks》CVPR 2019
4、《Additive powers-of-two quantization: an efficient non-uniform discretization for neural networks》 ICLR 2020
5、《Differentiable Soft Quantization: Bridging Full-Precision and Low-Bit Neural Networks》 CVPR 2019
6、《Post-Training Piecewise Linear Quantization for Deep Neural Networks》ECCV 2020

一、均匀量化/线性量化 uniform quantization

s(a, b, n) 就是scale,\left\lfloor\frac{\operatorname{clamp}(r ; a, b)-a}{s(a, b, n)}\right]是量化,\left\lfloor\frac{\operatorname{clamp}(r ; a, b)-a}{s(a, b, n)}\right] s(a, b, n)+a是反量化,

\begin{aligned} \operatorname{clamp}(r ; a, b) &:=\min (\max (x, a), b) \\ s(a, b, n) &:=\frac{b-a}{n-1} \\ q(r ; a, b, n) &:=\left\lfloor\frac{\operatorname{clamp}(r ; a, b)-a}{s(a, b, n)}\right] s(a, b, n)+a \end{aligned}

另外一种写法,\alpha是全精度数据的值域[0,\alpha],大括号里面就有255个值,让全精度数据映射到这255值。

\mathcal{Q}^{u}(\alpha, b)=\alpha \times\left\{0, \frac{\pm 1}{2^{b-1}-1}, \frac{\pm 2}{2^{b-1}-1}, \frac{\pm 3}{2^{b-1}-1}, \ldots,\pm 1\right\}

二、Logarithmic 文章:《Convolutional Neural Networks using Logarithmic Data Representation》

在这里插入图片描述

先贴公式,下面公式是上图(b)的方案:

\begin{aligned} w^{T} x & \simeq \sum_{i=1}^{n} w_{i} \times 2^{\tilde{x}_{i}} \\ &=\sum_{i=1}^{n} \operatorname{Bitshift}\left(w_{i}, \tilde{x}_{i}\right) \end{aligned}

为啥要将x变成log呢?就是为了在做矩阵乘法的时候用2的指数形式,先log_{2}x,后面再用2^{x}复原。这是为了可以用位移的方式实现乘法。方案(b)只将input做了log操作。

继续看上图©的方案,即weight和input两个矩阵乘法的乘子都做了log操作,那么:

\begin{aligned} w^{T} x & \simeq \sum_{i=1}^{n} 2^{\text {Quantize }\left(\log _{2}\left(w_{i}\right)\right)+\text { Quantize }\left(\log _{2}\left(x_{i}\right)\right)} \\ &=\sum_{i=1}^{n} \operatorname{Bitshift}\left(1, \tilde{w}_{i}+\tilde{x}_{i}\right) \end{aligned}

做矩阵乘法的时候,weight和input都需要用2^{x}来复原之前的log操作。 另外还要担心溢出,所以要有做一个截断clamp。一定的bit的数值范围2^{FSR},记为FSRLogQuant (x, bitwidth, \mathrm{FSR})=\left\{\begin{array}{ll}0 & x=0 \\ 2^{\tilde{x}} & \text { otherwise }\end{array}\right. 其中,

\tilde{x}=\operatorname{Clip}\left(\operatorname{Round}\left(\log _{2}(|x|)\right), \mathrm{FSR}-2^{\text {bitwidth }}, \mathrm{FSR}\right)

\operatorname{Clip}(x, \min , \max )=\left\{\begin{array}{ll}0 & x \leq \min \\ \max -1 & x \geq \max \\ x & \text { otherwise }\end{array}\right.

对应的均匀量化/线性量化:

\begin{array}{r} \text { LinearQuant }(x, \text { bitwidth, FSR }) \\ =\operatorname{Clip}\left(\text { Round }\left(\frac{x}{\text { step }}\right) \times \text { step }, 0,2^{\mathrm{FSR}}\right) \end{array}

其中\text { step }=2^{\mathrm{FSR}-\text { bitwidth }}

这个方法,还是比较复杂的,而且是2016的论文,大家就看看理解一下就好了。

三、Powers-of-two quantization(PoT)

量化的值跟名字一样,就是要把浮点数量化为2的n次幂,下面Q_{P oT }(x)公式是PoT的计算公式

Q_{P oT }(x)=\left\{\begin{array}{ll}\operatorname{sign}(x) & |x| \geq 1 \\ \operatorname{sign}(x) *2^{\left\lfloor\log _{2}|x|\right\rfloor} & 2^{-b+1} \leq|x|<1 \\ 0 & |x|<2^{-b+1}\end{array}\right.

下面\mathcal{Q}^{p}(\alpha, b)公式也是PoT的计算公式,不过是以集合的形式,列举可以选的PoT值

\mathcal{Q}^{p}(\alpha, b)=\alpha \times\left\{0, \pm 2^{-2^{b-1}+1}, \pm 2^{-2^{j-1}+2}, \ldots, \pm 2^{-1},\pm 1\right\}

其中b表示bit位数,这个也是为了做乘法的时候,可以使用位移。
2^{x} r=\left\{\begin{array}{ll}r & \text { if } x=0 \\ r<0 \\ r>>x & \text { if } x<0\end{array}\right.
那PoT的缺限在哪里呢?举个例子最好理解: \mathcal{Q}^{p}(1, 5) 为例子,那么两个最小的值为2^{-15}2^{-14},这两数值太接近了;而两个最大值为2^{-1}2^{0},这两个最大值的间距又过大。 当bit位数增加的时候,最大值仍然是2^{-1}2^{0},最小值的颗粒度更加细了。

四、Additive powers-of-two(APoT)

先来看看APoT的名字比powers-of-two多了个additive,也就说明比PoT的非线性量化多了个加法项, \mathcal{Q}^{a}(\alpha, k n)=\gamma \times\left\{\sum_{i=0}^{n-1} p_{i}\right\} where p_{i} \in\left\{0, \frac{1}{2^{i}}, \frac{1}{2^{i+n}}, \ldots, \frac{1}{2^{i+\left(2^{k}-2\right) n}}\right\}
其中,
\gamma表示是缩放系数,以保证\mathcal{Q}^{a}中的最大水平为\alpha
k是基位宽度(base bit-width),是每个加法项的位宽;
n是加法项的数量。
当设置了 bk 时,可以通过n=\frac{b}{k}计算n。 总共有2^{k n}=2^{b}个级别。 APoT量化中加法项的数量可以随位宽b的增加而增加,这为非均匀水平提供了更高的分辨率。下面的图片展示了均匀分布量化、PoT量化和APoT量化的图,可以看出一下几点: 1、均与分布量化是一个等间隔的阶梯,对于钟性分布的数据不利;
2、PoT解决了一个问题,就是在值比较小的区域阶梯变多了,也就是分辨率变高了,但是也存在Powers-of-two quantization中提到的问题;
3、APoT就是为了解决PoT存在的问题,也就是当bit数增加的时候,两个最大值的之间的分辨率没有提高的问题。
在这里插入图片描述 因为没有mobilenet、shufflnet的实验,实验结果就不贴图了,另外因为多了一些累加,具体speedup不好说,代码开源了。

五、可微分的非线性量化

可微分的非线性量化留到下一次讨论,给自己挖个坑,即两篇《Quantization Networks》和《Differentiable Soft Quantization: Bridging Full-Precision and Low-Bit Neural Networks》(当然还有其他的文章,我还没找到),主要的思路是:量化映射这个操作原来是阶跃函数或者阶段函数,是不可导或者导数为0,那么找一个可导的函数比如sigmoid去模拟阶跃函数,利用学习的方式去找上图的阶梯。这样就可以不用STE的方法,也就没有了梯度不匹配的问题。 当然这种量化方法也有局限性,就是,得用训练的方式,肯定增加了耗时,而且对于硬件是否友好,这个还得具体落地实验。 因为DSQ有mobilenet的实验,就贴实验效果表格(Quantization Networks没有mobilenet实验就忘记他吧): DSQ:在这里插入图片描述

六、Piecewise Linear Quantization(推荐)

最后来讨论一下PWLQ(作者自己要这么缩写的,不是我强行造词)。代码开源了。 就同名字一样,分段线性量化,这个思路简单而巧妙:在全精度数据的分布中,找一个分位点,那么中间的部分给予比较多的bit位数做一个线性量化,两边分比较少的bit位数也做一个线性量化,非常的巧妙的做法。

\mathrm{pw}(r ; b, m, p)=\left\{\begin{array}{l}\operatorname{sign}(r) \times \operatorname{uni}(|r| ; b-1,0, p, 0), r \in R_{1} \\ \operatorname{sign}(r) \times \operatorname{uni}(|r| ; b-1, p, m, p), r \in R_{2}\end{array}\right.

m是量化的值域[-m; m] (m > 0) ,R_{1}=[-p, p]R_{2}=[-m,-p) \cup(p, m],uni表示的是均匀分布量化/线性量化。看图就能一眼看懂这个公式。

在这里插入图片描述

图中,m=0.8,R_{1}=[-0.2, 0.2]R_{2}=[-0.8,-0.2) \cup(0.2, 0.8]。 来看看效果,(有mobilenet的实验):

在这里插入图片描述

后续有时间回过头来,我想更加详细的写一下这些内容。


欢迎关注GiantPandaCV, 在这里你将看到独家的深度学习分享,坚持原创,每天分享我们学习到的新鲜知识。( • ̀ω•́ )✧

有对文章相关的问题,或者想要加入交流群,欢迎添加BBuf微信:

二维码

为了方便读者获取资料以及我们公众号的作者发布一些Github工程的更新,我们成立了一个QQ群,二维码如下,感兴趣可以加入。

公众号QQ交流群