学习模型压缩知识,记录此论文(ICLR2016 的 best paper)学习过程。
论文链接: https://arxiv.org/abs/1510.00149
论文Pytorch实现GitHub链接: https://github.com/mightydeveloper/Deep-Compression-PyTorch
DNN是计算密集型和内存密集型的模型,使得他们很难应用在硬件资源受限的嵌入式系统中。因此作者提出了采用修剪、量子训练,霍夫曼编码技术进行模型压缩,过程如下:
在1,2步骤之后,我们对网络进行重新训练,以便对剩余的连接和量化的中心点进行微调;修剪减少了9到13倍的连接数,量化减少了连接比特数,从32减少到5。在ImageNet数据集中,AlexNet模型减小了35倍,从240MB减少到6.9MB,精度不损;VGG-16减小了49倍,从552MB减少到11.3MB,精度不损。这允许将模型拟合到片内SRAM缓存而不是片外DRAM内存中。
作者实验表明,深度压缩的三个阶段:剪枝,量化和霍夫曼编码。
剪枝使权值减少了10×,量化进一步提高了压缩率:在27×~ 31×之间。哈夫曼编码提供了更多的压缩:在35×和49×之间。压缩率已经包含用于稀疏表示的元数据。压缩方案不会造成任何精度损失。
模型权重等参数消耗了大量内存、带宽要大等弊端,应用在嵌入式设备上,导致的问题:
能量消耗主要由内存访问决定。在45nm CMOS技术下,32位浮点数加法使用0:9pJ, 32位SRAM缓存访问使用5pJ, 32位DRAM内存访问使用640pJ,这是加法操作的3个数量级。大型网络不适合芯片存储,因此需要更昂贵的DRAM访问。例如,运行一个10亿个连接神经网络,速度为20fps,仅DRAM访问就需要(20Hz)(1G)(640pJ) = 12:8W——远远超出了典型移动设备的功率包线
下面开始具体介绍 网络修剪、量化训练和共享权重,霍夫曼编码技术
网络修剪:
具体修剪可以参考作者2015的另外一篇论文,后续作者也会拜读论文
效果:
为了进一步压缩,我们存储索引相对位置而不是绝对位置,并将这个相对位置编码,这样索引的字节数就被压缩了。
论文中,用8比特保存卷积层的相对位置的索引和5位的fc层。
当我们需要一个比边界更大的索引差时,我们使用图2中所示的零填充解决方案:当差超过8时,最大的3位(例如)无符号数,我们添加一个填充零。
补充下,补0操作:
图2中:
第一行是index索引号,0-15;
第二行different是前后两个参数间的距离;
第三行是value,就是参数的值;
解释下图二中数据的含义;
例如在第二行第一个是1表示与初始参数距离为1,第二个是3表示与第一个参数的距离为3,4-1=3; 这里假设用3bit来存储相对距离,当第三个与第二个参数距离超过8时,这假设为11,首先要在第八个位置补0,例如12-4=8,因此在索引为12的地方添加0,其次把补0位置当做是第三个参数,真实第三参数后推为第四个,并在4+11=15的索引位置添加相应数据;
通过减少表示权重的比特位数量,网络量化和共享权重将更大程度的压缩被修剪后的网络。通过让多个连接共享相同的权重来限制需要存储的有效权重的数量,然后对这些共享权重进行微调。
如图三,假设我们有一个网络层有4个输入神经元和4个输出神经元,权重是4×4矩阵。图中左上的是一个44的权重矩阵,左下的是一个44的梯度矩阵,权重共享操作过程如下:
操作过程参考图三。
r = n b n l o g 2 k + k b r =\frac{nb}{nlog_2k + kb} r=nlog2k+kbnb
其中:n表示权重个数(分子n表示压缩前的,分母表示压缩后的个数),b表示存储的比特位数, k表示 k clusters,用log2K表示编码的索引。
图三,最初有4×4 = 16个权值,但只有4个共享权值:相似权重组合在一起共享相同的值。最初我们需要存储16个权重,每个权重32位,现在我们只需要存储4个有效权重(蓝色、绿色、红色和橙色),每个权重32位,加上16个2位索引,压缩率为:16 * 32 /(4 * 32+2*16) = 1/3.2
其实就用了非常简单的 K-means,对每一层都做一个weight的聚类,属于同一个 cluster 的就共享同一个权值大小。注意的一点:跨层的weight不进行共享权值;
我们将n个原始权值W = {w1,w2,…wn}划分为k个簇C = {c1,c2,…ck},从而最小化簇内平方和(WCSS):
我们的方法确定了网络完全训练后的权值共享,使共享的权值近似于原始网络的权值。
centroid 初始化影响聚类质量,从而影响网络的预测精度。作者尝试了很多生产初始点的方法:Forgy(random) 初始化从数据集中随机选择k个观测值,并将它们作为初始中心点。初始化的中心体用黄色表示。由于双峰分布中存在两个峰,所以Forgy方法往往集中在这两个峰附近
density-based 初始化y轴上权重的CDF的线性空间,然后找到与CDF的水平交点,最后找到x轴上的垂直交点,x轴成为质心,如图蓝点所示。该方法使两峰附近的质心密度增大,但比Forgy方法更分散。
linear initialization 初始化线性空间的中心点之间的[最小,最大]的原始权重。这种初始化方法对权值的分布是不变的,与前两种方法相比是最分散的。
画出了AlexNet中conv3层的权重分布,横坐标是权值大小,纵坐标表示分布,其中红色曲线表示PDF(概率密度分布),蓝色曲线表示CDF(概率密度函数),圆圈表示的是centroids:黄色(Forgy)、蓝色(density-based)、红色(linear)。
可以从图中看到,Forgy 和 density-based 方法产生的centroids很少落入到大权值的范围中,造成的结果就是忽略了大权值的作用;而Linear initialization产生的centroids非常平均,没有这个问题存在;
后续的实验结果也表明,Linear initialization 的效果最佳。
一维k均值聚类的中心是共享权值。在查找权值表的前向阶段和后向传播阶段存在一个间接层。
为每个连接存储共享权重表的索引。在反向传播过程中,计算每个共享权的梯度,并用于更新共享权。这个过程如图3所示。
Huffman Coding 是一种非常常用的无损编码技术。它按照符号出现的概率来进行变长编码。
上图的权重以及权值索引分布来自于AlexNet的最后一个全连接层。由图可以看出,其分布是非均匀的、双峰形状,因此我们可以利用Huffman编码来对其进行处理,最终可以进一步使的网络的存储减少20%~30%。
作者做了大量实验,这样介绍几个,其他有兴趣的可以看论文。
压缩LeNet-300-100 和 LeNet-5模型,其数据集为 MNIST dataset。
略
略