- Network Compression
十七、Network Compression(网络压缩)
原因:移动设备存储有限,不能存太深或太大的network,我们希望可以把我们的network缩小让它可以fit这些设备上有的运算资源。
可以让network变小的方式:
- Network Pruning(网络剪枝)
- Knowledge Distillation(知识提炼)
- Parameter Quantization(参数量化)
- Architecture Design(建筑设计)
- Dynamic Computation(动力计算)
(一)Network Pruning(网络剪枝)
把一个大的 network的一些weight或者neuron剪掉,让它变得比较小。
为什么可以做Network Pruning这件事?因为networks通常是over-parameterized(过度参数化)。
Network Pruning在文献上是怎么做的:
(1)首先要有一个network,是已经train好的,接下来评估在这个大的network里面的每一个weight或neuron的重要程度。
怎么评估一个weight或neuron的重要程度呢?
评估weight的重要性:看weight数值,如果比较接近0,那就是比较不重要的weight;或者说那个weight的值非常正,它可能就是一个重要的。所以可以就算一个weight的L1或L2的数值,然后看看这个weight是重要的还是不重要的。
评估neuron的重要性:如果给定一个data set,某个neuron的output几乎都是0的话,这个neuron可能就是一个不重要的neuron。
(2)把所有的weight或所有的neuron按重要性排序,移除不重要的weight或不重要的neuron,移除之后,本来比较大的network就变得比较小了,现在得network跟原来得不一样了,移除了一些东西performance就会掉一点。
(3)把刚才的损伤recover回来,做法:把新的network在原来的资料上再Fine-tuning(微调),再去update参数,损伤一般都可以复原。
(4)接下来看丢掉weight和neuron后network的大小是否满意,如果是就结束了。但是通常remove不会丢掉太多东西,如果一次丢掉太多,损伤就太严重,所以常见的做法是一点点移掉。
为什么要做pruning?为什么一开始不train一个比较小的network?
常见的说法是,小的network比较难train。大的 network可能比较容易optimize。
一个文献提出了一个大乐透假设:
一般做pruning,先train一个大的network,初始化这个大的network的参数,然后train完pruning掉不要的weight。作者发现直接train小的network,参数是重新random initialize的,结果发现是train不起来的;如果现在一样train小的network,参数是之前train好的model 的weight来initialize这一个比较小的network,发现就可以train起来了:
大乐透假设:network就像买乐透,在买乐透时你的票越多,中奖的几率越高。不同的random initialize的weight,有时候train的起来,有时候train不起来,一个巨大的network可以想象里面就是有很多的sub network。
另一篇文章说明小的network也可以train的起来:
network pruning实践上的问题:
(1)weight pruning
经过weight pruning之后,network变得不规则,即同一层里面有的neuron是吃两个input,有的neuron是吃三个、四个input,这样的network很难去implement(执行)以及speedup(加速)。
(2)Neuron pruning
Neuron pruning可能是比较好的方法:
(二)Knowledge Distillation(知识提炼)
Knowledge Distillation就是说我们可以先train一个大的network(Teacher Net),再train一个小的network(Student Net)去学习大的network的行为,即小的network看到一样的东西,可以得到和大的network一样的output。为什么小的network跟着大的network去学可以得到比较好的结果?因为teacher net提供了比label data更丰富的资料。
以上的例子,teacher net不仅教会了student net这张图片是1,还教会7跟1很像,9跟1很像,在输入7的image的时候可能也可以得到正确的辨识结果。
Knowledge Distillation有用的地方就是可以把你ensemble的model并起来变成一个model,也就是说现在ensemble一大堆network,把这些network的output平均得到答案,接下来让student net去学ensemble network的output,希望student net的output跟ensemble的结果一样,到时候只需要一个model的就可以达到ensemble的效果。
实践Knowledge Distillation有一个常用的技巧,softmax layer把network output的值(假设network 在最后一层output的值为
x
x
x)做一系列运算后得到最后的结果
y
y
y:
在做Knowledge Distillation时会把
x
x
x的值除以T(Temperature,通常大于1的值):
为了让teacher的行为更容易让student学到,会拉近不同label间的分数,比如:
(三)Parameter Quantization(参数量化)
一般有两种方法:
(1)使用较少的bits去表示值,network size变小;
(2)做weight clustering:举个例子,如下图是一个network的weight,把这些weight进行clustering,比如现在分成4群,用不同的颜色表示,如下图,之后再存这个network时,不需要存储真正的数值,只需要存它的cluster的id:
(3)可以更进一步压缩network,把比较常出现的cluster给予比较少的bit来表示,比较少出现的cluster给予比较多的bit来表示。
binary weight:只用+1和-1来表示一个weight。
binary connect:下图代表一个参数的space,某一点代表某一组参数,灰点代表这一点的参数都是binary 的。随机在这个space中initialize一组参数,一般train network是拿这组参数去计算gradient,但是在binary connect中去找跟这组参数最接近的一个有binary weights的network,根据这个binary weights的network去计算它的gradient,如下图:
(四)Architecture Design(建筑设计)
调整network的架构设计,减少需要的参数量。
怎么调整network的架构设计?
现在有一个network前一层有N个neuron,下一层有M个neuron,前一层到下一层中间W代表network的weight,现在前一层和下一层之间再插一层hidden layer,这个hidden layer有K个neuron,它们是linear的,没有激活函数。这一层把原来W这一层变成U+V两层,参数变少了。
为什么多加一层参数变少了?
之前的weight为M乘于N,V这一层有N乘于K个weight,U这一层有K乘于M个weight,把这个U乘上V让它可以做到原来W可以做到的事,设计时调整一下让K的值不要太大:
Depthwise Separable Convolution(深度可分卷积):
步骤1:Depthwise Convolution的filter不是立体的,限制是你的input有几个channel,那你就设几个filter,每个filter就负责一个channel,filter不是立体的,它的size都是kxk的矩阵:
接下来就拿每个filter各自去处理它们负责的channel,就会得到feature map。不同的channel之间没有交集。
步骤2:Pointwise Convolution(逐点卷积),使用1x1的filter来处理不同channel之间的关系。举例来说,现在有1x1的filter,它的参数就只有两个(因为input现在有两个matrix), 把这个1x1的filter扫过input 的feature map,和一般的convolution相比,这个方法在第二步的filter的大小是固定的,如下图,扫描之后得到一个4x4的matrix,有几个1x1的filter就得到几个4x4的matrix:
在第一步使用3x3x2=18个参数,在第二步使用2x4=8个参数,一共使用26个参数,而同样大小的input在一般的convolution中需要72个参数。
更直观地解原来的convolution跟Depthwise Separable Convolution有什么关系?
在下图的假设下,一般的convolution需要的参数量为(
(
k
×
k
×
I
)
×
O
(k\times k\times I)\times O
(k×k×I)×O),Depthwise Separable Convolution的参数量为(
k
×
k
×
I
+
I
×
O
k\times k\times I+I\times O
k×k×I+I×O):
应用:
(五)Dynamic Computation(动力计算)
减少运算量,先求有再求好,如果运算资源充足,那么就做到最好。
解决方法有以下几种:
(1)Train multiple classifiers:train一把network,从最深的到最浅的,选择一个适当的满足情景的network;
(2)Classifiers at the intermedia layer:train一个network,这个network面对不同的限制有不同的应对,举例来说,可以在一个network每一个中间hidden layer拿出来做classifier:
本文是对blibli上李宏毅机器学习2020的总结,如有侵权会立马删除。