Network Compression 1_6
先train好一个大的network,然后评估network中哪些neuron重要,哪些不重要。如果weight接近0可能是不重要的weight。给一个input,如果output几乎都是0,那这个neuron就不重要。
将这些neuron按照重要性排序,移除不重要的weight和neuron。移除最不重要的weight或neuron,所以performance不会掉太多。移除之后,拿这个新的neuron再回到训练集中训练一下,fine-tune一下,这样往往就可以恢复到移除前的performance。
fine-tune完之后要重新计算一下weight和neuron的重要程度。
Network Compression 2_6
为啥不直接train一个小network?而是要大network再pruning?一般说法是,小network比较难train。
大的network比较容易optimize。所以或许train 一个大network再prunning会比较好。
如果先random initialize network的参数,train完之后做prunning成小network,是可以的。但如果直接把这个小network拿出来,做random initialize来train,结果发现这个小network是train不起来的。
但如果还是这个小network,不重新random initialize,而是拿一开始就拿大网络random initialize好的参数复制到小网络来,则这个小网络是原来大网络的子网络,居然可以train。
该现象应该是很general的。这篇2019 ICLR的论文的大乐透假说(lottery ticket hypothesis)由此而来,该假说认为,network训练就想买彩票,train一个大网络其实是在大网络中包含的很多个小网络里找一个”中奖“小网络,这个小网络random initialize后train得起来,大网络就train得起来,所以prunning后效果差不多。
但是还有一篇2019-ICLR认为,小network照样train的起来。train from scratch的网络甚至比fine-tuned的网络效果还好。而且这个train from scratch的网络用的random initialize是真正的重新initialize。所以这两篇论文的结论是相反的!
可以prune weight,也可以prune neuron,但是prune哪个更好?
下面是prune weigth,这导致neuron是不规则的输入输出,很难部署。就算能部署出来,GPU不好加速。。因为GPU是做矩阵运算的,没有矩阵就没法用GPU加速。
所以实际并没有把这些weight prune掉,实际只是把这些weight的值设为0。虽然把这些weight设为0,但是实际上没有prune掉,所以network大小不会变。
prune的效果如下图,network为AlexNet,右边为稀疏度(prune的程度),可以看到靠右边接近95%的neuron被prune掉了,网络性能基本没怎么掉。奇怪的是,实际上用了不同的GPU测速度,发现居然不一定能加速!甚至有时候speedup是小于1的,因为network不是regular的,GPU加速的时候不好操作,导致prune之后反而没有加速,而是更慢了。
prune neuron可能会比较好
Network Compression 3_6 knowledge distillation 知识蒸馏
可以先train一个大network,再train一个小network,来学习大网络的知识。我们希望train小网络不是直接让输入对应其正确的label,而是让小网络学到的东西直接让大网络来学。这时候小网络也知道输入图像是"1"的概率是0.7等等,小网络就能学到更多的东西,甚至学到它不曾见过的东西,如小网络可能从来没见过“7”,但是却可以辨识“7”。
knowledge distillation还有一个作用,就是用在model ensemble的时候。只需要一个model(student net)就可以达到多个network ensemble的效果。
以温度预测(输出softmax)举例如下:李老师说实际使用knowledge distillation没有特别有用。
Network Compression 4_6 parameter quantization参数量化
一种方法是以更少的比特数存储参数,达到压缩的效果。还有一种方法是weight聚类,然后用聚类后的平均来代替原来的数。第三种如图,把常出现的用更少的bits表示,把少出现的用给更多的bits表示,如霍夫曼编码。
甚至可以直接让参数二值化
结果甚至可以比原网络要好。可以认为binary weight是一种normalization。
Network Compression 5_6 architecture design参数设计
也许这个方法是实际上最有效的做法
如果是FC层,可以在中间插一个linear
depthwise convolution是比较典型的将convolution简化的方法。第一步是depthwise convolution,只进行空间卷积,具体操作如图
第二步是pointwise convolution,只进行channel卷积。
动态计算,资源多就多算,资源少就少算。
解决方法是中间插入多个classifier
这样会导致整个CNN的结构,final classifier掉点