1:量化设计
Uniform Affine Quantizer
其中:
Δ
\Delta
Δ =
(
x
m
a
x
−
x
m
i
n
)
/
(
N
l
e
v
e
l
s
−
1
)
(x_{max}-x_{min})/(N_{levels}-1)
(xmax−xmin)/(Nlevels−1), z 指代 zero-point,由下面的公式计算:
z
=
−
r
o
u
n
d
(
x
m
i
n
Δ
)
z = -round(\frac {x_{min}}{\Delta})
z=−round(Δxmin).
这种量化方式无法保证if a>b then q(a)>q(b) (a
∈
\in
∈W,b
∈
\in
∈activation)。所以在计算W*A的时候,要做处理。
Uniform symmetric quantizer
这个和上面类似,就是量化区间要对称
可以看出这个量化方法令 z=0,并且使得量化区间对称。
Stochastic quantizer Stochastic
大同小异
量化前先加一个随机量。
总结
这几种量化方式来源应该是tensorflow lite。好处在于可以调节量化精度;坏处在于量化后的矩阵不能够直接相乘,因为意义不大,需要一定的技巧。这部分不是本白皮书的内容,我简单的补充一下:
假定r代表实数矩阵,q代表量化矩阵。
r
3
=
r
1
∗
r
2
r_{3}=r_{1}*r_{2}
r3=r1∗r2,
由于存在这样的限制,所以在train的过程中会遇到非常多麻烦。因此tersorflowlite实际在train的过程中用的并不是上面所说的任何一种量化方法,采用的是对上面量化方法一种近似,只在inference中使用了上面的量化方式以及矩阵乘法的特殊处理。这也就带来了一些不一致性。不过效果依然很好,是一种能够真正实用的量化方法。
2:quantization inference
这部分主要讲了对量化的两种使用方式,分别是post training quantization,quantization aware training
在介绍这两部分之前,首先补充两个概念
- 对称和非对称量化 如果量化区间关于0对称,那就是对称量化,反之则是非对称量化
- per layer 和per channel 量化。 主要指量化过程中的统计量的是在layer范围内计算出来的,还是在channel 范围内计算出来的。类似于batch normalization和layer normalization的区别。
post training quantization
横坐标代表量化范围,纵坐标代表精度。可以看出来
- 非对称比对称好
- per channel 比per layer 好
- 只量化activation 比w和a 都量化好(但是好的不多)
- 量化后的结果可以非常逼近全精度
quantization aware training
如果在training的时候就加入quantization,要面临两个问题:网络如何修改;梯度如何更新
网络修改
如上图,需要在全精度的后面增加simulated quantization模块。这里为什么要加入simulated字样,是因为在本文中,所有的量化都默认采用第一部分讲的量化方法,而这种量化在做MACs(矩阵乘法)的时候比较复杂,所以采用simulated quantization,使得量化后的结果能够直接进行MACs。
梯度更新
主要考虑如何处理
Δ
W
b
Δ
W
r
\frac {\Delta W_{b}} {\Delta W_{r}}
ΔWrΔWb.按照straight-through estimator
g
r
=
g
q
∗
1
∣
r
∣
<
1
g_{r} = g_{q}*1_{|r|<1}
gr=gq∗1∣r∣<1 即可处理
除此之外,本文还对bn做了探讨
batch normalization
首先关注下bn在training和inference时的公式
training
inference
作者注意到,在inference时,
γ
,
β
,
μ
,
θ
\gamma, \beta,\mu,\theta
γ,β,μ,θ已经固定,而还要经过bn层,会造成额外计算量,不如把bn的参数合并到矩阵乘法之中。
具体做法如下图:
左图是traing过程中的网络结构。首先要计算conv(v,w),通过batch norm层计算出均值方差。然后再回过头来,先对w乘上
γ
σ
β
\frac{\gamma}{\sigma_{\beta}}
σβγ然后再做量化,随后与v进行conv,再加上
β
−
μ
β
γ
σ
β
\beta - \frac {\mu _{\beta} \gamma }{\sigma _{\beta}}
β−σβμβγ,随后做激活,再做量化。
右图是inference。比较简单,不再赘述。
另外要思考下为什么Traing的graph要这么设计。关键原因在于,我们在做bn之前,是无法知道
σ
B
\sigma _{B}
σB的。因此需要先计算下bn,得到所有所需的统计量,然后再走fold的流程。
注意到,由于inference时所有的统计量都是估计的,所以存在training 和inference的mismatch。因此,作者提出后面的改进
主要改变是,trianing分成了两步。在training刚开始时,freeze batch norm值为零,那么就会取消掉
σ
β
σ
\frac {\sigma_{\beta}}{\sigma}
σσβ对W的影响。而在training持续一段时间后,(about 300000 steps ),再将freeze batch norm置为1.这时便将long term moving averages 的影响加入bn。
inference的graph不改变。
通过上面的操作,就可以将bn层在inference 时去掉,fold进w的scale中。
实验结果
- 非对称好于对称
- per channel 要好于 per layer
总结:
综合对比post traiing quantization 和quantization aware training
所以 quantization aware training 还是普遍好于post training quantization的。
3:Training best practices
1:Stochastic Quantization does not improve accuracy
2:Quantizing a model from a floating point checkpoint provides better accuracy than from scratch.
3:Matching Batch normalization with inference reduces jitter and improves accuracy
4: Use Exponential moving averaging for quantization with caution