现在,我们关注的网络结构都是大参数的模型,虽然可能准确率不错,但是实际应用上,我们需要能够把模型应用在移动设备上,但移动设备上的计算力受限,所以模型无法应用,这个时候就有人提出模型压缩、模型蒸馏、Teacher-student等等方法。模型压缩是为了 可以用更少的参数来实现不错的效果。在延迟性、隐私性方面的性能不断提高。
把网路的一些冗杂的参数剪掉。有些参数并没有起到很大的效果。我们要做的事情把这些冗杂的参数找出来,并裁掉。
90年代已经有人发表相关的论文,比如optimal brain damage等等优秀论文。
那么网络剪枝是怎么做的呢,大概的流程是怎么样子的呢?
(1)首先训练的一个大的network
(2)评估每一个参数/神经元的重要程度
那么怎么去评估这个重要性呢?最简单的方法是看他的绝对值。这个参数的绝对值越大,表示对网络的影响能力越大。越接近0表示对网络没什么影响。或者是life long learning中的bi值。
对于神经元呢,则计算神经元输出不为0的次数。
(3)剪掉不重要的参数
(4)通常此时的accuracy会下降一点
(5)通常会用train data重新训练一次 fine -tune 来提高acc
(6)然后再重复2,3来剪掉部分参数,再训练微调。
为什么不一次性剪掉大量的参数呢?因为一次性剪掉大量的参数,可能对你的网络上伤害太大了。可能伤害大到微调也无法恢复很好。所以一次性剪掉一点点。再重新训练,再剪掉参数,再重新训练,反复进行。知道得到一个比较小的模型。
问题1:裁剪参数和裁剪神经元的区别是在哪呢?
(1)如果是修剪参数的话,会导致网络结构不规则,用pytorch不好写以及不好实现。而且当网络形状不规则的时候,你也不容易用矩阵乘法的做法来加速,难以用gpu来进行加速。所以我们一般会将被修剪掉的weights变成0,使得网络结构规则化。但是这样子做的话,我们还是存了这些参数,并没有做到缩小参数缩小网络这个目标呀。内存还是一样,因为一样数量的参数,尽管有些参数值是0.所以尽管你以为你剪裁来95%的参数,但是训练速度和内存还是很不行。因为模型根本没有变小。
(2)如果是修剪神经元的话,是直接把这个神经元和对应的参数拿掉,这样出来的网络结构上是比较容易操作的,也能够加速。所以修剪神经元可能会更好一点。
问题2:为什么不先训练一个小的network,再慢慢变大? --答案不可以
因为大的network比较好train,小的network比较难train。
为什么会认为大的network比较好训练?一个小原因可能是大的network比较好optimize。
具体可以参考大乐透假设这个理解。https://arxiv.org/abs/1810.05270
直接train 小的模型 是无法得到大的模型的效果那么好。
而大的模型变小,效果却不会变的特别差。
问题3:如何裁剪冗杂的参数
评估Network中每个weight和neuron的重要性,裁剪掉不重要的weight或者neuron
(1)weight的重要性: 如果其值接近0,则说明该weight不重要,因此可以计算weight的L1或L2判断weight的重要性
(2)neuron的重要性:给定dataset,如果某个neural的输出都是0那么该neural是不那么重要的
问题4: 相关prune参数的论文研究
(1)大乐透假设 - Lottery Ticket Hypothesis
大乐透假设的论文链接: https://arxiv.org/abs/1803.03635
(2)Rethinking the value of Network Pruning
链接是: https://arxiv.org/abs/1810.05270
模型蒸馏是先train好一个大的network,然后再train一个小的network去学习大的network的行为。
大的network称为 Teacher ;小的network称为 Student
即当Teacher来预测一张数字的照片为 0.7的可能性为1,0.2的可能性为7,0.1的可能性为9.
这个时候,Student的网络结构是学习 Teacher的结果,而不是真实结果。
用交叉熵作为损失函数来更新迭代。
问题1: 为什么说让Student去跟着Teacher去学,会有比较好的结果?
因为Teacher,相对于label data,提供了更丰富的资料。比如,如上图所示,所以Student直接跟data去学,只会知道真实值为1.但是,如果跟Teacher去学,不仅仅会教导你这张照片有很大的可能性是1,而且,这张照片跟7长的很像,跟9也长的有点像。所以Student跟Teacher学习的话,会学到更多的东西。甚至有研究发现,对Student的训练中,从来没有给它看过7这个数字,Student也仍然可能正确地识别7,因为Student跟Teacher学习过 关于7的信息。
Student网络还可以把多个ensemble的teacher的行为学习起来,并成一个Student Net,具体做法是:
把多个Teacher的networks输出的结果,做一个平均得到的一个结果。接下来让Student去学习这个行为结果。所以最终就可以 让一个小的Student network去学习多个Teacher Nets,从而达到一个ensemble的效果。
最后在softmax输出类别的内容上Teacher需要做一个改进的是
正常是直接用Softmax输出判别为某一个label的概率是多少,如果是x1,x2,x3 = 100,10,1
结果就会像下图所示,输出的Y结果区分的并不明显。y1=1,y2=0,y3=0。那么跟直接从label data学习有什么区别呢,Student根本学习不到区别,这个时候加上一个temperature值,来使得y结果值区别比较明显。 能够让Student学习到不一样的信息。
方法一,比如你之前用的是32个bit存参数,现在改为用16个bit来存参数/
方法二是 weights clustering。把不同的clustering取一个均值,压缩成一个小的网络
方法三是 binary weights,即weights are always -1 or +1
里面涉及到binary connect以及 binary nets 以及XNOR net。可以参观相关的论文。
比正常的网络好一点点,可能是因为规定-1和1 起到了 正则化的作用。
调整网络结构是提高网络效率最有效的方法。
在中间插多一层,参数其实是变少的。比如本身是 5x5 变成3x3 和3x3 其实参数是变少了。
参数减少了,但是感受野是一样的,做的事情是差不多的
假设我们是的图片是只有两个channel。如下图所示:
传统的方法是用 2x3x3的滤波器来提取特征;假设我们有4个这样的滤波器。则我们
将产生4个这样的feature maps。所需要训练的参数是 2x3x3x4 = 72
为了能够减少参数,提出一种改进的方法:depthwise convolution + pointwise convolution
depthwise convolution是指用2d的矩阵来滤波,不再像传统的3d的滤波器来滤波。
如果有一张照片是2个channel的,则直接用两个 矩阵一一对应出来的两张feature maps。具体如下图所示:
然后再用pointwise convolution来整合。pointwise convolution其实就是用4个 2x1x1的滤波器来做。然后出来就是4个feature maps,如下图所示:
所以这样子的做的,总共·需要的参数是 2x3x3 + 4x2x1x1= 18 + 8 = 26
相对于传统方法的参数有72个 大大的减少了参数量。
所以我们可以算一个公式:
计算传统的参数所需:
假设m个滤波器 ,矩阵长度是 LxL,channel数为n 则参数所需是: m x n x L x L
而新的方法是:
n x L x L + m x n x 1 x 1 = L x L + mn
所以ratio为
(mm+LL) / mnLL= 1/LL + 1/mm
广泛的应用有 SquzzzeNet\ MobileNet \ ShuffleNet \ Xception
其中最有名就是MobileNet,MobileNet就是为了深度学习可以应用在手机上而提出的。