卷积神经网络的压缩和加速

本文介绍了卷积神经网络的压缩和加速方法,包括网络剪枝、低秩估计、模型量化和模型蒸馏。网络剪枝通过删除不重要的参数,低秩估计通过矩阵分解减少计算量,模型量化通过将参数转换为低精度整数实现压缩,模型蒸馏则通过训练小型网络学习大型网络的知识。这些方法旨在应对存储和计算资源的限制,提高模型效率。
摘要由CSDN通过智能技术生成
原创声明:本文为 SIGAI 原创文章,仅供个人学习使用,未经允许,不能用于商业目的。

其它机器学习、深度学习算法的全面系统讲解可以阅读《机器学习-原理、算法与应用》,清华大学出版社,雷明著,由SIGAI公众号作者倾力打造。

  •  
 

相关背景

为什么要对网络进行压缩和加速呢?最实际的原因在于当前存储条件和硬件的计算速度无法满足复杂网络的需求,当然也许十几年或更远的将来,这些都将不是问题,那么神经网络的压缩和加速是否仍有研究的必要呢?答案是肯定的,我认为对网络压缩和加速的最根本原因在于对高效率模型的追求,当前很多复杂网络中的很多参数是冗余的,对实际模型结果没什么贡献,我们怎么能容忍这些无意义的参数竟然和有意义的参数享受相同的“待遇”——相同的存储空间和计算时间。尤其当存储空间和计算时间受限的情况下,我们更加无法容忍那些无意义的参数。当我们可以构造训练出一种模型,其所有的参数都是不可替代的,那么压缩和加速的工作就终于可以走向历史舞台了,但这种情况是不可能发生的,至少在近几十年不可能发生,因为当前神经网络对于研究者来说仍是一个黑箱。

神经网络刚刚被提出来时,对于如何将其应用与图像仍是个很大的问题,最单纯的想法是将图片按像素点排列成向量,再走多层感知机的老路,但由于参数太多,存储不便,计算速度太慢,始终无法得到进一步发展。终于一个神奇而又简单的想法逆转了这个困境——伟大的权值共享,于是卷积神经网络将整个模型的参数减少了若干倍。虽然由于当时硬件条件限制,对卷积神经网络的研究也一度陷入瓶颈,直到2012年AlexNet一鸣惊人。但权值共享应该称得上是神经网络压缩和加速的第一次伟大尝试。卷积神经网络也是权值共享的神经网络的一种。接下来的模型加速和压缩,都是针对卷积神经网络模型的。

针对卷积神经网络模型的压缩,最早提出的方法应该是网络裁枝,LeCun在1989年就提出根据损失函数对各个参数的二阶导,来估计各个参数的重要性,再删去不重要的参数。后来又是到2012年之后,压缩方法更加多样,总体大约分为4种:网络裁枝、模型量化、低秩估计、模型蒸馏。下面我将对4种方法进行逐一介绍。

 

网络剪枝

我们先来看看当前深度学习平台中,卷积层的实现方式,其实当前所有的深度学习平台中,都是以矩阵乘法的方式实现卷积的(如图1左侧):

图1 卷积与矩阵乘法

网络裁枝有两个大问题需要考虑:

第二,若无规律的删掉一些连接,即令一些参数为0,实际上无法压缩,因为在网络存储中,0也是按32位浮点数存储的,与其他参数的存储量相同。所以我们不能仅仅将删掉的参数设为0,而是要彻彻底底地删掉这些矩阵。

最简单的一种想法:直接删掉参数矩阵的某一列,对应的就是删掉一个filter,相应的输出特征图将少一个通道。而在下一个卷积操作时,这个输出特征图将变成输入特征图,带入到图1右侧的输入矩阵,少一个通道即少一个列,那么为了保证矩阵乘法正确,参数矩阵必须要对应删去一行,即所有filter都要删去一个通道,整体变化如图2所示。从上述介绍我们发现:若对某层卷积以filter单位裁枝,那么到下一层一定会有以channel单位的裁枝,这就是filter-level裁枝(图4中所示)

