模型剪枝-网络瘦身(network sliming)
这是一篇ICCV2017年的论文,最近在读剪枝的论文时,有很多论文都提到了这篇文章,因而总结一下该文章的思想。
简述
网络模型越来越大,导致在实际生产环境中,无法将现有的模型有效地部署在边缘设备上。为了解决这一问题,本文的作者提出了一种具有创新性的剪枝流程,该剪枝流程具有一下作用:
- 降低模型大小;
- 降低模型运行时的内存消耗;
- 降低运算操作数。
在本文中,作者主要使用的是通道剪枝算法,即剪除的是模型中的卷积通道。除此之外,也有很多剪枝算法的对象是神经元之间的连接、卷积核中的单一权重等。
作者将他们的方法称为网络瘦身,因为,给定一个宽的大网络作为输入,剪枝算法将输出一个瘦的、紧凑的网络模型。
实现细节
与细粒度剪枝相比,粗粒度剪枝得到的是具有完整结构的卷积核,得到的模型易于部署,不需要底层硬件和矩阵算法的支持。
尺度因子和稀疏度感应惩罚
在该方法中,作者给每一个通道都引入了一个尺度因子$\lambda$,该因子会乘以对应通道的输出。接着,在模型的训练过程中,同时对模型的权重和引入的尺度因子进行训练,并在尺度因子上施加稀疏度正则项。最后,将那些具有较小的尺度因子的通道剪除,并对得到的剪枝网络进行微调。该方法的训练目标函数为:
在具体实现中,将第二项的稀疏度惩罚设置为$L_1$范数,即$g(s)=|s|$。也可以将$L_1$范数替换为$smooth-L1$以避免在不平滑点处使用次梯度。
剪除一个通道会直接移除该通道对应的输入和输出连接,因而可以直接获得一个窄的网络。尺度因子扮演着通道选择的作用,同时,由于同时对网络权重和尺度因子进行训练,网络可以自动识别不重要的权重,并可以很安全地将这些权重移除而不会损失性能。
使用BN层中的尺度因子
批量归一化层使用mini-batch的统计数据对中间层进行归一化,$B$表示当前批,BN层对于输入的特征图进行如下的转换:
其中,$\mu_B$和$\sigma_B$分别表示输入特征图的通道的平均值和标准差。
因为,在现代神经网络中,基本上每一个卷积层之后都会接一层BN层,因此在该方法中,作者直接使用BN层的$\lambda$参数作为尺度因子。
通道剪枝和微调
在使用尺度因子进行稀疏度训练之后,将会得到一个具有很多接近0的尺度因子的网络。接着,将接近0的尺度因子对应的输入和输出的连接和对应的权重剪除。
在进行剪除操作时,以所有的层为基础设定一个全局的阈值(定义为所有尺度因子的值的百分位数)。在剪枝之后,为了恢复由于剪枝导致的性能损失,进一步使用微调进行弥补。
多次重复
上述流程可以被多次重复,以得到更为紧凑的模型。
解决残差连接和预激活结构
对于直上直下式的网络结构,我们可以直接使用上述方法进行通道的裁剪,因为不用考虑通道匹配的问题。
但对于ResNet等有残差连接和预激活设计的网络模型,一个层的输出可以被看作多个子层的输入(残差块的输入),并且,在这一结构中,BN层被放在了卷积层之前(提前激活)。所使用的块结构如下:
很明显,BN层被放在了卷积层之前,并且在每一个残差块的第一个BN层之后都引入了一个通道选择层被用于依据BN的稀疏度对通道进行筛选。也就意味着,并未对这一个BN层之前的卷积层的输出通道进行实质性的裁剪,只是使用了额外的通道选择层降低了计算量。
除此之外,为了保持残差连接的特征图和最终输出的特征图的大小匹配,不对残差块中最后一层卷积层的输出通道进行剪枝,因为我们必须保证两个特征图的通道大小相同。
为了在测试时获得参数和计算量的降低,需要使用channel selection层来过滤掉所识别出的不重要的层。