Network Compression 视频 李宏毅

Network Compression 视频 李宏毅

课程视频(B站):李宏毅2020机器学习深度学习(完整版)国语 P43-P50

课程官网:http://speech.ee.ntu.edu.tw/~tlkagk/courses_ML20.html

课程笔记(知乎):https://www.zhihu.com/column/c_1325525429269671936

网友github代码:https://github.com/chouxianyu/LHY_ML2020_Codes

github:https://github.com/jacobgil/pytorch-pruning 待看!!!

Outline

  • Network Pruning
  • Knowledge Distillation
  • Parameter Quantization
  • Architecture Design
  • Dynamic Computation

Network Pruning 剪枝

P43 Network Compression (1_6)08:24

Network can be pruned

  • 网络一般都是“over-parameterized”,对于任务来说训练太多参数。 看一些neuron的output总是0,或者一些weight很接近0,对output无影响

  • 剪掉的weight、neuron是没意义的解空间,不影响最优解(和最优解的距离不变)。

  • neuron理解为上一层经过某些连接的输出;weight是连接的值,就是神经元之间连接上的权重。

剪枝流程

  1. 有一个训好的大network
  2. 评估neuron或weight的重要性(直接看weight的数值,接近0不重要,很正或很负重要;neuron的output总是0不重要)
  3. 把pruned后的network再去训练集finetue一下(recover)(因为pruned会使得模型精度下降,要finetune补回来、恢复回来)

迭代地进行,一次pruned一点点参数,再finetune,再pruned,再finetune,直到模型参数符合要求(因为一次pruned太多,recover不回来)。

image-20230419110903497

P44 Network Compression (2_6)12:44

Why Pruning?

为什么不直接train一个小network:因为小network比较难train,有文章理论上证明只要network够大,能找到global optimize全局最优。

Lottery Ticket Hypothesis 大乐透假设:

不同随机初始化有时候train得起来,有时候train不起来。一个巨大的network想象成由很多小的network所组成,每一个是sub network,每一个小network就是一种可能的初始化,这些小network有的train得起来,有的train不起来,而大的network之所以能够train得起来,是因为大的network里面只要有某一个小的network能够train起来,整个network就train起来,然后把大network做pruned,取出小network。

这解释了下图右下,取大network的初始化一样的参数的小network初始化能够train起来。

image-20230419110936001

不需要大乐透假说?直接train能train起来:

image-20230419110949757

Weight pruning

直接把pruned的weight挖空,不利于gpu加速计算(gpu对象是矩阵),所以做法是把要pruned的weight置0。但是补0后的network模型大小没有变化。

image-20230419111007726

pruning得即使很多(95%都pruned掉了),精度也没怎么掉,但是加速变慢了(小于1)有些pruning了结果还更慢了。

image-20230419111034391

Neuron pruning

相比于weight pruning,neuron pruning是一种更好的方式,把neuron前面和后面连接的weight拿掉,直接拿掉某一个hidden neuron。

image-20230419111054816

Knowledge Distillation

P45 Network Compression (3_6)08:33

Knowledge Distillation:https://arxiv.org/pdf/1503.02531.pdf

Do Deep Nets Really Need to be Deep?https://arxiv.org/pdf/1312.6184.pdf

能学会1长得和7很像,1也长得像9

论文里做了一个有趣的实验:训练集里没给student看过7的数据,但是蒸馏后,student也可能能分类出7,因为student知道7和1、7和9挺像。

image-20230419111117580

打比赛通常是ensemble很多,用集成方法组合多个模型。

知识蒸馏的teacher model把ensemble的模型并起来,比如输出是多个模型的平均,这个输出让student model去学习,最后student就能学到接近ensemble的结果。

image-20230419111135634

temperature

通常 $T>1$ ,提出temperature的目的就是不希望因为teacher model输出概率很“确定”,比如接近1或0,这样就很像label,这样和直接让student学习数据,学习label(0、1) 没区别,就失去了用teacher model的意义,于是用一个temperature缓解一下。

image-20230419111153649

李宏毅实践发现Knowledge Distillation没有特别有用。

Parameter Quantization

P46 Network Compression (4_6)06:37

  1. Using less bits to represent a value
  2. Weight clustering
image-20230419111215941

聚类,比如聚成4类,就用2个bit就能表示4个类,然后每个类的值(table)用所属类的值的平均值表示。

这样可能不够精准