图2 filter-level剪枝[2]

第二个想法:我们若将3*3的kernel删成2*3或更小的kernel,对应到参数矩阵,即删掉了若干行,同样绝对有压缩的效果,而这种裁枝并没有改变channel的个数,虽然输入矩阵的列数需要减少,但这是在im2col操作中进行的(以kernel和stride不同设置,会生成不同的输入矩阵),对输入特征图与输出矩阵没有任何影响。

对第二个想法,我们可以进一步改进:如果将3*3的kernel删成某个固定的形状,例如下图中,那么我们可以修改im2col操作,保证卷积的正确性,这就是Group-level的裁枝(图4中所示)

图3 另类kernel(白色为0值)

第三个想法:如果我们不急着删去参数,而是将那些没用的参数设为0,当整个参数矩阵中有很多的0时,稀疏矩阵闪亮登场,于是矩阵的乘法可以用稀疏矩阵的乘法来代替,从而起到模型压缩和加速的效果。图4中,Fine-grained,vector-level,kernel-level中一些裁剪方法,需要使用到稀疏卷积的方法来实现。

上述是从矩阵方面,对裁枝方法进行了讲解,其实我们忽略了一个重要的问题:究竟什么样的参数需要裁掉呢?一般有两种方法:损失函数对参数的二阶导,和参数的绝对值大小。第一种方法,损失函数对参数的二阶导越小,说明这个参数的更新对损失函数的下降的贡献越小,说明这个参数不重要,可以删去。第二种方法,参数绝对值越小,说明输出特征图与该参数几乎无关,因此可以删去。相比较而言,第一种方法是尽可能保证损失函数不变,对结果影响相对较小,但计算复杂;第二种方法是尽可能保证每层输出特征图不变,而不管损失函数,计算方便,但对结果可能相对较大。但无论哪种方法都需要对裁剪后网络做参数调优。

 

低秩估计

低秩估计的方法其实就是运用了矩阵分解和矩阵乘法的结合律。此时我们仍需要回到图1左侧的示意图:对输入矩阵我们无法做分解,因为不同的前向传递中矩阵是变化的,但是参数矩阵是固定的呀,那么何不分解参数矩阵呢?低秩估计就是这么个想法:

看上面的这个式子是不是感觉特别简单,只要我们可以用若干小矩阵对参数矩阵进行估计,那么输出矩阵就可以通过上面的式子得到。

在当前的很多对低秩估计的研究中,笔者认为奇怪的一点是:对矩阵分解后,将分解后的矩阵乘法又转回成卷积操作,例如上式中将原参数矩阵分解成3个小矩阵,那么在实现中就是用3个卷积来实现分解后的矩阵乘法。笔者认为这种操作实际上是增加了计算量,因为卷积需要经过im2col过程才可以转变成矩阵乘法,所以为什么不直接实现新的层或Op来做3个矩阵乘法呢?那么相对于用卷积实现,其实是少了2个im2col的过程。当然这是笔者的思考,还没有经过实验验证,如果有不同的想法或者实验结果,希望可以拿出来一起分享。

除矩阵分解以外,我们也可以直接对张量进行分解,而且卷积也符合结合律,那么上式中的乘法即变成了卷积,矩阵变成了张量,如下式以tucker分解为例:

同样可以得到更小的参数张量和与原输出相似的输出矩阵。下面我们以Tucker张量分解为例,分析一下低秩估计方法的压缩和加速效果。Tucker分解是对张量直接进行分解,其分解效果如图5所示

图5 Tucker分解

原卷积经过分解成3个计算量更小的卷积,卷积核通道数如图中所示,那么分解前后计算量为

由表所示,若要求加速至少2倍,在卷积核大小为3*3,卷积输出通道数等于输入通道数时,tucker分解的中间卷积通道数最大是原来的0.604倍。当然中间通道数越小,可实现的加速和压缩效果越好;而为了保证准确率,中间通道数越大,分解后的张量还原回原张量的误差越小,这就是速度与准确率之间的权衡,也是

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值