一些量化(quantization)技巧
对象:对权重量化,对特征图量化
(
神经元输出
)
,对梯度量化
(
训练过程中
)
过程:在
inference
网络前传,在训练过程
(
反传
)
一步量化
(
仅对权重量化
)
,
两步量化
(
对神经元与特征图量化,第一步先对
feature map
进行量化,第二步再对权重量化
)
。
32
位浮点和
16
位浮点存储的时候,
第一位是符号位,中间是指数位,后面是尾数。
英特尔在
NIPS2017
上,提出了把前面的指数项共享的方法。
这样可以把浮点运算,转化为尾数的整数定点运算,加速网络训练。
分布式训练梯度量化:
对权重数值进行聚类,量化的思想非常简单。
CNN
参数中数值分布在参数空间,
通过一定的划分方法,总是可以划分称为
k
个类别。
通过储存这
k
个类别的中心值,或者映射值,压缩网络的储存。
量化可以分为
Low-Bit Quantization(
低比特量化
)
、
Quantization for General Training Acceleration(
总体训练加速量化
)
和
Gradient Quantization for Distributed Training(
分布式训练梯度量化
)
。
由于在量化、特别是低比特量化实现过程中,由于量化函数的不连续性,在计算梯度的时候,会产生一定的困难。
对此,阿里巴巴把低比特量化,转化成
ADMM
可优化的目标函数,从而由
ADMM
来优化。
另一个角度思考,使用哈希把二值权重量化,再通过哈希求解。
用聚类中心数值,代替原权重数值,配合
Huffman
编码,具体可包括标量量化或乘积量化。
如果只考虑权重自身,容易造成量化误差很低,但分类误差很高的情况。
Quantized CNN
优化目标是重构误差最小化。
可以利用哈希进行编码,映射到同一个哈希桶中的权重,共享同一个参数值。
聚类例子:
例如下面这个矩阵。
1.2 1.3 6.1
0.9 0.7 6.9
-1.0 -0.9 1.0
设定类别数
k=3
,通过
kmeans
聚类。得到:
A
类中心:
1.0 ,
映射下标:
1
B
类中心:
6.5 ,
映射下标:
2
C
类中心:
-0.95 ,
映射下标:
3
储存矩阵可以变换为
(
距离哪个中心近,就用中心的下标替换
)
:
1 1 2
1 1 2
3 3 1
提出需要对量化后的值进行重训练,挽回一点丢失的识别率。
基本上所有压缩方法都有损,重训练还是比较必要的。
深度神经网络压缩 Deep Compression
为了进一步压缩网络,考虑让若干个权值共享同一个权值,需要存储的数据量也大大减少。
采用kmeans算法来将权值进行聚类,在每一个类中,所有的权值共享该类的聚类质心,
最终存储一个码书和索引表。
1.对权值聚类
采用kmeans聚类算法,通过优化所有类内元素,到聚类中心的差距(within-cluster sum of squares ),确定最终的聚类结果。
2. 聚类中心初始化
常用的初始化,包括3种:
a) 随机初始化。
即从原始数据,随机产生k个观察值,作为聚类中心。
b) 密度分布初始化。
现将累计概率密度CDF的y值,分布线性划分,
根据每个划分点的y值,找到与CDF曲线的交点,再找到该交点对应的x轴坐标,作为初始聚类中心。
c) 线性初始化。
将原始数据的最小值到最大值之间的线性划分,作为初始聚类中心。
三种初始化方式的示意图,如下所示:
由于大权值比小权值更重要(参加HanSong15年论文),线性初始化方式,能更好地保留大权值中心,文中采用这一方式,后面的实验结果,验证了这个结论。
3. 前向反馈和后项传播
前向时需要将每个权值,用对应的聚类中心代替,后向计算每个类内的权值梯度,
将梯度和反传,用来更新聚类中心。
如图:
共享权值后,就可以用一个码书和对应的index来表征。
假设原始权值用32bit浮点型表示,量化区间为256,即8bit,共有n个权值,量化后需要存储n个8bit索引和256个聚类中心值,可以计算出压缩率compression ratio:
r = 32*n / (8*n + 256*32 )≈4
如果采用8bit编码,至少能达到4倍压缩率。
参考链接: