如果从2006年算,深度学习从产生到火爆已经十年了,在工业界已经产生了很多落地的应用。现在网络的深度已经可达1000层以上,下面我们关注一个问题:

    这些年大家是怎么“压榨”CNN模型的。

为了压榨CNN模型,这几年大家都干了什么_全连接

    首先回顾一下几个经典模型,我们主要看看深度和caffe模型大小。

为了压榨CNN模型,这几年大家都干了什么_权重_02

    当然,在实际应用中,各自调试出的version会有出入,网络的大小也不止和深度有关系,此处想说明的问题是:好像模型大小(参数量)和模型的深浅并非是正相关。

为了压榨CNN模型,这几年大家都干了什么_卷积_03

下面言归正传

这里要讲的压榨主要是将模型变小,以便在ARM,FPGA,ASIC等存储空间有限的平台应用。

 

从2个方面进行回顾。第一条是经典模型的设计路线,可以看得出本身就在不断压缩模型。第二条是在网络结构基本不变的情况下,对模型参数的压缩。

1 经典模型进阶路

1 全连接网络到卷积神经网络

Fully connect to local connect

    这里我们仍然放这张经典的比较图,从最早的全连接神经网络到卷积神经网络本身就是一场大的参数压缩革命。

    按照全连接神经网络的思想,1000×1000的图像,如果隐藏层也是同样大小(1000*1000个)的神经元,那么由于神经元和图像每一个像素连接,则会有参数1000×1000×1000×1000。光是一层网络,就已经有10^12个参数。

    而如果采用卷积神经网络,则由于权值共享,对于同样多的隐藏层,假如每个神经元只和输入10×10的局部patch相连接,则参数为:1000×1000×100,降低了4个数量级。

    至于为什么可以这么做,读者可以自己去关注卷积神经网络的由来,主要原理在于图像的局部patch可以与全图有类似的统计特性

    这第一招,也是最厉害的一招,一举将神经网络的参数减小许多个数量级,才能有深度学习的发展。

为了压榨CNN模型,这几年大家都干了什么_权重_04

2 1×1卷积使用

NIN

    Alexnet[1]是一个8层的卷积神经网络,有约60M个参数,如果采用32bit float存下来有200M。值得一提的是,AlexNet中仍然有3个全连接层,其参数量占比参数总量超过了90%。

    NIN[2]是一个4层的网络结构,其直接对标对象就是AlexNet,那么为什么模型大小只有前者的1/10呢?

    除了去掉了全连接层外(这也是模型变小的关键),提出了1×1的卷积核,后来被广泛用于GoogLeNet[3]和ResNet[4]。

为了压榨CNN模型,这几年大家都干了什么_权重_05

    下面举一个例子,假如输入为28×28×192,输出feature map通道数为128。那么,直接接3×3卷积,参数量为3×3×192×128=221184。

    如果先用1×1卷积进行降维到96个通道,然后再用3×3升维到128,则参数量为:1×1×192×96+3×3×96×128=129024,参数量减少一半。虽然参数量减少不是很明显,但是如果1×1输出维度降低到48呢?则参数量又减少一半。对于上千层的大网络来说,效果还是很明显了。

    移动端对模型大小很敏感。下载一个100M的app与50M的app,首先用户心理接受程度就不一样。

    到此你可能有一个疑问?原则上降低通道数是会降低性能的,这里为什么却可以降维呢?

    笔者没有能力去完整回答这个问题,但是我们可以从很多embedding技术,比如PCA等中得到思考,降低一定的维度可以去除冗余数据,损失的精度其实很多情况下都不会对我们解决问题有很大影响。

    当然了该文章最重要的贡献应该是通过这种内嵌的结构,在通道之间组合信息从而增强了网络的非线性表达能力

    一句话:1×1卷积,在 GoogLeNet Inception v1[3]以及后续版本,ResNet[4]中都大量得到应用,有减少模型参数的作用。

3 卷积拆分

VGG

    VGG可以认为是AlexNet的增强版,两倍的深度,两倍的参数量。不过,也提出了一个模型压缩的trick,后来也被广泛借鉴。

    那就是,对于5×5的卷积,使用两个3×3的卷积串联,可以得到同样的感受野,但参数量却有所降低,为3×3×2/(5×5)=0.72,同样的道理3个3×3卷积代替一个7×7,则参数压缩比3×3×3/(7×7)=0.55,降低一倍的参数量,也是很可观的。

GoogLeNet[3]

    GoogleLet Inception v2就借鉴了VGG上面的思想。而到了Inception V3[3]网络,则更进一步,将大卷积分解(Factorization)为小卷积

    比如7×7的卷积,拆分成1×7和7×1的卷积后。参数量压缩比为1×7×2/(7×7)=0.29,比上面拆分成3个3×3的卷积,更加节省参数了。

    问题是这种非对称的拆分,居然比对称地拆分成几个小卷积核改进效果更明显,增加了特征多样性。

只能说

为了压榨CNN模型,这几年大家都干了什么_权重_06

    后来的Resnet就不说了,也是上面这些trick。到现在,基本上网络中都是3×3卷积和1×1卷积,5×5很少见,7×7几乎不可见。

SqueezeNet[7]

    squeezenet将上面1×1降维的思想进一步拓展。通过减少3×3的filter数量,将其一部分替换为1×1来实现压缩。

    具体的一个子结构如下:一个squeeze模块加上一个expand模块,使squeeze中的通道数量,少于expand通道数量就行。

为了压榨CNN模型,这几年大家都干了什么_全连接_07

    举上面那个例子,假如输入为M维,如果直接接3×3卷积,输出为7个通道,则参数量:M×3×3×7。

    如果按上图的做法,则参数量为M×1×1×3+3×4×1×1+3×4×3×3,压缩比为:(40+M)/21M,当M比较大时,约0.05。

    文章最终将AlexNet压缩到原来1/50,而性能几乎不变。

    据我所知的在卷积结构上做文章的,基本上都在这里,当然怎么训练出本来就小的模型不算。

2.1 SVD分解法

    有研究表明,一层的weights,可以通过其子集进行精确预测,所以可以使用奇异值分解(SVD分解)来对每一层进行低秩近似,下面只提一下基本原理和结论。

    原理:对于一个m×k维的实数矩阵W,其可以进行奇异值分解为W=USV,其中U维度为m×m,S维度为m×k,V维度为k×k。S是非负实数对角矩阵,如果将其对角线的值降序排列并发现其值衰减很快,则只需要前面几维就能保持W的绝大多数信息不丢失,这也是PCA的原理。

    假如只保留t维,那么原来的计算复杂度为O(m×k),现在则变成了O(m×t+t×t+t×k),对于足够小的t,O(m×t+t×t+t×k)远小于O(m×k)。

    不过这个方法实际的模型压缩比并不明显,在文章[8]中为2~3的左右,加速比也是2~3左右。所以同类的方法,就不再深究。

2.2 权重参数量化与剪枝

    下面是近两年比较有代表性的研究,主要是通过权重剪枝,量化编码等方法来实现模型压缩。其实最早也有直接对每个权重独立量化的研究[9],但是效果显然是不如下面的结果的。

DeepCompresion

    这是2016 ICLR最佳论文。文章早期的工作,是Network Pruning,就是去除网络中权重低于一定阈值的参数后,重新finetune一个稀疏网络。在这篇文章中,则进一步添加了量化和编码,思路很清晰简单如下。

(1) 网络剪枝:移除不重要的连接;

(2) 权重量化与共享:让许多连接共享同一权重,使原始存储整个网络权重变为只需要存储码本(有效的权重)和索引;

(3) 霍夫曼编码:更高效利用了权重的有偏分布;

    第一部分很好理解,就是如下流程:

(1) 普通网络训练;

(2) 删除权重小于一定阈值的连接得到稀疏网络;

(3) 对稀疏网络再训练;

    霍夫曼编码是一种成熟的编码技巧与cnn无关。下面只说说第二部分,这是从文章摘取的图,对于一个4×4的权值矩阵,量化权重为4阶(-1.0,0,1.5,2.0)。

为了压榨CNN模型,这几年大家都干了什么_卷积神经网络_08

那么索引表就是:

0:-1.0

1:0

2:1.5

3:2.0

对weights采用cluster index进行存储后,原来需要16个32bit float,现在只需要4个32bit float码字,与16个2bit uint索引,参数量为原来的(16×2+4×32)/(16×32)=0.31。

    存储是没问题了,那如何对量化值进行更新呢?事实上,文中仅对码字进行更新。如上图:将索引相同的地方梯度求和乘以学习率,叠加到码字

    这样的效果,就等价于不断求取weights的聚类中心。原来有成千上万个weights,现在经过一个有效的聚类后,每一个weights都用其聚类中心进行替代,作者的研究表明这样并不会降低网络的效果。而聚类的迭代过程,通过BP的反向传播完成,不得不说,想法非常plain和beautiful,难怪能得best paper。

    看下表就知道最终的压缩效率非常可观,把500M的VGG干到了11M。

