深度神经网络模型的卷积网络的量化
[TOC]
文章参考:https://zhuanlan.zhihu.com/p/58182172
文章参考:https://github.com/Ewenwan/MVision/tree/master/CNN/Deep_Compression/quantization
文章参考:https://zhuanlan.zhihu.com/p/149659607
概述
矩阵的量化
由于卷积网络中的卷积层和全连接层本质上都是一堆矩阵乘法,因此我们先看如何将浮点运算上的矩阵转换为定点运算。
假设$r_1、r_2$是浮点实数上的两个$N*N$的矩阵,$r_3$是$r_1、r_2$相乘后的矩阵:
$$
r_3^{i,k}=\sum_{j=1}^N r_1^{i,j}r_2^{j,k} \tag{1}
$$
假设 $S_1、Z_1$ 是$r_1$矩阵对应的$scale$ 和 zero point,$ S_2 、 Z_2 、 S_3 、 Z_3$ 同理,那么由 (1) 式可以推出:
$$
S_3(q_3^{i,k}-Z_3)=\sum_{j=1}^{N}S_1(q_{1}^{i,j}-Z_1)S_2(q_2^{j,k}-Z_2) \tag{2}
$$
整理一下可以得到:
$$
q_3^{i,k}=\frac{S_1 S_2}{S_3}\sum_{j=1}^N(q_1^{i,j}-Z_1)(q_2^{j,k}-Z_2)+Z_3 \tag{3}
$$
仔细观察 (3) 式可以发现,除了$ \frac{S_1 S_2}{S_3}$ ,其他都是定点整数运算。那如何把$ \frac{S_1 S_2}{S_3} $也变成定点运算呢?这里要用到一个 trick。假设$ M=\frac{S_1 S_2}{S_3}$,由于M通常都是 (0, 1) 之间的实数 (这是通过大量实验统计出来的),因此可以表示成$ M=2^{-n}M_0$,其中 $M_0$是一个定点实数。注意,定点数并不一定是整数,所谓定点,指的是小数点的位置是固定的,即小数位数是固定的。因此,如果存在 $M=2^{-n}M_0$,那我们就可以通过$M_0$的 bit 位移操作实现 $2^{-n}M_0$,这样整个过程就都在定点上计算了。
很多刚接触量化的同学对这一点比较疑惑,下面我就用一个简单的示例说明这一点。我们把$M=\frac{S_1 S_2}{S_3}$ 代入 (3) 式可以得到:
$$
q_3^{i,k}=M\sum_{j=1}^N(q_1^{i,j}-Z_1)(q_2^{j,k}-Z_2)+Z_3=MP+Z_3 \tag{4}
$$
这里面P是一个在定点域上计算好的整数。就是左边基于定点整数的求和公式计算出来的结果。
假设 $M$=7091,$P$=0.0072474273418460 ($M$可以通过$S$事先计算得到),那下面我们就是要找到一个$M_0$和 $n$,使得$MP=2^{-n}M_0P$成立。我们可以用一段代码来找到这两个数:
1 | M = 0.0072474273418460 |
输出:
1 | n=1, Mo=0, approx=0.000000, error=51.391507 |
卷积网络的量化
有了上面矩阵乘法的量化,我们就可以进一步尝试对卷积网络的量化。
假设一个这样的网络:
这个网络只有三个模块,现在需要把 conv、fc、relu 量化。
假设输入为$x$,我们可以事先统计样本的最大值和最小值,然后计算出$S_x$(scale) 和$Z_x$(zero point)。
同样地,假设 conv、fc 的参数为$w_1、w_2$,以及scale和 zero point 为$S_{w1}、Z_{w1} 、S_{w2} 、Z_{w2}$$。中间层的 feature map 为$a_1、a_2$ ,并且事先统计出它们的 scale 和 zero point 为$S_{a1} 、Z_{a1} 、S_{a2} 、Z_{a2}$。
卷积运算和全连接层的本质都是矩阵运算,因此我们可以把卷积运算表示成 (这里先忽略加 bias 的操作,这一步同样可以量化,不过中间有一些 trick,我们在之后的文章再仔细研究):
$$
a_1^{i,k}=\sum_{j=1}^N x^{i,j}w^{j,k} \tag{9}
$$
根据之前的转换,我们可以得到:
概括总结
这篇文章主要介绍了矩阵量化的原理,以及如何把矩阵量化运用到卷积网络中,实现全量化网络的计算。这中间忽略了很多细节,比如 relu 和 conv 的合并、激活函数的量化、量化训练的流程等。后面的文章会继续补充一些细节,并通过从零搭建一个 pytorch 的量化模型来帮助读者更好地理解中间的过程。