本文主要从几篇论文以及几篇博客分享谈一下现在的剪枝发展,以及从自己的一些实践中实际剪枝的实验效果。
参考文章
- 《Pruning and Quantization for Deep Neural Network Acceleration: A Survey》2020
- 《RETHINKING THE V ALUE OF N ETWORK PRUNING》2019
- 《THE LOTTERY TICKET HYPOTHESIS : FINDING SPARSE , TRAINABLE NEURAL NETWORKS》2019
- 《Filter Pruning via Geometric Median
for Deep Convolutional Neural Networks Acceleration》2019年CVPR,百度OCR采用的剪枝策略 - 《Learning Efficient Convolutional Networks through Network Slimming》2017年CVPR剪枝论文,实践简单
参考博客
- 闲话模型压缩之网络剪枝(Network Pruning)篇
- Some intuition about over parameterization
- 卷积神经网络通道剪枝算法小结
一、剪枝的理论基础
剪枝的理论基础就是过参数化(Over-parameterization)。在传统的机器学习中,过参数化意味着过拟合。
过拟合的原因是参数太多了,过多参数可以可以以任意精度近似任何Borel可测的函数。在传统机器学习中,如果学习到训练数据的细枝末节,以至于将不是特征的偶然相同也学习到,那么随着训练轮数加深,网络的训练误差逐渐减小,而val loss逐渐增加。呈现上图所示的现象。因此在传统网络中需要避免过拟合。
但是在深度学习中过参数化是不可或缺的。
(下面内容来自博客[Some intuition about over parameterization]https://zhuanlan.zhihu.com/p/40516287))
- 万能逼近定理:足够大的MLP可以表示任何函数。只要给网络足够多的hidden unit,它就可以以任意精度近似任何Borel可测的函数。(这一块的理论由于年代久远,而且也比较公认了,所以没啥好说的。ICLR17上,有一个工作也做了类似的研究,做了一个很有趣的实验,用随机标签标注数据,让网络去学,发现training loss依然能降下来[1]。)
- Deeper and Wider:大量的empirical结果,都表明合理的增加宽度/深度可以获得肉眼可见的性能提升。(由于我只关注CNN方向的内容,所以只举例CNN与图像的例子。最典型的例子就是在15年提出来的ResNet[2],直接做了1001层网络的尝试,而且依然很成功的收敛了(当然这里也有瑕疵,V1中的ResNet由于activation的问题,1001的网络性能并没有达到预期的结果,但依然收敛到了可以接受的水平,结构问题在V2中做出了修改,最终1202网络的性能达到了预期的效果);其次就是BMVC16上的wide ResNet[3],在宽度上下了文章,同样取得了很好的效果)
- Deep Double Descent: 这是OpenAI在论文中提到的一个现象,随着模型规模的增大,val loss并没有像预期(传统ML观点)那样单纯越来越高,而是在达到一个临界点后,会降的更低[4],文章对这个现象做了详细的分析。
在深度学习中,从一个大的、过参数化的模型开始训练是有必要的,因为这样的模型具有很强的表示和优化能力。一旦训练完成到了推理阶段,我们并不需要这么多的参数。这样的假设就支持我们可以在部署前对模型进行简化。模型压缩中的pruning和quantization两类方法正是基于这样的前提。
二、剪枝技术
2.1 剪枝发展
以下内容搬自闲话模型压缩之网络剪枝(Network Pruning)篇)
剪枝的核心问题是成如何有效地裁剪模型且最小化精度的损失。
其实这不是一个新的问题,对于神经网络的pruning在上世纪80年代末,90年代初左右就有研究了。如论文《Comparing Biases for Minimal Network Construction with Back-Propagation》提出了magnitude-based的pruning方法,即对网络中每个hidden unit施加与其绝对值相关的weight decay来最小化hidden unit数量。又如上世纪90年代初当时经典的论文《Optimal brain damage》与《Second order derivatives for network pruning: Optimal Brain Surgeon》分别提出OBD和OBS方法,它们基于损失函数相对于权重的二阶导数(对权重向量来说即Hessian矩阵)来衡量网络中权重的重要程度,然后对其进行裁剪。但因为当时的大环境下,神经网络(那时没有deep neural network,只有neural network,或为区分称为shadow neural network)并不是机器学习的一个特别主流的分支,因此之后的很长一段时间也没有大量开枝散叶,但他们对问题的梳理定义和解决问题思路对二十多年后的很多工作产生了深远的影响。
到了2012年,我们都知道深度学习一战成名,大放异彩。
之后刷榜之风兴起且愈演愈烈,大家的注意力就是提高精度。于是大趋势就是不断地加深加重网络以提高精度,ImageNet准确率每年都创新高。
2015-16年期间,Hang Song等人发表了一系列对深度神经网络进行模型压缩的工作。如《Learning both weights and connections for efficient neural networks》,《EIE: Efficient inference engine on compressed deep neural network》。
其中《Deep Compression: Compressing Deep Neural Networks with Pruning, Trained Quantization and Huffman Coding》获得了ICLR 2016的best paper。其中对当时经典网络AlexNet和VGG进行了压缩。结合pruning,quantization和huffman encoding等多种方法,将网络size压缩了几十倍,性能获得成倍的提升。其中对于pruning带来的精度损失,使用了iterative pruning方法进行补偿,可以让精度几乎没有损失。这让大家意识到DNN参数冗余程度如此之大,可榨油水如此之多。之后这几年,模型压缩领域变得越丰富,越来越多的相关工作衍生出各种玩法。
2.2 剪枝分类
按照剪枝之后的结构是否依旧是对称的,剪枝可以分为结构化剪枝和非结构化剪枝。
从剪枝的粒度上,可以分为:
- 单个神经元剪枝,这种剪枝方式因为会得到非结构化的网络结构也被称为非结构化的剪枝,剪枝之后的卷积核的权重参数稀疏化。这种剪枝往往不能适用于现在已经比较成熟的底层加速库BLAS。
- channel-wise,从这个层次开始都是结构化剪枝。通道剪枝和过滤器剪枝很容易弄混,这里仔细的解释两者的区别。假设某层的输入为,输出为,那么每个卷积核和通道数量为的输入feature map计算得到输出的一个通道。通道剪枝可以理解为对于的卷积核剪枝得到的卷积核,。这种剪枝实际上是减掉了之前输入层的一些通道。
- filter-wise,过滤器剪枝,同样以上面的情况为例,假设某层的输入为,输出为,通过过滤器剪枝之后,实际的输出层数为,并且。原本需要个的卷积核计算的输出,现在只要个就可以计算得到输出。这种剪枝实际上是减掉了本层输出层的通道数。
- shape-wise,这不是很清楚~还没有深度接触过
- layer-wise,这个就是把整个层都删掉了。
近些年的研究主要是集中在结构化剪枝上的。
2.3 剪枝方法
剪枝主要是减掉不重要的参数,那么怎么衡量参数的重要性。这里对剪枝方法的分类主要来自于闲话模型压缩之网络剪枝(Network Pruning)篇
2.3.1 用参数的绝对值大小和衡量重要性
一个最简单的启发就是按参数(或特征输出)绝对值大小来评估重要性,然后用贪心法将那部分干掉,这类称为magnitude-based weight pruning。
这种情况,往往需要参数是稀疏的,因此在训练时loss中加regularizer,尤其是L1 regularizer,从而使得权重稀疏化。对于structured pruning来说,我们想获得结构化的稀疏权重,因此常用group LASSO来得到结构化的稀疏权重。
为了剪枝掉参数较小的网络,可以对卷积层中的采纳数进行权重稀疏化,比如Learning Structured Sparsity in Deep Neural Networks》;可以对BN层的参数进行稀疏化训练,比如2017年的论文《Learning Efficient Convolutional Networks Through Network Slimming》;也可以对激活函数输出,像Relu这样的激活函数会倾向产生稀疏的activation,这样就可以减掉前面的通道层,比如2016年论文《Network Trimming: A Data-Driven Neuron Pruning Approach towards Efficient Deep Architectures》。
这种方法有个假设就是参数绝对值越小,其对最终结果影响越小。我们称之为’‘smaller-norm-less-important’'准则。然而这个假设未必成立(如2018年的论文《Rethinking the Smaller-Norm-Less-Informative Assumption in Channel Pruning of Convolution Layers》有对其的讨论)。
2.3.2 考虑参数剪裁对loss的影响
上世纪90年代初当时经典的论文《Optimal brain damage》与《Second order derivatives for network pruning: Optimal Brain Surgeon》分别提出OBD和OBS方法,它们基于损失函数相对于权重的二阶导数(对权重向量来说即Hessian矩阵)来衡量网络中权重的重要程度,然后对其进行裁剪。
这两种方法需要计算Hessian矩阵或其近似比较费时。近年来有一些基于该思路的方法被研究和提出。如2016年论文《Pruning Convolutional Neural Networks for Resource Efficient Transfer Learning》也是基于Taylor expansion,但采用的是目标函数相对于activation的展开式中一阶项的绝对值作为pruning的criteria。这样就避免了二阶项(即Hessian矩阵)的计算。2018年论文《SNIP: Single-shot Network Pruning based on Connection Sensitivity》将归一化的目标函数相对于参数的导数绝对值作为重要性的衡量指标。
2.3.3 特征输出的可重建性的影响
对特征输出的可重建性的影响,即最小化裁剪后网络对于特征输出的重建误差。它的intuition是如果对当前层进行裁剪,然后如果它对后面输出还没啥影响,那说明裁掉的是不太重要的信息。典型的如2017年论文《ThiNet: A Filter Level Pruning Method for Deep Neural Network Compression》和《Channel pruning for accelerating very deep neural networks》都是通过最小化特征重建误差(Feature reconstruction error)来确定哪些channel需要裁剪。
2.3.4 基于同一层特征的可替代性
2019年的CV顶会CVPR上提出的一篇剪枝文章《Filter Pruning via Geometric Median for Deep Convolutional Neural Networks Acceleration》这篇文章对较小范数不重要原则的进行重新审视。这个原则的基本要求是
- 第一,卷积核的范数值分布偏差必须大,即方差大,才能有足够的搜索空间来选择合适的阈值T,进而很容易将具有较小范数的卷积核裁剪掉;
- 第二,卷积核中的最小范数必须足够小.即接近于0.而不是相对于其他卷积核较小.
因为大部分网络无法满足这个要求,因此提出了一个新的角度,如果一个filter可以被同一层的其他filters表征,那么说明这层是冗余的,即是可以被删除的。删除冗余层对整个层的影响是最小的,可以通过其他filters很快的恢复冗余层的信息。
那么什么样的filter是冗余层呢?什么层可以被同层的其他filters表征呢?
答案是该层的几何中心或者说接近几何中心的filters。在2008年的顶会CVPR的论文《Robust statistics on riemannian manifolds via the geometric median》提到了几何中心可以被几何中心附近的其他filters表征,这个理论奠定了这篇论文的理论基础。
2.4 剪枝分析
2.4.1 剪枝比率
剪枝比率是剪枝之后的参数占原始参数的比率。
- 事先对每层的剪枝比率进行设置,这种方式在剪枝之前就已经知道了剪枝之后的网络结构。
- 在训练过程中学习得到各层的剪枝比率,也就是在训练完成之前,我们不清楚最后产生的模型结构,比如NetSlimming方法,在训练结束之后对全局的BN参数进行排序,减掉全局指定比率的参数,有可能一些层被删掉80%,另一些层只剪掉10%。
- 2018年论文《ADC: Automated Deep Compression and Acceleration with Reinforcement Learning》提出ADC(Automated deep compression)方法,根据不同需求(如保证精度还是限制计算量),利用强化学习来学习每一层最优的sparsity ratio。
2.4.2 剪枝过程
剪枝可以分为静态剪枝和动态剪枝。
- 静态剪枝往往分为三步走,训练-剪枝-finetune。
- 动态剪枝在训练的过程中完成剪枝,训练完成之后的模型就是剪枝完成的模型,因此不需要像静态剪枝那样不停的finetune
三、剪枝讨论
3.1 原始模型的初始化参数是否重要?
在传统的静态剪枝策略中,前人的研究发现从剪枝之后的网络结构重新初始化权重然后训练很难达到和剪枝前相同的精度。但是每次剪枝之后对保留的参数权重进行较少轮次的finetune的训练却可以使得相同的剪枝之后的网络结构达到或者只是略低于剪枝之前的精度。因此我们的共识是剪枝之后留下的网络结构和网络参数的权重都很重要。
但是ICLR2019的best paper《The Lottery Ticket Hypothesis》首次提出了反对的意见。
这篇论文进行了这样的实验:
- 对初始复杂网络进行初始化,然后开始训练
- 剪枝获得的子网络,清除剪枝之后的参数权重,用第一步中的初始化参数值进行初始化,然后训练
- 子网络训练达到收敛的迭代次数,不超过原网络所需的迭代次数。剪枝网络可以达到相同的精度。
- 如果子网络的初始化数值不取自原网络,而是按新的随机初始化方式执行训练,通常不会达到原网络的推理精度。
结论一:始终存在较小的子网络,它们从头开始训练,并且至少与较大的子网络一样快地学习,同时达到类似的测试精度。
但是同年同会议的另一篇论文《Rethinking the Value of NetWork Pruning》给出了结论类似但又有些不同的观点。这篇论文同样否定了剪枝之后保留权重的重要性,但是也否定了保留初始化参数的必要性,认为剪枝之后的finetune得到的模型效果,往往差于直接从头训练剪枝模型,虽然从头训练剪枝之后的结构的模型往往需要更多的训练轮次。
为什么之前的论文实验中,从头开始训练的实验效果都没有使用剪枝之后的参数的效果好?因为想当然的思想,使得之前的在“ 从头开始训练的”实验中没有仔细选择超参数、数据扩充策略,并且也没有给从头开始训练足够的计算时间和轮次(因为作者提到从头开始训练需要更多的轮次才能得到和利用剪枝参数进行finetune类似的精度)
3.2 预先定义每层的剪枝比率和训练中学习剪枝比率
《Rethinking the Value of NetWork Pruning》中的实验还有一个结论,就是网络剪枝的作用就是网络结构搜索。
作者针对《 Learning efficient convolutional networks through network slimming》这篇文章进行了5次随机从头训练,发现如果指定比率剪枝,那么5次剪枝之后,每层的保留层数总是神奇的相似,这说明这个方法确实可以得到一个比较高效稳定的结构。
关于预定义每层的剪枝比率以及根据训练结果动态计算剪枝比率两种方式,《Rethinking the Value of NetWork Pruning》给出的实验标明:在VGG网络上,net-slimming剪枝策略优于每层等比例剪枝,而在ResNet,DenseNet上,net-slimming剪枝策略可能不如每层等比例剪枝。
作者分析了这些网络剪枝之后的结构,发现这种结构趋向于每层等比例剪枝,这可能就是这个策略剪枝之后的效果约等于每层等比例剪枝的原因。而VGG网络每层的冗余并不是均衡的,因此剪枝策略有效。
结尾
正如目前的研究所表明的
- 剪枝算法和网络结构搜索的边界已经模糊了,剪枝本质上可以看成是对已有的冗余网络的最优结构搜索
- 对于剪枝的基本假设过参数化以及已有参数是否重要这些假设前提也貌似摇摇欲坠。
- 剪枝和其他领域的技术也在融合,2019年论文《Towards Optimal Structured CNN Pruning via Generative Adversarial Learning》采用了GAN的思想,让generator生成裁剪后网络,discrimintor来判别是否属于原网络还是裁剪后网络,从而进行更有效的网络结构化裁剪。
- 期待未来的研究吧~