为了压榨CNN模型,这几年大家都干了什么_权重_09

    文中还比较了如果只用剪枝或者只用量化对结果的影响,表明各自都对压缩比低于一定阈值时很敏感,如下。而combine两个trick,则在压缩比达到5%时,仍然性能不降。当然了还有如卷积层对压缩比比全连接层更敏感等结论,感兴趣可以自己去读。

为了压榨CNN模型,这几年大家都干了什么_权重_10

Binarized Neural Networks

如果说deep compression是float到uint的压缩,那么这篇就是uint到bool的压缩了。前者只是将weights进行量化,而这个,权重只有+1或者-1二值。

    将权重和每层的激活值全部二值化。如此一来大部分数学运算都是位运算。

    二值化的方法也很简单,文章提到了两种,第一种就是符号函数,即x>0,则f(x)=1,x<0,则f(x)=-1。另一种是以一定的概率赋值,是不是想起了dropout?文中就是,只有在激活函数时,才采用第二种二值化方法,其余都采用符号函数。

    其实大问题就是一个,符号函数的导数并不连续,那怎么进行梯度传播?文中将sign(x)进行放松,在-1到1之间采用了线性函数。

f(x) = max(-1,min(1,x))

    主要事项:

    (1) 在训练过程中还是需要保存实数的参数的

    (2)在进行权重参数更新时,裁剪超出[-1,1]的部分,保证权重参数始终是[-1,1]之间的实数。

而在使用参数时,则将参数进行二值化

    最终效果到底如何?在一些比较小的数据集,比如MNIST,CIFAR-10上,精度稍微有所下降但不明显,模型大学降低为原来的1/32,32bit的float变成1 bit。对于时间代价可见下图,第2个直方图是MNIST数据集的结果,作者的优化将速度相对于cublas提升了约3.4倍,而精度不变(第三个直方图)。

为了压榨CNN模型,这几年大家都干了什么_权重_11

    类似的还有什么XORnet,YodaNet,感兴趣的可以去选读。

    就这么多,本文主要关注的是模型压缩,这跟计算量压缩不等价,跟加速也不等价,希望不要搞混淆。

    还是那句话,如有疏漏,错误,请自行消化。因为本公众号暂时没有评论功能,所以需要交流或者有所指教,请直接加微信联系。为了照顾受众,很多细节也没有深究,爱好者可以自行看下面参考文献学习。所有观点整理纯属个人爱好消化,不能保证100%的accuracy和recall。

为了压榨CNN模型,这几年大家都干了什么_全连接_12 为了压榨CNN模型,这几年大家都干了什么_卷积神经网络_13

 

 

为了压榨CNN模型,这几年大家都干了什么_卷积_14

 

【1】Krizhevsky A, Sutskever I, Hinton G E. Imagenet classification with deep convolutional neural networks[C]//Advances in neural information processing systems. 2012: 1097-1105.

【2】Lin M, Chen Q, Yan S. Network in network[J]. arXiv preprint arXiv:1312.4400, 2013.

【3】Szegedy C, Liu W, Jia Y, et al. Going deeper with convolutions[C]//Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition. 2015: 1-9.

【4】He K, Zhang X, Ren S, et al. Deep residual learning for image recognition[C]//Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition. 2016: 770-778.

【5】Simonyan K, Zisserman A. Very deep convolutional networks for large-scale image recognition[J]. arXiv preprint arXiv:1409.1556, 2014.

【6】Szegedy C, Vanhoucke V, Ioffe S, et al. Rethinking the inception architecture for computer vision[C]//Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition. 2016: 2818-2826.

【7】Iandola F N, Han S, Moskewicz M W, et al. SqueezeNet: AlexNet-level accuracy with 50x fewer parameters and< 0.5 MB model size[J]. arXiv preprint arXiv:1602.07360, 2016.

【8】Denton E L, Zaremba W, Bruna J, et al. Exploiting linear structure within convolutional networks for efficient evaluation[C]//Advances in Neural Information Processing Systems. 2014: 1269-1277.

【9】Vanhoucke V, Senior A, Mao M Z. Improving the speed of neural networks on CPUs[C]//Proc. Deep Learning and Unsupervised Feature Learning NIPS Workshop. 2011, 1: 4.

【10】Han S, Mao H, Dally W J. Deep compression: Compressing deep neural networks with pruning, trained quantization and huffman coding[J]. arXiv preprint arXiv:1510.00149, 2015.

【11】Hubara I, Courbariaux M, Soudry D, et al. Binarized neural networks[C]//Advances in Neural Information Processing Systems. 2016: 4107-4115.