这篇文章是深度学习算法优化系列的第一篇文章,主要解读一篇ICLR 2017年的《Pruning Filters for Efficient ConvNets》,关于通道剪枝策略的一篇论文。论文原地址见附录。
在模型压缩的方法中,包括剪枝,量化,多值网络,模型蒸馏等。这篇论文是模型剪枝当面的。剪枝最初应用应该是在决策树算法中,通过降低决策树的模型复杂度防止过拟合。在CNN中也是类似的思想,因为在大型的模型中,总是不可避免的存在大量的权重冗余,这种冗余甚至有可能降低模型的准确率。因此需要借助剪枝的方法压缩模型,在压缩率合适的条件下,可以提高模型的准确率的同时减少模型大小。同时,在往移动端部署模型的时候也会考虑牺牲一点精度换取时间和空间的节约。CNN的剪枝主要分为两种,一种是基于幅值的剪枝,一种是基于通道的剪枝。基于幅值的剪枝主要思想是将小于一定阈值的权重抛弃,阈值用剪枝率来确定。而基于通道的剪枝主要思想史将不重要的整个权重通道剪掉,从而将模型变小。这篇论文就属于第二类。
CNN在各种应用中的成功伴随着计算量和参数量的显着增加。最近朝着减少这些开销的研究涉及到在不损伤精度的条件下剪枝和压缩不同层的权重。然而,基于幅值的权重剪枝主要是减少了全连接层的参数量,并且由于修剪的不规则性,并没有减少卷积层的计算成本。这篇论文展示了一种对于CNN的加速方法,即直接移除对于CNN精度影响很小的卷积核。通过将网络的这些卷积核以及它们的feature map移除掉,可以极大的减少计算成本。与权重剪枝相比,这个方法不会导致稀疏连接模式。因此,它不需要专门支持稀疏卷积库的支持,它可以使用针对密集矩阵乘法的BLAS库高效处理,我们展示了通过简单的卷积核剪枝可以推理成本,在CIFAR10上,VGG-16的推理成本可降低高达34%,ResNet-110最高可降低38%,同时通过重新训练网络恢复接近原始精度。
n i n_i ni是第 i i i个卷积层的输入通道数, h i h_i hi和 w i w_i wi是输入特征图的高和宽。卷积层将输入维度为 X i ∈ R n i × h i × w i X_i \in R^{n_i\times h_i\times w_i} Xi∈Rni×hi×wi的特征图转化为维度为 X i + 1 ∈ R n i + 1 × h i + 1 × w i + 1 X_{i+1}\in R^{n_{i+1}\times h_{i+1}\times w_{i+1}} Xi+1∈Rni+1×hi+1×wi+1的输出特征图作为下一层的输入。这里卷积核的维度为 n i + 1 × n i × k × k n_{i+1}\times n_i\times k\times k ni+1×ni×k×k,卷积层的乘加操作次数为 n i + 1 × n i × k 2 × h i + 1 × w i + 1 n_{i+1}\times n_i\times k^2\times h_{i+1}\times w_{i+1} ni+1×ni×k2×hi+1×wi+1。如下面的Figure1所示:
当我们把一个卷积核剪掉后,对应的feature map也没了,减少了 n i × k 2 × h i + 2 × w i + 2 n_i\times k^2\times h_{i+2}\times w_{i+2} ni×k2×hi+2×wi+2操作。这是因为当前一个卷积层的卷积核被剪掉后,该层保留的卷积核参数不仅仅在卷积核个数这个维度上缩减了,还和上一个卷积层剪掉的卷积核个数有关,其简介导致了该层卷积核在通道上的缩减。
论文用 F i , j ∈ R n i × k × k F_{i,j}\in R^{n_i\times k\times k} Fi,j∈Rni×k×k来表示第 i i i层的一个卷积核,然后论文提出通过 ∑ ∣ F i , j ∣ \sum|F_{i,j}| ∑∣Fi,j∣,即一个卷积核类所有权值绝对值之和(L1范数)来表示每个层中该卷积核的重要程度。Figure2(a)展示了在CIFAR-10数据集上训练好的VGG16网络中每一个卷积层中每个卷积核权重绝对值之和的分布,可以看到每层的分布是不同的。
同时论文发现剪掉L1值最小的卷积核比随机剪枝或者剪掉最大的卷积核效果更好。从第 i i i个卷积层剪掉 m m m个卷积核的算法过程如下:
为了确定每个卷积层对剪枝的敏感度,论文对每一层独立剪枝并在验证集上对剪枝后的网络进行评估。Figure2(b)展示了这一结果。其中曲线的斜率就可以代表敏感度,斜率比较平缓的说明该层对剪枝的敏感度就更高。论文根据经验来决定对每一层的卷积核进行剪枝,对于深度网络(如VGG-16或ResNets),观察到同一stage相同尺寸的特征图)对应的层对剪枝的敏感度相似,论文对于同一stage的所有层使用相同的剪枝比例。而对于那些敏感度高的层,剪枝时比例很小,甚至完全不进行剪枝。
之前的工作是逐层剪枝然后重新训练来恢复进度。然而理解如何能一次性的对多层进行剪枝是有有必要的:(1)因为对于深层网络来说,逐层剪枝再训练太耗时。(2)整体剪枝的方法可以为网络鲁棒性提供一个全局视野,从而形成了一个更小的网络。(3)对于复杂的网络,一个整体的方法是有必要的。例如对于ResNet,对恒等映射特征图或者每个残差模块的第二层剪枝会导致额外层的剪枝。为了对多层同时剪枝,论文考虑了两个策略。
在剪枝过后,通过重新训练可以补偿剪枝造成的精度损失,有两种策略:
从下面的Table1可以看到,对剪枝后的网络结构从头训练要比对重新训练剪枝后的网络(利用了未剪枝之前的权重)的结果差,这也说明了对小容量的网络训练很难。
其中Tabl2表示了VGG16中各层的剪枝比例,如下:
在CIFAR10上,VGG-16的推理成本可降低高达34%,ResNet-110最高可降低38%,同时通过重新训练网络恢复接近原始精度。
论文原文:https://arxiv.org/abs/1608.08710
再记录一些剪枝相关的论文。
基于权重的剪枝
https://zhuanlan.zhihu.com/p/63779916
因为我也刚开始学习CNN的剪枝,量化等模型压缩技巧,所以还没有什么深度的认识,也仅仅是从文字角度阅读了这篇论文,要真正做好这方面的工作还需要大量论文阅读和代码实践。
欢迎关注我的微信公众号GiantPandaCV,期待和你一起交流机器学习,深度学习,图像算法,优化技术,比赛及日常生活等。