image-20230419111236504
  1. Represent frequent clusters by less bits, represent rare clusters by more bits
    • e.g. Huffman encoding 哈夫曼编码,把比较常出现的token用较少的bit表示,比较少出现的token用较多的bit表示

Binary Weights

Binary Connect: https://arxiv.org/abs/1511.00363

Binary Network: https://arxiv.org/abs/1602.02830

XNOR-net: https://arxiv.org/abs/1603.05279

Your weights are always +1 or -1

  • Binary Connect

流程:随机初始化参数,然后找到参数最接近的二值化参数,计算该二值化参数的梯度,认为是原参数的梯度(非二值化),然后用这个梯度作为原参数的更新方向,更新后的参数值,再去找最接近的二值化参数,再去计算该二值化参数的梯度,再用这个梯度更新real value 参数。直到迭代完了,最后这个最接近real value的二值化参数,作为最终的参数使用。

image-20230419111323712

binary connect 结果

https://arxiv.org/abs/1511.00363

论文发现用binary connect结果居然还变好了,一开始认为参数二值化可能会更差,没想到更好,分析是binary connect有点像正则,起到正则作用,二值化。

image-20230419111341304

Architecture Design

P47 Network Compression (5_6)11:53

应该是实践中最有效的做法

Low rank approximation

fully connect:

中间插入一层(没有激活函数,纯linear),是做SVD奇异值分解。

参数大小来说 $W>U+V$ ,因此减少了参数量;

但是 $W$ 能做到 $UV$ 所做不到的事(解空间),因为 $K\ge rank(UV)$ 也就是 $U*V$的秩小于等于K,但 W没有限制。

image-20230419111357322

Review: Standard CNN

feature的channel有几个,filter的channel就要有几个,然后根据filter的数量,得到output的数量

image-20230419111414978

Depthwise Separable Convolution

1. Depthwise Convolution

每个filter负责一个channel的input(之前每个filter负责所有channel的input,所以每个filter是三维的(有channel通道))现在没有channel通道了,二维的。

image-20230419111437116
  • Filter number = Input channel number
  • Each filter only considers one channel.
  • The filters are $k\times k$ matrices
  • There is no interaction between channels
image-20230419110529312

2. Pointwise Convolution

前一个步骤(Depthwise Convolution)得到的feature map,用1 * 1 filter去扫,卷积核是1 * 1,channel和feature map的channel数量一样。

image-20230419110507038

总共用了18+8=26个参数。

P48 Network Compression (6_6)13:09

  • 普通卷积:比如要得到(右上图形)橙色的左上角的值,是由(左上图形)左上18个值和filter做dot product再求和得到的。

  • ds卷积:(左下图形)feature map 被第二层filler作用时,feature map的参数是“共用的”,既给橙色filler用、又给黄色filler用。因此参数量少了。

    不同filler间,共用同样的参数。

image-20230421133120061

参数计算:

  • 普通cnn:有几个output channel,就有几个filler

一般O是512、128等,1/O可忽略,因此可以缩小到1/K^2,比如1/9。

image-20230421133140058

待看的论文:

Dynamic Computation

要想在设备上用,但是每个设备的资源不一样,要怎么样在不同设备上都能用一个好的模型呢

https://arxiv.org/abs/1703.09844

  1. Train multiple classifiers 训练一批网络模型,根据设备资源的不同,选择其中某个模型。
  2. Classifiers at the intermedia layer 取模型的不同中间层输出,看输出的分类器是否满足效果需求,看中间层就输出是否满足设备资源的需求。(虽然比如模型是20层,这样功耗比较高,但如果不拿完,就是比如只做前面15层,拿15层的输出做分类,可能功耗没那么高,并且效果也还行)

左下图的意思是,拿初始几层(接近input特征)的输出做分类的结果,不太好,越往后面层拿,效果会越好。因为初始几层input,CNN抽出来的pattern比较简单。

右下图的意思是:本来的模型是只有最后一层有分类器,现在中间好多层都接了分类器,这样多个分类器训练出来的模型效果是不好的。尤其是初始几层就接分类器,会更影响模型效果。(后面几层接分类器,不是很影响效果),这是因为中间层接分类器,会影响到原来整个模型的布局,比如一开始模型就是希望初始几层是抽取初级特征,现在初始几层就接分类器了,相当于让初级特征强行学习高级特征,就会破坏原来布局。

image-20230421141557284

https://arxiv.org/abs/1703.09844

MSD net

image-20230421141611270