這一段時間擼了幾篇論文,當我擼到GoogLeNet系列論文的時候,真是腦洞大開!GoogLeNet絕對可以稱為已公開神經網絡的複雜度之王!每當我看到它那錯綜複雜的網絡圖時,心裡總有一種說不出的苦澀滋味,我也不知為何。
然後,我萌生了一個想法,用自己的語言描述一下GoogLeNet的發展歷程和關鍵技術點,我知道網上已經有很多人總結過GoogLeNet的各種版本,但那畢竟是別人的東西,自己總結一遍會提升自己的水平。計劃是寫4篇文章,希望能在一個月內完成吧。下面是GoogLeNet的4篇論文:
[v1] Going Deeper with Convolutions,ensemble top5 error 6.67%,2014
[v2] Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift,ensemble top5 error 4.8%,2015
[v3] Rethinking the Inception Architecture for Computer Vision,ensemble top5 error 3.5%,2015
[v4] Inception-v4, Inception-ResNet and the Impact of Residual Connections on Learning,ensemble top5 error 3.08%,2016
v4版本top5錯誤率只有3.08%!這個應該是目前錯誤率最低的吧。
不過有時候自己也會萌生一些悲觀想法,現在深度學習的網絡是越做越複雜,針對某些數據集的識別率是越來越高,可是,然並卵,當我們換個數據集,換個環境,換個照片,換個……以後,效果就不行了,這真是個問題啊!
本文介紹關於GoogLeNet第一篇正式論文,習慣稱為inception v1,如下:
[v1] Going Deeper with Convolutions,top5 error 6.67%
在開始介紹論文之前,先說一些題外話,GoogLeNet這個名字的誕生由兩方面促成,一是設計者在Google工作,二是向LeNet致敬。GoogLeNet只是一個名字,它的核心內容是發明了Inception Architecture(以下簡稱IA),發明IA的靈感來自於2013年的一篇論文《Provable Bounds for Learning Some Deep Representations》,這篇論文讀起來非常困難,需要很多的數學知識,有興趣的可以看看。
1、提出inception architecture並對其優化
2、取消全連層
3、運用auxiliary classifiers加速網絡converge
接下來對以上幾點分別介紹。
首先得說一下Szegedy發明IA的動機,他估計是在某天閱讀了Provable Bounds for Learning Some Deep Representations這篇論文,又結合自己多年來在深度學習界摸爬滾打的經驗,發現傳統的提高網絡精度的方法是一條邪路(P.S. 傳統的方法指的是 擴大網絡規模 或 增大訓練數據集),而想從本質上提高網絡性能,就得用sparsely connected architectures,即「稀疏連接結構」。
我自己對「稀疏連接結構」的理解是這樣的,用儘可能的「小」、「分散」的可堆疊的網絡結構,去學習複雜的分類任務,怎麼體現「小」、「分散」呢?如下圖:
Inception Architecture,naive version
原來造神經網絡,都是一條線下來,我們可以回想一下AlexNet、VGG等著名網絡,而IA是「分叉-匯聚」型網絡,也就是說在一層網絡中存在多個不同尺度的kernels,卷積完畢後再匯聚,為了更好理解,「匯聚」的tensorflow代碼寫出來是這樣的:
net = tf.concat(3, [branch1x1, branch5x5, branch3x3, branch_pool])
就是簡單的在kernel維度把矩陣concatenate起來。但是這麼做有一個問題,會產生「維度爆炸」,什麼意思呢?假如branch1x1、branch3x3、branch5x5都有256個kernels,加上branch_pool的kernels(假定為256),經過tf.concat操作,最終的kernels是256×4=1024個kernels!這沒法接受啊!如果多層IA疊加起來,那kernels的數量豈不上天!!於是Szegedy就改進了一下,如下圖:
Inception module with dimension reductions
他加入了kernels數量控制方式,就是那些1×1的卷積層,這些1×1的卷積層輸出kernels會比上一層要少,這樣即便在經過tf.concat以後,總kernels數量不會增加太多。另外,這些1×1的卷積層還增加了網絡的非線性程度。
關於IA的結構就介紹完了,可是,為什麼?這樣的結構有啥用?Szegedy在論文裡解釋過一點點:IA之所以能提高網絡精度,可能就是歸功於它擁有多個不同尺度的kernels,每一個尺度的kernel會學習不同的特徵,把這些不同kernels學習到的特徵匯聚給下一層,能夠更好的實現全方位的深度學習!
為什麼VGG網絡的參數那麼多?就是因為它在最後有兩個4096的全連層!Szegedy吸取了教訓,為了壓縮GoogLeNet的網絡參數,他把全連層取消了!其實我個人也認為全連層作用確實沒那麼大,取消了也好,GoogLeNet網絡詳細配置如下:
GoogLeNet詳細配置
從上圖就可以看出,網絡的最後幾層是avg pool、dropout、linear和softmax,沒有看到fully connect的影子。現在取消全連層貌似是個大趨勢,近兩年的優秀大型神經網絡都沒有全連層,可能是全連層參數太多,網絡深度增加了以後,難以接受吧。
搞機器學習的都知道,梯度消散是所有深層網絡的通病,往往訓練到最後,網絡最開始的幾層就「訓不動了」!於是Szegedy加入了auxiliary classifiers(簡稱AC),用於輔助訓練,加速網絡converge,如下圖畫紅框部分:
GoogLeNet
以上圖片摘自此文,因為網絡太深了,豎著太長,就把它橫過來看了。可以看到,筆者在網絡中間層加入了兩個AC,這兩個AC在訓練的時候也跟著學習,同時把自己學習到的梯度反饋給網絡,算上網絡最後一層的梯度反饋,GoogLeNet一共有3個「梯度提供商」,先不說這麼做有沒有問題,它確實提高了網絡收斂的速度,因為梯度大了嘛。另外,GoogLeNet在做inference的時候AC是要被摘掉的。
AC這種加速收斂訓練方式與ResNet表面上看不太一樣,但是我感覺本質上應該是類似的。ResNet也很深,但是它先是通過構建淺層網絡學習參數,再把淺層網絡的參數應用到較深網絡中,從而儘可能減少梯度消散的影響。GoogLeNet是直接把淺層網絡的訓練和深層網絡的訓練揉到一起了。關於這個問題還有待深究。
原文連結:https://www.jianshu.com/p/33197e469414
https://www.jianshu.com/p/a2ad00eddbd5
查閱更為簡潔方便的分類文章以及最新的課程、產品信息,請移步至全新呈現的「LeadAI學院官網」:
www.leadai.org
請關注人工智慧LeadAI公眾號,查看更多專業文章
大家都在看