深度学习模型压缩方法综述(二)
前言
上一章,将基于核的稀疏化方法的模型压缩方法进行了介绍,提出了几篇值得大家去学习的论文,本章,将继续对深度学习模型压缩方法进行介绍,主要介绍的方向为基于模型裁剪的方法,由于本人主要研究的为这个方向,故本次推荐的论文数量较多,但都是非常值得一读的。
基于模型裁剪的方法
对以训练好的模型进行裁剪的方法,是目前模型压缩中使用最多的方法,通常是寻找一种有效的评判手段,来判断参数的重要性,将不重要的connection或者filter进行裁剪来减少模型的冗余。同样也分为regular和irregular的方式。 这类方法最多,下面列举几篇典型的方案。
Pruning Filters for Efficient Convnets 论文地址
作者提出了基于量级的裁剪方式,用weight值的大小来评判其重要性,对于一个filter,其中所有weight的绝对值求和,来作为该filter的评价指标,将一层中值低的filter裁掉,可以有效的降低模型的复杂度并且不会给模型的性能带来很大的损失,算法流程如下:
裁剪方式如下:
对于ResNet之类的网络:
作者在裁剪的时候同样会考虑每一层对裁剪的敏感程度,作者会单*剪每一层来看裁剪后的准确率。对于裁剪较敏感的层,作者使用更小的裁剪力度,或者跳过这些层不进行裁剪。目前这种方法是实现起来较为简单的,并且也是非常有效的,它的思路非常简单,就是认为参数越小则越不重要。Network Trimming: A Data-Driven Neuron Pruning Approach towards Efficient Deep Architectures 论文地址
作者认为,在大型的深度学习网络中,大部分的神经元的**都是趋向于零的,而这些**为0的神经元是冗余的,将它们剔除可以大大降低模型的大小和运算量,而不会对模型的性能造成影响,于是作者定义了一个量APoZ(Average Percentage of Zeros)来衡量每一个filter中**为0的值的数量,来作为评价一个filter是否重要的标准。APoZ定义如下:
作者发现在VGG-16中,有631个filter的APoZ超过了90%,也就说明了网络中存在大量的冗余。作者的裁剪方式如下:
但是作者仅在最后一个卷积层和全连接层上进行了实验,因此该方法在实际中的效果很难保证。An Entropy-based Pruning Method for CNN Compression 论文地址
作者认为通过weight值的大小很难判定filter的重要性,通过这个来裁剪的话有可能裁掉一些有用的filter。因此作者提出了一种基于熵值的裁剪方式,利用熵值来判定filter的重要性。 作者将每一层的输出通过一个Global average Pooling将feature map转换为一个长度为c(filter数量)的向量,对于n张图像可以得到一个n*c的矩阵,对于每一个filter,将它分为m个bin,统计每个bin的概率,然后计算它的熵值 利用熵值来判定filter的重要性,再对不重要的filter进行裁剪。第j个feature map熵值的计算方式如下:
在retrain中,作者使用了这样的策略,即每裁剪完一层,通过少数几个迭代来恢复部分的性能,当所有层都裁剪完之后,再通过较多的迭代来恢复整体的性能,作者提出,在每一层裁剪过后只使用很少的训练步骤来恢复性能,能够有效的避免模型进入到局部最优。作者将自己的retrain方式与传统的finetuning方式进行比较,发现作者的方法能够有效的减少retrain的步骤,并也能达到不错的效果。
在VGG16上作者的裁剪方式和结果如下,由于作者考虑VGG-16全连接层所占的参数量太大,因此使用GAP的方式来降低计算量:Designing Energy-Efficient Convolutional Neural Networks using Energy-Aware Pruning 论文地址
这篇文章也是今天的CVPR,作者认为以往的裁剪方法,都没有考虑到模型的带宽以及能量的消耗,因此无法从能量利用率上最大限度的裁剪模型,因此提出了一种基于能量效率的裁剪方式。 作者指出一个模型中的能量消耗包含两个部分,一部分是计算的能耗,一部分是数据转移的能耗,在作者之前的一片论文中(与NVIDIA合作,Eyeriss),提出了一种估计硬件能耗的工具,能够对模型的每一层计算它们的能量消耗。然后将每一层的能量消耗从大到小排序,对能耗大的层优先进行裁剪,这样能够最大限度的降低模型的能耗,对于需要裁剪的层,根据weight的大小来选择不重要的进行裁剪,同样的作者也考虑到不正确的裁剪,因此将裁剪后模型损失最大的weight保留下来。
每裁剪完一层后,对于该层进行locally的fine-tune,locally的fine-tune,是在每一层的filter上,使用最小二乘优化的方法来使裁剪后的filter调整到使得输出与原始输出尽可能的接近。在所有层都裁剪完毕后,再通过一个global的finetuning来恢复整体的性能。整个流程如下:
作者从能耗的角度对层的裁剪程度进行分析,经过裁剪后,模型的能耗压缩较大:Coarse Pruning of Convolutional Neural Networks with Random Masks 论文地址
此文的方法比较有意思,作者认为,既然我无法直观上的判定filter的重要性,那么就采取一种随机裁剪的方式,然后对于每一种随机方式统计模型的性能,来确定局部最优的裁剪方式。 这种随机裁剪方式类似于一个随机mask,假设有M个潜在的可裁剪weight,那么一共就有2^M个随机mask。假设裁剪比例为a,那么每层就会随机选取ML*a个filter,一共随机选取N组组合,然后对于这N组组合,统计裁剪掉它们之后模型的性能,然后选取性能最高的那组作为局部最优的裁剪方式。 算法流程如下:
作者同样将这种裁剪方式运用在kernel上,对kernel进行裁剪,并将filter级和kernel级的裁剪进行组合,得到了较好的结果。方法简单粗暴,看起来也比较有效,没有考虑每一层对于裁剪的敏感性,也没有评价参数的重要性,可能需要尝试多个mask才能得到较好的结果。
Efficient Gender Classification Using a Deep LDA-Pruned Net 论文地址
作者发现,在最后一个卷积层中,经过LDA分析发现对于每一个类别,有很多filter之间的**是高度不相关的,因此可以利用这点来剔除大量的只具有少量信息的filter而不影响模型的性能。 作者在VGG-16上进行实验,VGG-16的conv5_3具有512个filter,将每一个filter的输出值中的最大值定义为该filter的fire score,因此对应于每一张图片就具有一个512维的fire向量,当输入一堆图片时,就可以得到一个N*512的fire矩阵,作者用intra-class correlation来衡量filter的重要性:
具体实现如下:
其中:
Sw为类内距离,Sb为类间距离,作者这样做的目的是通过只保留对分类任务提取特征判别性最强的filter,来降低模型的冗余。 在前面几个卷积层,由于提取的特征都是很简单的特征,如边缘、颜色,直接对它们求ICC可能难以达到好的效果,因此作者在这些层之后接了deconv层,将特征映射到pixel级别,再来计算。 对于VGG最后用来分类的全连接层,作者认为参数量太大,故用Bayesian或者SVM来替代,在目前的ResNet或者Inception中不存在这样的问题,可以不用考虑。在VGG16上,本文方法裁剪的力度还是比较大的,但是本文作者做的任务为性别识别,在其他任务中的效果未知。Sparsifying Neural Network Connections for Face Recognition 论文地址
本文为2016年的CVPR,应用场景为人脸识别的模型:DeepID。作者认为,如果一层中的某个神经元的**与上一层的某个神经元的**有很强的相关性,那么这个神经元对于后面层的**具有很强的判别性。也就是说,如果前后两层中的某对神经元的**具有较高的相关性,那么它们之间的连接weight就是非常重要的,而弱的相关性则代表低的重要性。如果某个神经元可以视为某个特定视觉模式的探测器,那么与它正相关的神经元也提供了这个视觉模式的信息,而与它负相关的神经元则帮助减少误报。作者还认为,那些相关性很低的神经元对,它们之间的连接不一定是一点用也没有,它们可能是对于高相关性神经元对的补充。在全连接层中,计算方式如下:
其中 ai 是当前层的一个神经元,上一层有 K 个神经元,为bik。
卷积层的计算方式如下:
其中 aim 是当前层第 i 个feature map中的第 m 神经元,bmk 应该是上一层 feature map 中与aim连接的神经元。
本文的算法流程如下:
作者提供了一个基于神经元**相关性的重要性判别方法,属于irregular的方法,在计算公式上增加一个求和项可以将这种方法拓展到filter级上。但是作者在实验中并没有对所有的层进行裁剪来比较效果,但是在人脸识别任务上的效果确实是非常好。Pruning Convolutional Neural Networks for Resource Efficient Transfer Learning Inference 论文地址
本文为今年的ICLR,Nvidia的工作,作者将裁剪问题当做一个组合优化问题:从众多的权重参数中选择一个最优的组合B,使得被裁剪的模型的代价函数的损失最小,即:
这类似于Oracle pruning的方式,即通过将每一个weight单独的剔除后看模型损失函数的衰减,将衰减最少的参数认为是不重要的参数,可以剔除,这也是OBD的思路,但是OBD的方法需要求二阶导数,实现起来难度较大,而本文提出的Taylor expansion的方法可以很好的解决这个问题:
其中hi=0表示hi这个feature map被剔除,因此,可以通过将损失函数C在hi=0出进行Taylor展开,因此就可以将损失函数的衰减转化成损失函数对feature map的梯度和feature map**乘积的绝对值,这样就能够用来评价参数的重要性,由于是一个Global的裁剪,因此将每一个Taylor展开计算得到的值进行标准化:
并将计算量(Flops)考虑进去:
为了评价作者方法的有效性,作者通过Taylor对所有的filter进行评级,然后将评级顺序与Oracle pruning得到的评级顺序计算一个相关性,作者也将其他的裁剪方法,如weight大小、feature map**等方法分别于Oracle的方法计算相关性,得到的结果如下表:
发现Taylor的方法确实与Oracle的方法最接近的,从上表我们还发现,OBD的效果也与Oracle非常接近,在某些任务上,甚至超过了Taylor的方法,可见这个上世纪80年代提出的方法多么伟大。
本文的方法还有一个优点就是,可以在训练的反向过程中将梯度记录下来,然后与feature map的activation直接相乘,可以达到边训练边裁剪的效果。
总结
可以看出来,基于模型裁剪的方法很多,其思路源头都是来自于Oracle pruning 的方法,即挑选出模型中不重要的参数,将其剔除而不会对模型的效果造成太大的影响,而如何找到一个有效的对参数重要性的评价手段,在这个方法中就尤为重要,我们也可以看到,这种评价标准花样百出,各有不同,也很难判定那种方法更好。在剔除不重要的参数之后,通过一个retrain的过程来恢复模型的性能,这样就可以在保证模型性能的情况下,最大程度的压缩模型参数及运算量。目前,基于模型裁剪的方法是最为简单有效的模型压缩方式。(未完待续)