网络剪枝(network pruning)就是要把网络里面的一些参数剪掉。剪枝就是修剪的意思,把网络里面的一些参数剪掉。为什么可以把网络里面的一些参数剪 掉呢?这么大的网络里面有很多很多的参数,每一个参数不一定都有在做事。参数这么多的 时候,也许很多参数只是在划水,什么事也没有做。这些没有做的参数放在那边,就只是占空 间而已,浪费计算资源而已。为何就把它们剪掉呢?所以网络剪枝就是把一个大的网络中没 有用的那些参数把它找出来,把它扔掉。人刚出生的时候,脑袋是空空的,神经元跟神经元间 没什么连接。在六岁的时候会长出非常多的连接。但是随着年龄渐长,有一些连接就慢慢消 失了。这个跟网络剪枝有异曲同工之妙。网络剪枝不是太新的概念,早在这个90年代,Yann Le Cun 的论文“Optimal Brain Damage”是讲网络剪枝,他把大脑(网络)剪枝,把它剪掉一 些权重看成是一种脑损伤,最优的意思是要找出最好的剪枝的方法,让一些权重被剪掉之后, 但是对这个脑的损伤是最小的。
网络剪枝其框架如图1所示,首先,先训练一个大的网络。接下来去衡量这个大的网 络里面每一个参数或者是每一个神经元的重要性,去评估一下有没有哪些参数是没在做事的, 或有没有哪些神经元是没在做事的。怎么评估某一个参数有没有在做事呢,怎么评估某一个 参数重不重要呢。最简单的方法也许就是看它的绝对值。如果这个参数的绝对值越大,它可 能越能对整个网络的影响越大。或者如果它的绝对值越接近零。也许对整个网络的影响越小, 也许对我们任务的影响越小。
图1 剪枝框架
为什么不一次剪掉大量的参数,因为在实验上,如果一次剪掉大量的参数,可能对网络的 伤害太大了,可能会大到用微调也没有办法复原。所以一次先剪掉一点参数。比如说只剪掉 10% 的参数,然后再重新训练,然后再重新剪掉10%的参数,再重新训练,反复这一个过程。 我们可以剪掉比较多的参数,当网络够小以后,整个过程就完成了,就得到一个比较小的网 络。而且这个比较小的网络,也许它的正确率跟大的网络是没有太大的差别的。修剪的单位可 以以参数为单位,也可以以神经元来当作单位,这两者作为单位,在实现上会是有显著不同。 如果我们现在是以参数当作单位会发生什么事,假设我们是要评估某一个参数要不要被去掉, 某个参数对整个任务而言重不重要能不能够被去掉,我们把这个不重要的参数去掉以后,得 到的网络的形状可能会是不规则的。如图2所示,所谓不规则的意思是说,举例来说,红 色的这个神经元连到接下来三个绿色的神经元,但第二个红色的神经元只连到两个绿色的神 经元。或这个红色的神经元的输入只有两个蓝色的神经元,而这个红色的神经元的输入有四 个蓝色的神经元。如果把参数当作单位来进行修剪的话,修剪完以后的网络的形状会是不规则的。
图2 枝的问题
形状不规则最大的问题就是不好实现。用PyTorch要实现这种形状不规则的网络,不好 实现。因为在PyTorch里面,定义第一个网络的时候,定义方法都是每一层有几个神经元,定 义现在每一层要输入几个输入,输入有几个神经元,输出有几个神经元。或者输入多长的向 量,输出有多长的向量。这种形状不固定的网络根本不好实现,而且就算硬是把这种形状不规 则的网络实现出来,用GPU也很难加速。GPU在加速的时候,就是把网络的计算看成一个 矩阵的乘法,但是当网络是不规则的时候,不容易用矩阵的乘法来进行加速,我们不容易用 GPU 来进行加速,所以实际在做权重剪枝的时候,在实现上我们可能会把那些修剪掉的权重 直接补零,就是修剪掉的权重不是不存在,它的值只是设为零。这样的好处是实现就比较容 易,比较容易用GPU加速,但根本就没有真的把网络变小,虽然权重值是零,但还是存了这 个参数,我们还是存了一个参数在内存里面,并没有真的把网络变小。这是以参数为单位来做 剪枝的时候,实现上会遇到的问题。
如图3 所示,紫色的这一条线是指稀疏程度(sparsity)。稀疏程度就是有多少百分比 的参数现在被修剪掉了。紫色的这条线的值都很接近1,代表有接近大概95%以上的参数都 被修剪掉了。网络剪枝其实是一个非常有效率的方法,往往可以修剪到95%以上的参数,但 是准确率只掉12%而已。所以这边参数修剪时,有95%的参数都被丢掉了,只剩下5%的 参数,这个网络变得很小,的计算要很快吧。但实际上我们发现根本就没有加速多少,甚至可 以说根本就没有加速。图17.3中的长条图显示的是在三种不同的计算资源上面,加速的程度。 加速的程度要大过1才有加速,加速程度小于1其实是变慢的。在多数情况下根本就没有加 速,多数情况下其实都是变慢,也就是把一些权重修剪掉,结果网络形状变得不规则,真的用 GPU 加速的时候,反而没有办法真的加速它,所以权重剪枝不一定是一个特别有效的方法。
图3 权重剪枝无法用GPU加速
神经元剪枝,即以神经元为单位来做剪枝也许是一个比较有效的方法。如果用神经元做 单位来剪枝,丢掉一些神经元以后,网络的架构仍然是规则的。这种用PyTorch也比较好实现,实现的时候,只要改那个每一个层输入、输出的那个维度就好了,也比较好用GPU来加速。
接下来要问一个问题:我们先训练一个大的网络,再把它变小,而且说小的网络跟大的网 络的正确率没有差太多。不直接训练一个小的网络就好了,直接训练一个小的网络比较有效 率,还训练大的网络变小干嘛,根本是舍本逐末,为什么不直接训练小的网络?一个普遍的答 案是大的网络比较好训练。如果直接训练一个小的网络,往往没有办法得到跟大的网络一样 的正确率。我们可以先训练一个大的网络,再把它变小,正确率没有掉太多。但直接训练小的 网络,得不到大的网络剪枝完变得小的网络一样的正确率。
为什么大的网络比较好训练?有一个假说叫做彩票假说(lottery ticket hypothesis)。假 说代表说它不算是一个被实证的理论。但它现在只是一个假说而已,这个彩票假说是怎么解 释为什么大的网络比较容易训练,直接训练一个小的网络没有办法得到跟大的网络一样的效 果,一定要大的网络剪枝变小,结果才会好。彩票假说是这样说的,每次训练网络的结果不一 定会一样。我们抽到一组好的初始的参数,就会得到好的结果;抽到一组坏初始的参数,就会 得到坏的结果。但如何在彩票这个游戏里面得到比较高的中奖率,是不是就是包牌买比较多 的彩券,可以增加中奖率,所以对一个大的网络来说也是一样的。大的网络可以视为是很多小 的子网络(sub-network)的组合。如图 4 所示,我们可以想成是一个大的网络里面其实包 含了很多小的网络。训练这个大的网络的时候,等于同时训练很多小的网络。每一个小的网络 不一定可以成功的被训练出来。所谓成功的训练出来是说它不一定可以,通过梯度下降找到 一个好的解,不一定可以训练出一个好的结果,不一定可以让它的损失变低。但是在众多的子 网络里面,只要其中一个子网络成功,大的网络就成功了。而如果大的网络里面包含的小的 网络越多,就好像是去买彩票的时候,买比较多的彩券一样,彩券越多,中奖的概率就越高。 一个网络越大,它就越有可能成功的被训练起来。彩票假说在实验上是怎么被证实的?它在实 验上的证实方式跟网络的剪枝非常有关系,所以直接看一下在实验上是怎么证实彩票假说的。
图 4 大网络包含了很多小网络
如图5 所示,现在有一个大的网络,在这个大的网络上面一开始的参数是随机初始化。 把参数随机初始化以后,得到一组训练完的参数。训练完的参数用紫色来表示,接下来用网络 剪枝的技术,把一些紫色的参数丢掉,而得到一个比较小的网络。如果直接把这个小的网络里面的参数,再重新随机的去初始化,也就是重训练一个一样大小的小的网络,就是我们把这个 网络复制一次。但是参数完全不一样,重新再训练一次。重新再训练一次,直接训练这个小的 网络,训练不起来,训练一个大的再把它变小,没问题。但假设这一个小的网络,再重新初始 化参数的时候,我们用的跟这组红色的参数是一模一样的,就训练得起来。
图5 彩票假说
这两组参数虽然都是随机初始化的,但是这组绿色的参数跟这组红色的参数是没有关系 的。而这边这些随机初始化的参数是直接从这边的红色参数里面选出对应的参数,就是这边 有四个参数。我们就是把这边对应到的这四个参数直接把它复制过来,这边有四个参数。我 们就把这里面对应到的四个参数直接复制过来,把这里面的参数直接复制过来就训练了起来。 如果用彩票假说来解释的话,就是这里面有很多子网络。而这一组初始化的参数,就是幸运的 那一组可以训练得起来的子网络,所以用把这些网络,把这个大的网络训练完,再剪枝掉的时 候,留下来的就是幸运的那些参数,可以训练得起来的那些参数,所以这一组初始化的参数是 可以训练得起来的一个子网络。但是如果我们再重新随机初始化的话,就抽不到可以成功训 练起来的参数,所以这个就是彩票假说。彩票假说非常地知名,它得到了ICLR2019的最佳 论文奖。
后面也有很多后续的研究,比如说有一篇有趣的研究叫做“Deconstructing Lottery Tick ets: Zeros, Signs, and the Supermask”。解构这个彩票有什么有趣的结论,直接讲它的结论。 第一个试了不同的剪枝策略,它做了一个非常完整的实验发现说,如果训练前跟训练后权重 绝对值差距越大,剪枝那些网络得到的结果是越有效的。另外一个比较有趣的结果是,到底这 一组好的初始化是好在哪里呢?如果我们只要不改变参数的正负号,就可以训练起来,小的网 络只要不改变正负号,就可以训练起来。假设剪枝完以后,剩下的这个数。假设剪枝完以后, 再把原来随机初始化的那些参数拿出来,它的值是0.9,3.1,−9.1,8.5,可以完全不管它的数值, 直接把正的数值的通通都用+α来取代,小于0的都用−α来取代,即+α,+α,−α,+α。
用这组参数去初始化模型,这样也训练得起来,会跟用这组参数去初始化差不多。所以这 个实验告诉我们说正负号是初始化参数,能不能够训练起来的关键,它的绝对值不重要,正负 号才重要。
最后一个神奇的发现是,既然我们在想说一个大的网络里面有一些网络有一些子网络,它 是特别是好的初始化的参数,它训练起来会特别地顺利。会不会一个大的网络里面甚至其实 已经有一个子网络,它连训练都不用训练,直接拿出来就是一个好的网络呢?我们完全不用训 练网络,直接把大的网络剪枝,就得到一个可以拿来做分类的分类器了,有没有可能是这个样 子的呢。就好像米开朗基罗说:“塑像就在石头里,我只是把不需要的部分去掉”,会不会在整 个大的网络里面,算参数都是随机的,其中已经有一组参数,它就已经可以做分类了,把多余 的东西拿掉,直接就可以得到好的分类结果的。 但是彩票假说不一定是对的,论文“Rethinking the Value of Network Pruning” 是打脸 彩票假说,而且神奇的是这篇文章跟彩票假说是同时出来的,它们同时出现在ICLR2019,它 们得到了不太一样的结论。这篇文章试了两个数据集,还有好几种不同的模型,这个是没有剪 枝过的网络的正确率,然后它试着去剪枝了一下网络,再重新去做微调。小的网络可以跟大的 网络得到差不多的正确率。然后它说一般人的想像是,如果直接去训练小的网络,正确率会不 如大的网络剪枝完以后的结果。 其实在这篇文章里面也有对彩票假说做出一些回应,它觉得彩票假说观察到的现象,也 许只有在某一些特定的情况下才观察得到。根据这篇文章的实验,只有在学习率设比较小的 时候,还有非结构化的(unstructured)的时候,就是剪枝的时候是以权重作为单位来做剪枝 的时候,才能观察到彩票假说的现象,它发现说学习率调大,它就观察不到彩票假说的这个现 象,所以到底彩票假说的正确性尚待更多的研究来证实。