本文於2017-3-12日首發於公眾號《有三AI》,很多技術已經更新了,請大家及時關注

如果從2006年算,深度學習從產生到火爆已經

十年了

,在工業界已經產生了很多落地的應用。現在網路的深度已經可達1000層以上,下面我們關注一個問題:

這些年大家是

怎麼“壓榨”CNN模型的。

【技術綜述】為了壓縮CNN模型,這幾年大家都幹了什麼

首先回顧一下幾個經典模型,我們主要看看

深度和caffe模型大小。

#FormatImgID_3##FormatImgID_4#

當然,在實際應用中,各自調試出的version會有出入,網路的大小也不止和深度有關係,此處想說明的問題是:好像

模型大小(引數量)和模型的深淺並非是正相關。

【技術綜述】為了壓縮CNN模型,這幾年大家都幹了什麼

下面言歸正傳,這裡要講的壓榨主要是將模型變小,以便在ARM,FPGA,ASIC等儲存空間有限的平臺應用。

從2個方面進行回顧。第一條是

經典模型的設計路線

,可以看得出本身就在不斷壓縮模型。第二條是在

網路結構基本不變

的情況下,對

模型引數的壓縮

1.經典模型進階路

Fully connect to local connect

這裡我們仍然放這張經典的比較圖,從最早的

全連線神經網路到卷積神經網路

本身就是一場大的引數壓縮革命。

按照全連線神經網路的思想,1000×1000的影象,如果隱藏層也是同樣大小(1000*1000個)的神經元,那麼由於神經元和影象每一個畫素連線,則會有引數1000×1000×1000×1000。光是一層網路,就已經有10^12個引數。

而如果採用卷積神經網路,則由於

權值共享

,對於同樣多的隱藏層,假如每個神經元只和輸入10×10的區域性patch相連線,且卷積核移動步長為10,則引數為:1000×1000×100,降低了4個數量級。

至於為什麼可以這麼做,讀者可以自己去關注卷積神經網路的由來,主要原理在於

影象的區域性patch可以與全圖有類似的統計特性

這第一招,也是最厲害的一招,一舉將神經網路的引數減小許多個數量級,才能有深度學習的發展。

#FormatImgID_7##FormatImgID_8#

NIN 1×1卷積使用

Alexnet[1]是一個8層的卷積神經網路,有約60M個引數,如果採用32bit float存下來有200M。值得一提的是,AlexNet中仍然有3個全連線層,其引數量佔比引數總量超過了90%。

NIN[2]是一個4層的網路結構,其直接對標物件就是AlexNet,那麼為什麼模型大小隻有前者的1/10呢?

除了去掉了全連線層外(

這也是模型變小的關鍵

),提出了

1×1的卷積核

,後來被廣泛用於GoogLeNet[3]和ResNet[4]。

【技術綜述】為了壓縮CNN模型,這幾年大家都幹了什麼

下面舉一個例子,假如輸入為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]中都大量得到應用,有減少模型引數的作用。

卷積拆分

(1) 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,降低一倍的引數量,也是很可觀的。

(2) 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模型,這幾年大家都幹了什麼

後來的Resnet就不說了,也是上面這些trick。到現在,

基本上網路中都是3×3卷積和1×1卷積

,5×5很少見,7×7幾乎不可見。

(3) SqueezeNet[7]

squeezenet將上面1×1降維的思想進一步拓展。透過減少3×3的filter數量,將其一部分替換為1×1來實現壓縮。

具體的一個子結構如下:

一個squeeze模組加上一個expand模組

,使squeeze中的通道數量,少於expand通道數量就行。

【技術綜述】為了壓縮CNN模型,這幾年大家都幹了什麼

舉上面那個例子,假如輸入為M維,如果直接接3×3卷積,輸出為8個通道,則引數量:M×3×3×8。

如果按上圖的做法,則引數量為M×1×1×3+3×4×1×1+3×4×3×3,壓縮比為:(40+M)/24M, 當M比較大時,約0。04。

文章最終將

AlexNet壓縮到原來1/50

,而效能幾乎不變。

據我所知的在卷積結構上做文章的,基本上都在這裡,當然怎麼訓練出本來就小的模型不算。

2.模型引數壓縮方法

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],但是效果顯然是不如下面的結果的。

(1) DeepCompresion

這是2016 ICLR最佳論文。文章早期的工作,是Network Pruning,就是去除網路中權重低於一定閾值的引數後,重新finetune一個稀疏網路。在這篇文章中,則進一步添加了量化和編碼,思路很清晰簡單如下。

(1) 網路剪枝:移除不重要的連線;

(2) 權重量化與共享:讓許多連線共享同一權重,使原始儲存整個網路權重變為只需要儲存碼本(有效的權重)和索引;

(3) 霍夫曼編碼:更高效利用了權重的有偏分佈;

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

(1) 普通網路訓練;

(2) 刪除權重小於一定閾值的連線得到稀疏網路;

(3) 對稀疏網路再訓練;

霍夫曼編碼是一種成熟的編碼技巧與cnn無關。下面只說說第二部分,這是從文章摘取的圖,對於一個4×4的權值矩陣,量化權重為4階(-1。0,0,1。5,2。0)。

【技術綜述】為了壓縮CNN模型,這幾年大家都幹了什麼

那麼索引表就是:

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模型,這幾年大家都幹了什麼

文中還比較瞭如果只用剪枝或者只用量化對結果的影響,表明各自都對壓縮比低於一定閾值時很敏感,如下。而

combine兩個trick,則在壓縮比達到5%時,仍然效能不降

。當然了還有如

卷積層對壓縮比比全連線層更敏感

等結論,感興趣可以自己去讀。

【技術綜述】為了壓縮CNN模型,這幾年大家都幹了什麼

(2) 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模型,這幾年大家都幹了什麼

類似的還有什麼

XORnet,YodaNet

,感興趣的可以去選讀。

就這麼多,本文主要關注的是

模型壓縮

,這跟

計算量壓縮

不等價,

跟加速

也不等價,希望不要搞混淆。

如有疏漏,錯誤,請批評指正,謝謝!

【技術綜述】為了壓縮CNN模型,這幾年大家都幹了什麼

時隔一年,以mobilenet為代表的很多技術已經更新了,我會找時間再來補上,等不及的大家自己去學習吧。

【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。