Lecture 13:Compression:神经网络压缩

Lectured by HUNG-YI LEE (李宏毅)

Recorded by Yusheng zhao(yszhao0717@gmail.com


Lecture 13:Compression:神经网络压缩Network Pruning:网络剪枝Network Pruning的流程Practical Issue:用参数(weight)或神经元(neuron)当作剪枝单位的差别Weight pruningNeuron pruningWhy Pruning ?Knowledge Distillation:知识蒸馏Parameter Quantization:量化参数Binary WeightsArchitecture Design:网络的架构设计Depthwise Separable Convolution操作同一般的卷积层比较参数量原理Low rank approximation——来减少一层network的参数量Depthwise Separable Convolution的原理More Architecture DesignDynamic Computation:动态计算Dynamic DepthDynamic WidthComputation based on Sample Difficulty:让network根据情境自行决定自身的深度或宽度Concluding Remarks


我们见过像BERT、GPT-3这样的庞大的模型,那我们能不能简化这些模型,让他们有较少的参数但是跟原来的模型效能差不多。——Network Compression

应用场景:将ML模型应用在资源比较有限的情况下譬如物联网设备或是小型电器上(例如智能手表、无人机等等),这就要求ML model不能太大,因此模型压缩对算法在工业应用落地有其必要性。

这类应用场景往往需要低延迟(low latency)、以及隐私(privacy)保护的需求。

因此无法应用云计算(输入通过无线网络传入云端,在云端计算,输出传回来)——其一原因是云计算带来信息传递的延迟(Latency),一些小型物联网设备应用场景需要尽量快速的实时反应。

尽管5G时代或许会解决信息传递的延迟,但是将用户隐私数据储存在云端进行运算建模,也有着对隐私侵犯的隐患。

针对隐私在云端的保护,涉及到云端上建模使用联邦学习、或在隐私数据上进行同态加密。此处不是本lecture讨论重点。

因此,Network Compression有其应用价值和潜力。

以下介绍五种神经网络压缩的技术(全是软件层面),本lecture不考虑硬件层面的运算加速或压缩方案

Network Pruning:网络剪枝

所谓树大必有末枝,多数的大型神经网络通常都是over-parameterized,这些没有用的“摸鱼参数”(redundant weights or neurons)可以被剪掉,而不影响模型整体的性能。

90年代,Yann LeCun发表的一篇”Optimal Brain Damage“探索了如何optimize脑的神经元而使脑的损伤最少,和Network Pruning有异曲同工之妙。

Network Pruning的流程

image-20220417203928547

Practical Issue:用参数(weight)或神经元(neuron)当作剪枝单位的差别

Weight pruning

当我们去掉某一个/些不重要的参数后,模型形状会变得不规则(如下图右)

image-20220417204518112

形状“不规则”的模型是不好实做的(coding很不方便…)而且不利于用GPU做加速运算。如果非要做,只能把去掉的weight补为0,这又违反了我们做剪枝的初衷,存储中依然存在weight(即便是0),模型根本没有变小…remark:hard to implement and speedup

来自https://arxiv.org/pdf/1608.03665.pdf的实验;验证了即便剪枝掉九成多的weight,但是speedup的效果依然很差。

image-20220417205308171

如果自己写个库用于weight pruning的实现和加速……

Neuron pruning

当我们去掉某一个/些不重要的神经元后,模型形状依然保持规则(regular),如下图右

image-20220417205529325

这时候用Pytorch比较方便实现,改改输入输出的dimension就行;也比较利于GPU加速。Easy to implement and speedup !

Why Pruning ?

:为什么不直接train一个小的network?

:大的network比较好train(实践验证,众所周知);然后再把大模型磨小。如果直接train小的network难以达到大模型再pruning后得到的小模型的性能

image-20220417223019923

两个数据集,四个模型,分别设unpruned和pruned,做一下fine-tuned,得到指标。针对pruned model:👇

第一次实验是scratch-E(对于小模型初始参数是真的随机初始化,彼时乐透假说中小模型重新train前初始化参数来源于pruned前的大模型),发现指标确实略逊一些

第二次实验在第一次实验的基础,pruned model训练时的epoch多加几个,结果就比fine-tuned好。这篇文章和乐透假说的想法是相反的,里面也提出了乐透假说的可能隐含的成立条件:当learning rate设的较小、还有unstructured(以weight作为单位来pruning)的时候好像才会发现乐透假说的现象。

乐透假说是真是假,需要更多的研究来证实。

Knowledge Distillation:知识蒸馏

知识蒸馏的思想和pruning有一些类似的地方

参考文献:Knowledge DistillationDo Deep Nets Really Need to be Deep?提出了知识蒸馏或类似的想法

我们先train一个大的network:称之为Teacher Net(Large);我们最终要得到的小的network称之为Student Net

和pruning不一样的地方是,pruning中小网络是大网络(修建后)的衍生品;而knowledge distillation中Student net是去根据teacher net来学习。

image-20220418105303936

teacher net按照一般神经网络来训练(如图以mnist做手写数字分类器);而student net以老师的embedding(上图中是[0, 0.7,..., 0.2, 0, 0.1],十维的)作为学习目标而非分类正确率;学生的目标就是尽量逼近老师的输出(就算老师是错的也直接学),optimization的方法为cross-entropy minimization。

目前来看知识蒸馏的好处:对于student net来说,teacher net不仅尽量提供了正确的分类答案,而且还提供了额外的信息(相比直接告诉网络正确分类的标记):如上图,“1”、“7”和“9”长的有点像。

在这种情况下,光是凭着teacher net的教学哪些数字有怎样的关系,student net可能甚至可以在测试中识别出训练集中缺乏的数字。

Parameter Quantization:量化参数

Binary Weights

比较极端的情况:只用一个bit来存储参数。你的参数要不是+1要不就是-1。

参考文献:Binary ConnectBinary NetworkXNOR-net

以binary connect为例:

image-20220418125640627

结果也不错:

image-20220418125735667

第一行是一般的网络,第二三行用binary connect结果更好了。binary network对网络做了一些更多的限制,从而很好的减弱了过拟合。

 

Architecture Design:网络的架构设计

Review:standard CNN

每个layer的input都是一个feature map(以下图为例:有2个channel)。输入feature map的channel的数量等于filter(立方体形状)的高度。用这个filter扫过feature map会得到一个输出feature map,有几个filter那么output的feture map就有几个channel。(总共参数量是72个)

image-20220418131048612

Depthwise Separable Convolution

操作

以上两步骤: 步骤一考虑到channel内的关系;步骤二考虑到channel间的关系。分别需要个参数以及个参数,总共需要26个参数(相比一般的卷积层少了很多)。

同一般的卷积层比较参数量

输入feature map的channel数量

输出feature map的channel数量

filter尺寸

image-20220418174932251

简单计算

原理
Low rank approximation——来减少一层network的参数量

在Depthwise Convolution和Pointwise Convolution出现之前减少network参数的方法。

image-20220418175515420

解释上图:对于原来的一层网络,分别有N个神经元,有M个神经元,那么总共参数量为;Low rank approximation方法设计一个k个神经元的linear层放在网络之间(拆成两层),此时参数量为

如果,那么 ,参数量大大减少了。局限性在于对于原网络有一定限制,的秩要小于,这时才能拆成两个网络(矩阵)。

Depthwise Separable Convolution的原理

image-20220418180804723

原来的卷积层,18个数值直接经过卷积层得到一个数值(结果);而Depthwise Convolution则是把这个过程拆成两个阶段,或者说把一个网络拆成两个网络。

More Architecture Design

Dynamic Computation:动态计算

相比前面四个技术不同的目标:希望network自由地调整它的运算量

有时候,同样的模型可能会跑在不同的devices上面,device之间有着尺寸和运算资源上的差异;对于同一个device,也需要根据设备状态来调整运算量的大小(譬如手机电量)。所以我们需要network可以做到适应设备情况来自动调整运算量。

image-20220418191759773

如果我们通过训练一大堆的network,或许能解决运算资源适应的问题,但是其会占用大量的存储空间。

Dynamic Depth

一个可能的方向是,通过让network自由的调整它的深度,从而让其调整运算资源的需求。

以做图像分类为例:训练一个很深的network

image-20220418192221629

在layer和layer之间再加上一个extra layer,其作用:根据前一个隐藏层(hidden layer)的输出来决定现在分类的结果应该是怎样的。

当运算资源非常充足的时候,可以跑通整个network,得到最终的分类结果;而如果运算资源比较局限,那么决定再network的哪一个extra layer自行输出,作为结果。

训练的过程:让ground truth()跟每一层extra layer以及最后的output的距离统统加起来,得到loss的计算公式:,然后minimize这个loss函数。目前来看,这并不是最好的方法。目前比较优异的训练方法参考Multi-Scale Dense Network (MSDNet)

Dynamic Width

让network自由决定它的宽度

同一张图片丢进不同宽度的network,每一个network会有不同的输出,目标是所有的输出都和ground truth越接近越好。loss函数:

image-20220418193357209

以上图:同一个network但是宽度不同(neuron的使用率100%、75%、50%)。

以上至少简略的想法,实践这样简单的做法是有问题的。关于dynamic width可以参考Slimmable Neural Networks

Computation based on Sample Difficulty:让network根据情境自行决定自身的深度或宽度

不同图像存在不同的识别难度👇

image-20220418193844859

简单的图片,第一层就停下来;困难的图片可能需要跑好多层。

这个问题相关的文章:

Concluding Remarks

前四个技术不是互斥的,可以在network中一起被使用。