天天看點

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

[VGG-Paper]

[原文位址 - Very deep convolutional networks for large-scale image recognition]

一篇對 VGGNet 了解比較詳細的部落格,很長很詳盡,十分受用.

轉載并非常感謝原部落客 - Yuens’s Blog.

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

這篇文章是以比賽為目的——解決ImageNet中的1000類圖像分類和 localization(這裡需要注意 localization 和 detection 的差別. localization是找到某個物體的檢測框,而detection是找到所有物體的檢測框,後文會詳細說明.)

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

作者對六個網絡的實驗結果在深度對模型影響方面,進行了感性分析(越深越好),實驗結果是16和19層的VGGNet(VGG代表了牛津大學的Oxford Visual Geometry Group,該小組隸屬于1985年成立的Robotics Research Group,該Group研究範圍包括了機器學習到移動機器人)分類和localization的效果好(作者斬獲2014年分類第二,localization第一,分類第一是當年的GoogLeNet.)下面是來自一段對同年的GoogLeNet和VGG的描述:

GoogLeNet和VGG的Classification模型從原理上并沒有與傳統的CNN模型有太大不同。大家所用的Pipeline也都是:訓練時候:各種資料Augmentation(剪裁,不同大小,調亮度,飽和度,對比度,偏色),剪裁送入CNN模型,Softmax,Backprop。測試時候:盡量把測試資料又各種Augmenting(剪裁,不同大小),把測試資料各種Augmenting後在訓練的不同模型上的結果再繼續Averaging出最後的結果.

參考:如何評價今年的 ILSVRC 2014 結果? | 知乎

https://www.zhihu.com/question/24904450/answer/29400634

需要注意的是,在VGGNet的6組實驗中,後面的幾個網絡使用了pre-trained model A的某些層來做參數初始化。這點上雖然作者沒有提該方法帶來的性能增益,但其實是很大的(我會在下文中優秀的特征提取器和泛化能力具體說明.)

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

上圖來自CS231n課程blog的tiny-vggnet模型架構,可以看到有三組卷積後接一個全連接配接層,每組卷積(blog裡稱為pattern)的形式都是一樣的(conv-relu-conv-relu-pool),實際的VGG16(隻算卷積和全連接配接層的個數是16)與上圖略有不同(前兩組conv-relu-conv-relu-pool,中間三組conv-relu-conv-relu-conv-relu-pool,最後三個fc,前兩個fc是fc-relu-dropout,最後一個fc僅有fc。後文ConvNet

Configurations部分我會具體說明),不過整體來說作者也承認是繼承了AlexNet和OverFeat:

  1. 繼承了AlexNet不少網絡結構(基于它加深層數和修改所有卷積核為3×3的小卷積),最後三個fc層基本算是平移AlexNet的到VGGNet上;
  2. 繼承了OverFeat在Localization任務中的做法(we adopt the approach of Sermanet et al. (2014),沒記錯的話OverFeat拿了2013年Localization任務的第一名.)

VGGNet的兩個特點:層數更深更寬、卷積核更小. 因為卷積核變小全部改用3×3大小(性能最好的兩個網絡:實驗D(VGG16)和實驗E(VGG19)),小卷積核的使用帶來參數量減少,可以更加steadily地增加層數得同時不會太過于擔心計算量的暴增.因為這篇文章正文寫的是分類,附錄介紹了VGGNet在localization上的工作,我也會對localization任務的解決進行分析.

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

這篇文章的主要特别的地方是前兩點(換句話說,抄的不是很明顯):

  1. 卷積核變小。作者做的6組實驗中,卷積核全部替換為3×3(極少用了1×1),選用更小卷積核的motivation是作者受到這兩篇文章(Zeiler & Fergus, 2013; Sermanet et al., 2014)啟發,使用更小的卷積核尺寸和stride得到性能提升;
  2. 層數更深更寬(11層、13層、16層、19層)。我認為作者是覺得:既然小卷積核帶來性能提升,那麼不妨試試深度對性能的影響,反正參數量我的gpu可以cover住。作者的實驗也發現層數越深,帶來的分類結果也越好,但并沒有提到channel變寬這一個因素:6組實驗中channel數都是逐層加寬的,如果單說深度對性能的影響而忽略寬度(這裡寬度不是feature map的width而是depth),我覺得并不夠convincing,應該再加入一下對寬度(channel)數分析對比的實驗;
  3. 池化核變小且為偶數。AlexNet中的max-pool全是3×3的,但VGGNet中都是2×2的。作者沒有說明選擇這種size的考量(現在stride=2、以及2×2和3×3的pooling kernel選擇的主流),我認為主要是2×2帶來的資訊損失相比3×3的比較小,相比3×3更容易捕獲細小的特征變化起伏,此外或許是發現2×2的實驗效果确實比3×3的好吧(畢竟這也是直接原因);
  4. 網絡測試階段将訓練階段的三個全連接配接替換為三個卷積。對于訓練和測試一樣的輸入次元下,網絡參數量沒有變化,計算量也沒有變化,思想來自OverFeat,1×1的卷積思想則來自NIN。優點在于全卷積網絡可以接收任意尺度的輸入(這個任意也是有前提的,長和寬都要滿足: a×2n a × 2 n ,n是卷積與池化做stride=2的下采樣的次數);
  5. 刷比賽的小技巧。其實沒什麼意思,比方輸入圖檔的尺寸對于訓練和測試階段的處理方式不同,single和multi-scale的問題(具體見後文)。

下面我将會任務背景開始說明,最後我會再次引用CS231n對于VGG的中肯評價進行總結。

1. 任務背景

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

因為VGGNet在AlexNet之後,有必要先說一下問題的背景:自從AlexNet将深度學習的方法應用到圖像分類取得state of the art的驚人結果後,大家都競相效仿并在此基礎上做了大量嘗試和改進,先從兩個性能提升的例子說起:

  1. 小卷積核。在第一個卷積層用了更小的卷積核和卷積stride(Zeiler & Fergus, 2013; Sermanet et al., 2014);
  2. 多尺度。訓練和測試使用整張圖的不同尺度(Sermanet et al., 2014; Howard, 2014)。

作者雖然說自己是在保證其他一緻,改變深度情況來提升效果的,但實際上也是集大成(抄襲這兩個:用更小卷積核;多尺度訓練和測試)。算是作者整個實驗的motivation吧,既然如此,或許作者想:我再試試深度,如果效果好,就發表出來又水篇文章(畢竟不能沒有自己的工作),哈哈哈!

1.1 優秀的特征提取器和泛化能力

1.1.1 特征提取器

另外,作者發現訓練出的卷積網絡是一個天然的且十分優秀的特征提取器(在不對卷積網絡進行fine-tuning而直接在其後接一個SVM分類器并訓練該SVM,最終結果也很好),而且特征提取器在其他資料集上具有通用性。說到這點不得不提到RCNN這篇文章,因為該作者将CNN作為一個特征提取器,主要流程是前三個步驟(第四個檢測框回歸也隻是在附錄寫到,下圖是我基于作者修改的圖,略有不同):

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition
  1. (Supervised pre-training)用12年的分類資料去pre-train模型,CNN後接1k-way softmax
  2. (Domain-specific fine-tuning)用當年20類檢測資料集生成分類資料(根據檢測資料通過selective search生成小圖,然後計算IOU大于0.5視為該類圖像),去fine-tune模型,CNN後接20-way softmax;
  3. (Object category classifier)CNN參數固定,訓練SVM。輸入SVM的資料是CNN處理後的feature map,如果是20類那麼對應20個,即分類20類的二分類SVM。其中對于某一類的SVM來說,正樣本是proposal和ground-truth的框IOU大于0.3的(交叉驗證得到的),其餘視為負樣本;
  4. (Bounding-box regression)這裡原圖沒有畫出,其實在檢測這裡既有對proposal進行分類,再有對proposal的中心點和寬和高這四個值進行回歸的過程,當然這個regressor的參數是訓練拿到的。

在此過程中,RCNN作者預訓練CNN,之後又用任務資料去fine-tune網絡,最後把CNN作為特征提取器給SVM。同樣展示了CNN的強大特征提取能力。說到這裡不得不提pre-train和fine-tune。

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

VGGNet 6組實驗中的後面幾組中用到了pre-train後的A模型的部分層作為網絡初始化的參數。上圖是AlexNet作者在16年的深度學習暑期學校時候課上的一頁PPT。可以看出三種針對不同資料量級而選擇的訓練政策。之前做過的幾次Kaggle比賽中,使用pre-trained model 和 train-from-scratch 拿到的性能結果差距不小. Alex講到,對于在ImageNet上訓練過的pre-trained model,其參數可以用來初始化别的任務:

  • 資料量小的新任務。可以把前面的大部分層參數freeze,保留前面的卷積層和部分卷積層,以擷取在ImageNet上得到的提取特征的能力,作為特征提取器,而隻訓練最後一層的全連接配接層。
  • 資料量中等的新任務。則需要更多的可變的層來拟合新任務的資料,freeze前面的層,留出更多的層去拟合新資料。

但實際來說,什麼是小和大往往沒有定量的描述,我覺得還是需要根據pretrain模型時的資料和新問題的資料之間的多樣性複雜程度來評估,隻是說,可finetune的層數越多,可以拟合新資料的分布的參數越多,這一個觀點。但若是認真去解決問題且時間充裕,需要把所有可能都嘗試到。

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

“淺層學到的是紋理特征,而深層學到的是語義特征”,這句話是從某篇博文看到的,我認為網絡層數在特征提取這裡,單從可視化的角度來講,如果是線性模型對學出的權重矩陣進行可視化,那麼得到的是對應各類别圖像的輪廓,這是CS231n課程有講到的。然而上圖是對GoogLeNet這一網絡的特征圖可視化的結果,可以看到淺層學到的是邊緣(Edges)、紋理(Texture)等,深層學到的是更偏向語義的資訊,相當于把原本線性模型的feature map拉長了。本質還是那麼多資訊,隻是中間的過程更加清晰可見,看上圖中最後一組6張圖中第一列放大的圖,有建築物的特征,而且顔色偏藍,應該是訓練資料中該類的圖像大多有雲朵和天空作為建築物的背景。

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

不過可以發現,無論網絡深淺,最後一層(或幾層)總是對應類别的輪廓,即語義資訊。

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

根據優化的目标不同,得到的可視化結果不同,如DeepDream就是對feature

map的結果backprop回去更新輸入圖像進行可視化(該過程的流程如下圖,該圖來自zhihu的一篇部落格見參考部分。關于可視化這裡我沒有仔細看,需要結合Feature

Visualization這篇文章、Google Blog上關于DeepDream的兩篇文章以及風格遷移學習那篇文章再深入分析)。

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

1.1.2 在其它資料集上的泛化性

作者通過在ImageNet預訓練得到的模型,在其他小資料(VOC-2007、VOC-2012、Caltech-101、Caltech-256等圖像分類任務)上發現優秀的泛化性能(這部分來自本篇文章附錄 Localization 的 Generation of Very Deep Features),作者說到使用pre-trained模型,再在自己的小資料上訓練不容易過拟合,關于這點我的了解是:

  1. 一開始在量級大且多樣性廣的資料集(如ImageNet)上pre-train,不嚴謹地說,新問題的小資料隻是當初pre-train時所用資料集的一個子集,換句話說,pre-trained模型的參數已經避開了用小資料train-from-scratch的一些局部最優;
  2. 一開始在足夠大的資料上pre-train,模型已經見識過了廣闊的樣本空間,這會帶來了更廣闊和豐富的特征空間,因而模型在小資料上學習時不會太過糾結于比較片面或者偏斜的樣本帶來的影響(還是類似第一點,初始化足夠好)。

總而言之:事半功倍,pre-trained模型用于fine-tune前已經趟(略,或者說exploit)過了很多坑(局部最優),因而效果好。另外,作者還使用不同尺度跑網絡的方式提取到多組特征,對它們做平均的方法來表示最終給分類器的特征,這樣相比将特征直接concate,不會導緻最終特征太多(inflating,或者說是膨脹)。另外,作者發現使用multi-scale訓練模型時,如果尺度範圍比較小(256,384,512,640,768和256,384,512 兩種 multi-scale相比)提升的性能比較有限(0.3%)。

x′i,j=xi,j∑height−1i=0∑width−1j=0x2i,j√ x i , j ′ = x i , j ∑ i = 0 h e i g h t − 1 ∑ j = 0 w i d t h − 1 x i , j 2

作者在使用pre-trained模型的時候,是把用于喂給softmax前、産生1000維的最後一層全連接配接層去掉,使用倒數第二個全連接配接層産生聚合了位置和尺度的4096維圖像特征,将這個特征做L2-normalization(上面公式便是圖像上位于第 i 行 j 列的像素點 xi,j x i , j 經過L2-norm後的像素值 x′i,j x i , j ′ ,需要注意的是這裡是圖像進行中 L2-normalize)後給SVM分類器訓練 1VsALL 模型,提取特征的CNN沒有做fine-tune操作。作者用倒數第二層的4096維的特征的考量是這個次元一定程度聚合了multiple location 和 scale 的資訊,我覺得這個說法還是有些道理,一是網絡有三個全連接配接層,經過1個或者2個全連接配接,原本的帶有位置的局部資訊被聚合起來了,但是 4096 次元的數目這個超參數還可以進一步使用交叉驗證來優化,此外作者使用的是第二個fc後的特征,也不妨試試第一個fc後的特征、或者最後一個卷積的特征、甚至是将這些拼起來,說不定效果會更好。

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

此外,作者在對CNN提取到的特征做了聚合和一些變換,作者對4096維的resulting feature map(也就是剛做過l2-normalize過程的)再做global average pooling 産生一樣次元的輸出,并将與之鏡像的圖檔也做同樣的過程,最後将二者的特征加和求平均。當然全局平均池化(global average pooling,Network In Network有介紹該方法和dropout在作用上都起到正則作用,但有兩個特點:1. 讓feature map與類别通過softmax時的計算更自然,feature map也即對應類别的置信度分數;2. 無參數的政策,避免了過拟合問題。更多的參考上圖NIN的截圖)是一種聚合方法,作者也說到還可以使用stacking到一起,我想應該類似concate。

2. ConvNet Configurations

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

為了友善分析,先把VGGNet16的結構圖放出來,即将說到的内容會跟下面這幅圖有很密切的關系:

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

結合這張圖,我們有網絡D的參數表格(參數來自CS231n的計算,我這裡重新排版):

# LAYER FEATURE MAP MEMORY WEIGHTS
INPUT [224x224x3] 224x224x3=150K
1 CONV3-64 [224x224x64] 224x224x64=3.2M (3x3x3)x64 = 1,7282
2 CONV3-64 [224x224x64] 224x224x64=3.2M (3x3x64)x64 = 36,864
POOL2 [112x112x64] 112x112x64=800K
3 CONV3-128 [112x112x128] 112x112x128=1.6M (3x3x64)x128=73728
4 CONV3-128 [112x112x128] 112x112x128=1.6M (3x3x128)x128=147456
POOL2 [56x56x128] 56x56x128=400K
5 CONV3-256 [56x56x256] 56x56x256=800K (3x3x128)x256=294912
6 CONV3-256 [56x56x256] 56x56x256=800K (3x3x256)x256=589824
7 CONV3-256 [56x56x256] 56x56x256=800K (3x3x256)x256=589824
POOL2 [28x28x256] 28x28x256=200K
8 CONV3-512 [28x28x512] 28x28x512=400K (3x3x256)x512=1179648
9 CONV3-512 [28x28x512] 28x28x512=400K (3x3x512)x512=2359296
10 CONV3-512 [28x28x512] 28x28x512=400K (3x3x512)x512=2359296
POOL2 [14x14x512] 14x14x512=100K
11 CONV3-512 [14x14x512] 14x14x512=100K (3x3x512)x512=2359296
12 CONV3-512 [14x14x512] 14x14x512=100K (3x3x512)x512=2359296
13 CONV3-512 [14x14x512] 14x14x512=100K (3x3x512)x512=2359296
POOL2 [7x7x512] 7x7x512=25K
14 FC [1x1x4096] 4096 7x7x512x4096=102760448
15 FC [1x1x4096] 4096 4096×4096=16777216
16 FC [1x1x1000] 1000 4096×1000=4096000
TOTAL memory 24M * 4 bytes ~= 93MB / image (only forward! ~*2 for bwd)
TOTAL params 138M parameters

網絡的輸入尺寸為224×224的圖像,輸入前需要減去RGB均值(提前跑了一遍train set,resize到224并計算每個位置的強度均值)。下面是作者作的六組實驗,觀察深度、LRN、conv1x1的小卷積這三個因素對結果的影響(另外,也可以看出層數的算法,是隻統計卷積層和全連接配接層)。

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

在具體說明結構之前,先說一下在AlexNet中出現的LRN(Local Response Normalization)層,該層會對相鄰的N個通道在同一 (x,y) 位置處的像素值進行normalize。VGGNet作者發現(實驗A和A-LRN),LRN層對分類準确率不僅沒有提升,還帶來更多的顯存占用和計算時間,是以在之後的四組(B、C、D、E)實驗中均沒有出現LRN層。

觀察上圖6組實驗中可以發現作者在統計層數的時候,不算POOL、LRN、softmax,隻算conv、fc,比方A組中所有的fc層和conv層加起來是11,A組就是11層。我想這是因為:

  1. 參數太少。像relu、pool這樣的層參數量太少,有的甚至如激活層relu不儲存中間結果直接給下一層;
  2. 計算量小。相比conv甚至fc,pool這些層的計算量太少。

此外,所有實驗中的網絡結構除了層數大體相同,均是五組卷積(每一組可能有多個卷積層,A網絡包含8個卷積,E網絡包含16個卷積),再接三個全連接配接層。網絡得到的feature map從64開始随卷積組數的推進逐漸遞增,以2的倍率擴大直到達到512的channel數。因為小卷積核的緣故,網絡即使很深也不會帶來過大的參數量(見上圖Table2)。

2.1 卷積

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

上圖是卷積核在feature map上滑動的過程,這幅圖來自CS231n。下面是Deep Learning for Computer Vision (Andrej Karpathy, OpenAI)暑期學校課上列出的卷積公式:

f[x,y]∗g[x,y]=∑∞n1=−∞∑∞n2=−∞f[n1,n2]⋅g[x−n1,y−n2] f [ x , y ] ∗ g [ x , y ] = ∑ n 1 = − ∞ ∞ ∑ n 2 = − ∞ ∞ f [ n 1 , n 2 ] ⋅ g [ x − n 1 , y − n 2 ]

但似乎這裡的公式寫錯了,應該寫成:

f[x,y]∗g[x,y]=∑∞n1=−∞∑∞n2=−∞f[n1,n2]⋅g[n1−x,n2−y] f [ x , y ] ∗ g [ x , y ] = ∑ n 1 = − ∞ ∞ ∑ n 2 = − ∞ ∞ f [ n 1 , n 2 ] ⋅ g [ n 1 − x , n 2 − y ]

在知乎的“如何通俗的了解卷積?”這個問題下,找到一個比賈揚清的回答更易于了解的一個回答,下面是該回答中的計算過程示意圖:

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

這幅圖描述的是卷積的兩種實作方式,上面的中括号Traditional convolution就是直接法實作卷積,而下面的 Matrix Product Version of Convolution則是使用矩陣乘法實作卷積,可以看到該方法會先對原圖上卷積核2×2的大小的位置進行提取,也就是 im2col 的過程,在這裡depth是 3,即三個通道,那麼對輸入的三通道圖像的第一個計算卷積的位置處,會提取出2x2x3=12個元素成為一行,然後對所有的位置提取,多少個位置對應Input features (Matrix)的行數,而卷積核的個數對應kernel matrix的列數。剛好矩陣A(即Input features)的第一行和矩陣B(即Kernel Matrix)的第一列的結果就是結果矩陣第一個位置對應元素的結果,也就是卷積後的結果。

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

圖就是進一步列成矩陣乘法的樣子,進一步抽象并列出公式的示意圖。矩陣A(Input matrix)的行數相當于下圖卷積在原圖上滑動的次數,列數就是 KxKxC,其中 K 和 C 分别是卷積核的寬/高、feature map的通道數(Channel/Depth):

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

但需要注意的是,input matrix通常都是帶有深度,或者說是厚度的(depth/channel),這個動态地在不同位置處卷積的過程也可用下圖表示:

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

既然知道了卷積的做法,那麼下面我将分析:

  1. 卷積核尺寸;
  2. feature map的次元變化(height,width,depth);
  3. 卷積組(相比AlexNet的變化及個人沒有實驗的感性分析)。

2.1.1 卷積核尺寸

說VGGNet的kernel size前,不妨先來看看AlexNet的kernel size,AlexNet的結構如下:

# layer kernel size stride output type pad drop-rate
INPUT
1 CONV1 11×11 4 96
ReLU1
LRN1
POOL1 3×3 2 MAX
2 CONV2 5×5 1 256 2
LRN2
POOL2 3×3 2 MAX
3 CONV3 3×3 1 384 1
4 CONV4 3×3 1 384 1
5 CONV5 3×3 1 256 1
POOL5 3×3 2
6 FC6-4096
ReLU6
Drop6 0.5
7 FC7-4096
ReLU7
Drop7 0.5
8 FC8-1000
SoftMax-1000

可以看出AlexNet雖然也有用3×3的卷積核,而且是大規模用,但基本上都是在網絡的中後期。一開始卻用了11×11這樣的大卷積核,需要注意該卷積核對應的stride為4。我的了解是,一開始原圖的尺寸雖然很大很備援,但最為原始的紋理細節的特征變化一開始就用大卷積核盡早捕捉到比較好,後面的更深的層數害怕會丢失掉較大局部範圍内的特征相關性,因為後面更多是3×3這樣的小卷積核(和一個5×5卷積)。

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

另外,conv11x11 這樣的大卷積核使用的 stride 為4,見上圖是我畫的在一張 19×19 的圖上做11×11的卷積,其實會發現即使是 stride 為4,對于11×11的kernel size而言,中間有很大的重疊,計算出的3×3區域每個值很過于受到周邊像素的影響,每個位置卷積的結果會更多考慮周邊局部的像素點,原始的特征多少有被平滑掉的感覺。換句話說,局部資訊因為過大的重疊,會造成更多細節資訊的丢失。那大卷積核,是否帶來更大的參數和feature map大小呢?我計算了同樣conv3x3、conv5x5、conv7x7、conv9x9和conv11x11,在224x224x3的RGB圖上(設定pad=1,stride=4,output_channel=96)做卷積,卷積層的參數規模和得到的feature map的大小:

kernel conv param conv sum calc. calc. sum feature map feature sum conv + feature
conv3x3 3x3x3x96 2592 3x3x3x[(224-3+2×1)/4+1]^2x96x2 16695396 [(224-3+2×1)/4+1]^2×96 309174 311766
conv5x5 5x5x3x96 7200 5x5x3x[(224-5+2×1)/4+1]^2x96x2 45562500 [(224-5+2×1)/4+1]^2×96 303750 310950
conv7x7 7x7x3x96 14112 7x7x3x[(224-7+2×1)/4+1]^2x96x2 87721956 [(224-7+2×1)/4+1]^2×96 298374 312486
conv9x9 9x9x3x96 23328 9x9x3x[(224-9+2×1)/4+1]^2x96x2 142420356 [(224-9+2×1)/4+1]^2×96 293046 316374
conv11x11 11x11x3x96 34848 11x11x3x[(224-11+2×1)/4+1]^2x96x2 208918116 [(224-11+2×1)/4+1]^2×96 287766 322614

看來大卷積核帶來的參數量并不大(卷積核參數+卷積後的feature map參數,不同kernel大小這二者加和都是30萬的參數量),即使考慮AlexNet中有兩種形式的卷機組([conv-relu]-lrn-pool和[conv-relu]-[conv-relu]-[conv-relu]-pool)。實際增大的是計算量(上面我列出了計算量的公式,最後要乘以2,代表乘加操作)。為了盡可能證一緻,我這裡所有卷積核使用的stride均為4,可以看到,conv3x3、conv5x5、conv7x7、conv9x9、conv11x11的計算規模依次為:1600萬,4500萬,1.4億、2億,這種規模下的卷積,雖然參數量增長不大,但是計算量是恐怖的。

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

其實對比參數量,單層卷積核參數的量級在十萬,一般都不會超過百萬。相比全連接配接的參數規模是上一層的feature map和全連接配接的神經元個數相乘,這個也很恐怖。

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

作者在VGGNet的實驗中隻用了兩種卷積核大小:1×1和3×3。作者認為兩個3×3的卷積堆疊獲得的感受野大小,相當一個5×5的卷積;而3個3×3卷積的堆疊擷取到的感受野相當于一個7×7的卷積。見上圖,輸入的8個元素可以視為feature map的寬或者高,我畫了當輸入為8個神經元經過三層conv3x3的卷積得到2個神經元。

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

此外,在分割問題中卷積核的大小對結果有一定的影響,在上圖三層的conv3x3中,最後一個神經元的計算是基于第一層輸入的7個神經元,換句話說,反向傳播時,該層會影響到第一層conv3x3的前7個參數。從輸出層往回forward同樣的層數下,大卷積影響(做參數更新時)到的前面的輸入神經元越多。

  • input=8,3層conv3x3後,output=2,等同于1層conv7x7的結果;
  • input=8,2層conv3x3後,output=2,等同于2層conv5x5的結果。
VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

上圖是用2個stride=1、padding=0的conv3x3來代替1個stride=2的conv5x5的例子。此外,作者在3個conv3x3代替1個conv7x7的做法上,認為有以下三點優勢:

  1. 3個激活函數(ReLU)去代替1個,可使決策函數更加具有辨識能力,此外就卷積本身的作用而言,3×3 比 7×7 就足以捕獲特征的變化:3×3的9個格子,最中間的格子是一個感受野中心,可以捕獲上下左右以及斜對角的特征變化。主要在于3個堆疊起來後,三個3×3近似一個7×7,網絡深了兩層且多出了兩個非線性ReLU函數,(特征多樣性和參數參數量的增大)使得網絡容量更大(關于model capacity,AlexNet的作者認為可以用模型的深度和寬度來控制capacity),對于不同類别的區分能力更強(此外,從模型壓縮角度也是要摒棄7×7,用更少的參數獲得更深更寬的網絡,也一定程度代表着模型容量,後人也認為更深更寬比矮胖的網絡好);

    以下是個人的深層思考:網絡更深帶來了更多變化,更好的特征多樣性,就好比是資料增強雖然引來方差是好的,我們想在變化中尋找不變的映射關系。但是,網絡更深帶來特征更多真的好嘛?我覺得更多的特征和更深的網絡,不一定都是有助于、有貢獻于正确梯度下降尋找最優或者局部最優的方向,我們真正需要的是可以正确建立映射關系的特征。

    反倒是層數越深,特征更多,會有更多局部最優。但為此,我們又在減少因引入特征多樣性帶來的高方差的影響,不論是在随機梯度下降中引入動量,還是各種正則化的手段,又嘗試減少更深網絡帶來更多特征造成的影響。一方面我們在增大方差,又在減少方差。這樣看,似乎這是沖突的。

    網絡由于有着本身的更新政策,可以正确建立映射關系。但網絡更深卻在影響映射關系的建立,把這個建立的過程變得更加曲折,甚至無法建立出好的、正确的、有效的映射關系。

    我想了想,感覺這是一個平衡,重要是多了可以篩選:

    一方面,我們希望有更多特征,在于我們可以篩選。本身的更新政策可以指導映射關系的建立。但是學習的東西多了,必然會造成學習出現問題,因為要在其中篩選。但是所有的基于部分樣本的優化帶來的梯度估計,必然會學出的權重都有一點不正确。

    另一方面,我們又在減少影響,減少不正确性帶來的影響,就有這些正則化來去篩選。有的正則化起到篩選的作用,而有的則是減緩、減小高方差帶來錯誤下降方向的影響的作用。

    我覺得重點在于這個特征篩選做的好不好,現在大多情況都不缺資料。其實這樣看來,即使是深度學習,又回到了以前的問題,特征工程、特征選擇。似乎深度學習帶來了更深的網絡,表面上看給我們造成沒有必要做特征工程的假象,但其實我們做了這個過程,在網絡結構設計、子產品選擇、網絡的訓練(優化)trick裡。

    無論是特征跨 depth 的 cross(resnet),還是跨channel的cross(lrn、shufflenet)。這幾年的網絡都是在網絡更dense的前提(比方mobilenet)下,基于各自的module做特征工程,引入更多特征,一方面特征 diverse 方差加大,一方面又用正則等手段鈍化平滑方差。我認為,大家認為深度學習玄學的一個原因可能是不可估量的方差的 tradeoff 造成的。

    有小夥伴也提到,玄學也是因為現在的文章中說到的方法其實并不是work的,你按照他說的這麼調整就是不對。

  2. conv filter的參數減少。相比5×5、7×7和11×11的大卷積核,3×3明顯地減少了參數量。作者還使用了1×1的卷積核,認為1×1卷積核是channel級别的線性變換(畢竟一組channel用對應的一樣的卷積核在這一組channel上掃描,一組channel不是指這一層feature map的所有channel)。比方input channel數和output channel數均為C,那麼3層conv3x3卷積所需要的卷積層參數是:3x(Cx3x3xC)=27C^2 ,而一層conv7x7卷積所需要的卷積層參數是:Cx7x7xC=49C^2。conv7x7的卷積核參數比conv3x3多了(49-27)/27×100% ≈ 81%;
  3. 小卷積核代替大卷積核有正則作用。作者用三個conv3x3代替一個 conv7x7,認為可以進一步分解(decomposition)原本用7×7大卷積核提到的特征.

    This can be seen as imposing a regularisation on the 7 × 7 conv. filters,

    forcing them to have a decomposition through the 3 × 3 filters (with

    non-linearity injected in between).

    我沒看明白,關于正則化在《Deep Learning》這本書的Chapter 7 Regularization for Deep Learning中是這麼定義的:

    In section 5.2.2, we defined regularization as “any modification we make

    to a learning algorithm that is intended to reduce its generalization

    error but not its training error.”

    也就是說,隻要是可以減少泛化(驗證集/測試集)誤差,而非訓練誤差的任何方法都屬于正則化。作者所說的分解(decomposition)我可以感性了解,但是認為這是一種正則化可能還需要做進一步關于 “小卷積替代大卷積的” ablation study 和理論證明。

    選用 1×1 卷積核的原因:作者首先認為1×1卷積可以增加決策函數(decision function,這裡的決策函數我認為就是softmax)的非線性能力,非線性是由激活函數ReLU決定的,本身1×1 卷積則是線性映射,即将輸入的feature map映射到同樣次元的feature map。作者還提到“Network in Network” architecture of Lin et al. (2014).這篇文章就大量使用了1×1卷積核。

    此外,搜了些相關資料,簡單總結下1×1卷積的特點(就不說加入非線性這個conv自帶的特點了):

    1. 專注于跨通道的特征組合:conv1x1 根本不考慮單通道上像素的局部資訊(不考慮局部資訊),專注于那一個卷積核内部通道的資訊整合。conv3x3 既考慮跨通道,也考慮局部資訊整合;
    2. 對 feature map 的channel級别降維或升維:例如224x224x100的圖像(或feature map)經過20個conv1x1的卷積核,得到 224x224x20 的 feature map。尤其當卷積核(即filter)數量達到上百個時,3×3 或 5×5 卷積的計算會非常耗時,是以 1×1 卷積在 3×3 或 5×5 卷積計算前先降低 feature map 的次元。
      VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition
    關于小卷積核前人就有使用,如Ciresan et al. (2011)還有Goodfellow et al. (2014),後者使用11 層的網絡解決街道數量的識别問題(street number classification,我也沒看懂是回歸還是分類),結果顯示更深的網絡可以帶來更好地網絡性能。而作者在小卷積核的基礎上使用了更多層數,2014年ImageNet分類比賽的第一名使用GoogLeNet,Szegedy et al., (2014)也使用了更小的卷積核、更深達到22層的網絡,使用了5×5、3×3和1×1卷積(實際還用到了7×7的卷積,第一層卷積)。但GoogLeNet的拓撲結構比較複雜,上圖是Inception module的結構圖,可以看到module内直接使用了常見的三種卷積核進行并聯,并将最後的結果feature map直接concate到一起,而VGGNet則是使用傳統卷積核串聯的方式。
    VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition
    然而,分類性能上同樣的單模型,VGGNet比GoogLeNet在top5的錯分率要低,而多模型下,同樣七個網絡的VGGNet不如GoogLeNet。

2.1.2 feature map的次元變化

随層數遞增逐漸忽略局部資訊,feature map 的 width 和 height 随着每個pool操作縮小50%,5個pool 操作使得 width 和 height 逐漸變化:224->112->56->28->14->7,但是深度depth(或說是channel數),随着5組卷積在每次增大一倍:3->64->128->256->512->512。特征資訊從一開始輸入的224x224x3被變換到7x7x512,從原本較為local的資訊逐漸分攤到不同channel上,随着每次的conv和pool操作打散到channel層級上。

我的了解是,這樣便于後面fc層的特征映射,因為 fc 層相比conv更考慮全局資訊,global的feature map(既有width,height還有channel)資訊,全部映射到4096次元。估算一下,也就是說7x7x512,大概是25000,映射到4096,大概是5000,就是說壓縮到原來的五分之一。後面三個全連接配接的了解是,這個映射過程的學習要慢點來,太快不易于捕捉特征映射來去之間的細微變化,讓backprop學的更慢更細一些(更逐漸)。

其實按理說不應該将 feature map 的次元與後面 fc 層的分析拆分開,畢竟最後的分類器是softmax,三個fc層的操作結束才是最終的 feature map。那麼,最後一組卷積後就會接三組全連接配接層,前兩組fc的形式是:fc4096-relu-dropout0.5,最後一個fc的形式就是:fc1000。

可以發現feature map的次元在最後一個卷積後達到7x7x512,即大概25000,緊接着壓縮到4096維,可能是作者認為這個過程太急,又接一個fc4096作為緩沖,同時兩個fc4096後的relu又接dropout0.5 去過渡這個過程,因為最後即将給1k-way softmax,是以又接了一個fc1000去降低softmax的學習壓力。

feature map次元的整體變化過程是:先将local資訊壓縮,并分攤到channel層級,然後無視channel和local,通過fc這個變換再進一步壓縮為稠密的feature map,這樣對于分類器而言有好處也有壞處,好處是将local資訊隐藏于/壓縮到feature map中,壞處是資訊壓縮都是有損失的,相當于local資訊被破壞了(分類器沒有考慮到,其實對于圖像任務而言,單張feature map上的local資訊還是有用的.)

2.1.3 卷積組

除了卷積kernel和feature map的變化,卷積後的output channel數的變化是遞增的(上面已經說過)。但是,若以pooling操作為切分點對整個網絡分組的話,我們會得到五組卷積,五組卷積中有2種卷積組的形式,VGG網絡是下面這樣:

  • 前兩組卷積形式一樣,每組都是:conv-relu-conv-relu-pool;
  • 中間三組卷積形式一樣,每組都是:conv-relu-conv-relu-conv-relu-pool;
  • 最後三個組全連接配接fc層,前兩組fc,每組都是:fc-relu-dropout;最後一個fc僅有fc。

CS231n的blog裡将這種形式稱為layer pattern,一般常見的網絡都可以表示為:

INPUT -> [[CONV -> RELU]*N -> POOL?]*M -> [FC -> RELU]*K -> FC

的形式,其中,

?

表示pool是一個可選項。這樣的pattern,因為可以對小卷積核stacking,更适合建構深層網絡。

INPUT -> FC

表示一個線性分類器。

那麼這VGG兩種卷積組,即layer pattern的形式有什麼差別,很明顯第二種([conv-relu]-[conv-relu]-[conv-relu]-pool)比第一種([conv-relu]-[conv-relu]-pool) 多了一個[conv-relu]。我的了解是:

  1. 多出的relu對網絡中層進一步壓榨提煉特征。結合一開始單張 feature map 的 local 資訊更多一些,還沒來得及把資訊分攤到 channel 級别上,那麼往後就慢慢以增大 conv filter 的形式遞增地擴大channel數,等到了網絡的中層,channel數升得差不多了(資訊分攤到channel上得差不多了),那麼還想抽 local 的資訊,就通過再加一個[conv-relu]的形式去壓榨提煉特征。有點類似傳統特征工程中,已有的特征在固定的模型下沒有性能提升了,那就用更多的非線性變換對已有的特征去做變換,産生更多的特征的意味;
  2. 多出的conv對網絡中層進一步進行學習指導和控制不要将特征資訊漂移到channel級别上。
    1. 上一點更多的是relu的帶來的了解,那麼多出的[conv-relu]中 conv 的意味就是模型更強的對資料分布學習過程的限制力/控制力,做到資訊backprop可以回傳回來的學習指導。本身多了relu特征變換就加劇(權力釋放),那麼再用一個 conv 去控制(權力回收),也在指導網絡中層的收斂;
    2. 其實 conv 本身關注單張feature map上的局部資訊,也是在嘗試去盡量平衡已經失衡的channel 級别(depth)和local級别(width、height)之間的天平。這個conv控制着特征的資訊量不要過于向着channel級别偏移。
      VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

其實說到這裡,我想到一種古老的pretrain網絡的方式(見上圖,來自台大的機器學習技法課程):使用 auto-encoder 和 decoder 去逐層預訓練網絡,逐層地用輸入 x 預測輸入 x 。雖然說和這裡的卷積組的形式還是差異比較大,但是逐漸逐層地去學習的意思在裡面。逐層的預訓練網絡,在我了解就是想通過這樣的方式訓練處能夠提取深層特征表征的網絡權重。多少有點類似(其實有點牽強)這裡更深的一種卷積組的感覺,類比一下,每次我都在訓練一種卷積組,第一次可能是一層的卷積,第二次是兩層的,第三次是三層的,依此類推。我既希望這樣保證學到的權重不會導緻結果發散(爆炸或者消失),也希望可以有足以讓目前層特征傳遞到下一層、維持高效表示的特征權重(重點在于這一點)。

關于卷積組(Layer pattern),CS231n的部落格給出如下觀點:

  1. 串聯和串聯中帶有并聯的網絡架構。近年來,GoogLeNet在其網絡結構中引入了Inception子產品,ResNet中引入了Residual Block,這些子產品都有自己複雜的操作,上圖就是Inception子產品。換句話說,傳統一味地去串聯網絡可能并不如這樣串聯為主線,帶有一些并聯同類操作但不同參數的子產品可能在特征提取上更好。

    是以我認為這裡本質上依舊是在做特征工程,隻不過把這個過程放在裡 block 或者 module 的小的網絡結構裡,畢竟 kernel、stride、output 的大小等等超參數都要自己設定,目的還是産生更多豐富多樣的特征。

  2. 用在 ImageNet 上 pre-trained 過的模型。設計自己模型架構很浪費時間,尤其是不同的模型架構需要跑資料來驗證性能,是以不妨使用别人在 ImageNet 上訓練好的模型,然後在自己的資料和問題上在進行參數微調,收斂快精度更好。

    我認為隻要性能好精度高,選擇什麼樣的模型架構都可以,但是有時候要結合應用場景,對實時性能速度有要求的,可能需要多小網絡,或者分級小網絡,或者級聯的模型,或者做大網絡的知識蒸餾得到小網絡,甚至對速度高精度不要求很高的,可以用傳統方法。

2.1.4 Layer Sizing Patterns

要說到layer pattern,不得不提到 sizing pattern,這也是CS231n裡所講到的。對于每種層,有不同的預設設定:

  1. 輸入層:大都是 2 的N次方,這和網絡中卷積或者池化層出現的 stride 為 2 的次數有關,比方VGGNet中每個 pattern 的卷積不會對 feature map 的寬度和高度有改變,而每個pattern結束前總會做一個 stride 為 2 的下采樣,因為有 5 組,那麼做 5 次就是 32,是以VGGNet網絡input大小一般都是 32 的倍數,即 a×2n a × 2 n , n n 是下采樣的次數,aa 是最終卷積和池化得到的feature map大小,如224或者384。

    其實對于邊界問題的處理,主要有4種方法:

    1. 用0填充,相當于黑色,卷積核對應位置相乘也是0;
    2. 用邊界的鄰近像素擴充;
    3. 把圖當做一個循環,同一行最右邊的填補使用最左邊的像素;
    4. 舍棄無法卷積的部分。
  2. 卷積層:現在常用的是小卷積核如 3×3 或者 1×1。卷積為了保留feature map不變,通常會采取 pad 為 1 的操作,其實具體來說應該是:為了保證卷積後的 feature map的寬度和高度不變,那麼有 pad=(F−1)/2 p a d = ( F − 1 ) / 2 ,但我覺得這個有點問題,可以改成更一般的形式,不過首先可以看看計算下一層feature map寬高的公式:

    W2=(W1–F+2P)/S+1 W 2 = ( W 1 – F + 2 P ) / S + 1

    因為要保證 W1 W 1 和 W2 W 2 一樣,有 W1=W2=W W 1 = W 2 = W ,那麼可以導出:

    P=S(W−1)–W+F2 P = S ( W − 1 ) – W + F 2

    當 Stride=1 時,那麼 pad=(F−1)/2 p a d = ( F − 1 ) / 2 。因為現在 stride=1 的3×3卷積用的多,是以大家會預設說是 pad=1.

    VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

    上圖就是stride=1、padding=1的conv3x3的效果圖。關于這點上,也是由于實驗發現這樣保留feature map 的寬高情況下,性能好的緣故,我認為填補主要是針對stride大于1的情況帶來的邊界問題,如果input尺寸不是事先設定的 a×2n a × 2 n ,那麼就會有邊界無法卷積到的問題帶來資訊丢失。不過這種填補我認為也有一定問題,就是說原本 conv3x3 去計算對應位置的 3×3,而填補後為0,這樣相當于少算了一些值,這肯定還是有影響的。但若stride不是1,那麼要保證前後feature map的寬高一樣,就要根據上面的公式計算得出。

    另一個點是通常與 Input 比較接近的 conv 會采用大卷積核。關于接近input層使用較大的卷積核這點,我認為先是考慮到後面的操作,先盡可能用大的卷積核 cover 更多的原始資訊(雖然經過了卷積有一些變換),第二點在于大卷積核帶來的大感受野,後面的卷積層能的一個神經元能看到更大的 input,第三點是GPU的顯存受限,經典的例子就是 AlexNet 使用 stride=4 的 conv11x11,目的就是從一開始就減少顯存占用,其實這裡的 大stride,我覺得起到了一些正則的作用。但缺點也很明顯,因為卷積核變大,矩陣乘法實作卷積時,若沒有大 stride,那麼第一個矩陣的列數,也就是第二個矩陣的行數,會變大,帶來大的計算量。是以在AlexNet中,大卷積核也對應使用了大的stride值;

  3. 池化層:常見2×2的max-pooling,少見3×3或者更大的kernel。更大的kernel帶來的問題是資訊丢失帶來的資訊損失,此外,stride通常為2;其實按照以上的設定看來,也是有好處的。卷積專注于保留白間資訊前提下的channel變換,而池化則專注于空間資訊的變換(下采樣).

2.2 池化

VGGNet 中的 max-pool 均采用kernel為2×2的尺寸,stride為2的設定。這裡和AlexNet有差別,AlexNet使用的max-pool的kernel為3×3大小,stride為2的pool。

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

那麼我想卷積核也可以是2×2、4×4這種偶數的吧,為什麼大家都用奇數呢?我問了些人他們的回答也是說感受野中心這個問題。其實我覺得感受野中心看怎麼了解,如果是4×4的卷積核,可以說 4×4 因為是偶數,中間沒有感受野中心,但是也可以說 4×4 有 4 個感受野中心,也可以捕捉上下左右的資訊,說不定效果比 3×3 還更好!在計算上,也是對應位置相乘後整體加,不過目前大家都在用奇數尺寸的卷積核,但這需要進一步實驗說明。

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

另外一個是池化,先前沒有注意到 AlexNet 的 pooling 的kernel size全是奇數,裡面所有池化采用kernel size為3×3,stride為2的max-pooling。而VGGNet所使用的 max-pooling的kernel size均為2×2,stride為2的max-pooling。pooling kernel size從奇數變為偶數。小kernel帶來的是更細節的資訊捕獲,且是 max-pooling 更見微的同時進一步知著(見微知著,微:隐約;著:明顯。意指看到微小的苗頭,就知道可能會發生顯著的變化。比喻小中見大、以小見大)。

在CS231n裡講到現在也在逐漸不使用 pooling,因為發現完全可以使用一個 stride 不等于1的卷積來代替pooling,另外,不少工作,如生成模型(generative models)、對抗網絡(adversarial networks)、變分自動編碼器(variational autoencoders ,VAEs),發現用stride不等于1的卷積來代替 pooling 帶來的優勢。

關于pooling反向傳播的做法,常見有三種方式(max、average、stochastic,第三種随機池化現在已經不常見,訓練過程的做法是将池化 kernel 位置中的原圖的像素值,按照像素值占整體 kernel的比例來表示原始值,那麼原始像素值大的被選中的機率也就越大,随機産生一個數看落到哪個區間就使用哪個點做下采樣,而測試時的做法是每個位置的像素值乘以該位置的機率值并加和),caffe 代碼中對第三種方式并沒實作(可以提個PR,哈哈),反向的計算如下:

  • max:反向過程會記錄當時正向時最大值的位置,反向則最大值位置不變,其他位置填補0;
  • average:反向過程會将正向的平均值,以平均的形式分攤到每個位置;
  • stochastic:反向一樣記錄正向時時被随機選中的位置,該位置值不變,其他位置填補0。

2.3 全連接配接

形式上完全平移AlexNet的最後三層,VGGNet後面三層(三個全連接配接層)為:

  • FC4096-ReLU6-Drop0.5,FC為高斯分布初始化(std=0.005),bias常數初始化(0.1)
  • FC4096-ReLU7-Drop0.5,FC為高斯分布初始化(std=0.005),bias常數初始化(0.1)
  • FC1000(最後接SoftMax1000分類),FC為高斯分布初始化(std=0.005),bias常數初始化(0.1)

超參數上隻有最後一層fc有變化:bias的初始值,由AlexNet的0變為0.1,該層初始化高斯分布的标準差,由AlexNet的0.01變為0.005。超參數的變化,我的了解是,作者自己的感性了解指導認為,我以貢獻bias來降低标準差,相當于标準差和bias間trade-off,或許作者實驗validate發現這個值比之前AlexNet設定的(std=0.01,bias=0)要更好。

2.4 其它

我發現 AlexNet 和 VGGNet 的 SoftMax 層最後都是 1000 個輸出,但是有小夥伴說,經常有不在這1000類裡的物體被分類到了這一千類中的某一類,可能置信度還很高如80%等等,那我想在訓練的過程中加一個背景這一類進行輸出,這樣用一些非 1000 類物體中的圖檔去訓練。有小夥伴實驗表示,這樣性能會有小的提升。其實我們在一些分割或檢測問題中,也見過不少作者是用原本的類别數加一類背景類去訓練。

3. 訓練和測試

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

實作是基于Caffe架構,作者 branch out 出一個caffe的分支,在一台4張NVIDIA Titan BLACK 的機器上完成的,梯度的計算是彙總多張卡同步後的結果,是以和在單GPU上訓練的結果是一緻的(4張卡相比單張有3.75倍的加速),訓練一個網絡根據架構的不同大概要2到3周的時間。

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

3.1 訓練階段

除了對訓練圖像的多尺度後的crop進行采樣訓練,其它和AlexNet基本一緻:

  • 優化方法:帶動量(momentum)的小批量梯度下降
  • batch size:256
  • learning rate:0.01

    和AlexNet一樣,當val-acc 不下降則學習率縮小十倍,訓練過程縮小了三次

  • momentum:0.9
  • weight decay( L2 L 2 懲罰乘子): 5×10−4 5 × 10 − 4
  • dropout rate(前兩個全連接配接層):0.5
  • 目标函數:多項式邏輯斯特回歸(SoftMax)
  • 疊代次數:37萬次iteration(74 epochs)後,停止訓練

AlexNet的模型參數量是4000萬(無論是one-gpu還是two-gpu版),feature map的量級在140萬。AlexNet訓練了90個 epochs,用了兩張GTX 580 3GB跑了5、6天,估算下來230img/sec/2gpus;而VGGNet的6個模型的參量級都在1億3000萬到1億4000萬之間,feature map我沒算,四張卡跑一個網絡大概是2到三周的時間,假設兩周半,那麼估算下來62.64img/sec/4gpus。

盡管模型參數量是AlexNet的3倍多且層數深,但跑的epochs比AlexNet少收斂快,作者認為是以下兩點原因:

  1. 正則化:dropout和小卷積核的使用。關于dropout,我記得AlexNet有寫道:前兩個全連接配接層用到了dropout,若沒有dropout模型必然會過拟合, 但是有dropout後,收斂大約需要原本兩倍的 iteration 次數。我對 dropout 的了解是模型 ensemble,每次iteration對原網絡dropout 一些神經元後的模型可視為一個單獨的模型,最後test時則是ensemble的模型,效果必然好于單模型。參數越多越容易過拟合,比方全連接配接層比卷積層要容易過拟合,全連接配接層因為參數量大,好比一個多元高次函數,而卷積層好比簡單的函數,多元高次的函數肯定在捕捉細節特征上會比簡單函數好,但代價就是訓練時間更長,需要正則化等方法去平衡。對于收斂更快,我認為主要是小卷積核帶來的優勢,小卷積核參數少,從訓練樣本中需要拟合/學習的參數自然少,而且backprop的時候涉及到前面的範圍也比較小,因而似乎會收斂快(但我不認為這是 VGG 比 AlexNet 收斂快的根本原因);
  2. pre-initialisation,相當于預訓練。為了防止不好的初始化會導緻訓練過程中停止學習,作者把A實驗的模型的前四個卷積層和三個全連接配接層的參數拿來作為模型的初始化參數,中間層的初始值從均值為0,方差為0.01的正态分布中采樣得到,bias初始化為0,學習率設定和訓練A(相當于pre-train)時的一樣。雖然作者沒有承認pre-initialisation是預訓練,但本質上就是。好處主要兩點:性能比train-from-scratch有提高,且收斂更。

作者對中間層以均值為0,方差為0.01的正态分布初始化,和AlexNet一樣。我想也可以對已經訓練過的網絡做權重值的統計,用統計出的分布去嘗試初始化網絡層。作者最後也說到,送出結果後,Glorot& Bengio (2010)等人使用随機初始過程來對模型做參數初始化。

其實我想說,收斂更快的主要原因很可能就是預訓練,說小卷積核和dropout有點扯,感覺正則隻會延長訓練過程。另外在知乎看到一個觀點很有意思:

便也要糾正一下在提到CNN的時候經常出現的錯誤:“CNN的參數太多,造成學習困難。”

其實CNN相比較于以前的模型,參數并不見得多:在CNN之前,NEC Labs 采用 sparse SIFT+Pyramid Pooling的方法取得過ILSVRC的冠軍,在這些模型中,最後線性SVM的輸入特征在160K 到 260K不等。因為一共有1000類,是以SVM的總參數是160M-260M左右。Alex 2012年的模型隻有60M參數,而我們今年的模型大概隻有7M。(補充編輯:這些圖像特征一般都是稀疏的,但是SVM的參數并不稀疏。)

是以,其實我們應該說的是,CNN的優化是一個非凸(non-convex)的問題,是以才比較困難.

參考:如何評價今年的 ILSVRC 2014 結果?

https://www.zhihu.com/question/24904450

3.1.1 訓練圖像尺寸

模型輸入的固定input大小是 224×224,這個大小的圖是由rescale後的訓練圖像随機crop得到的(rescale是VGGNet的特色,後面會詳細講到),(即使是同一張圖像)每次SGD的iteration的crop都不同。為了進一步data augmentation,在crop上又做了随機水準翻轉(random horizontal flipping)和随機的RGB顔色抖動,這兩個小技巧也都來自AlexNet.

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

設定 S 是rescale後的訓練圖像的短邊,用 S 代指訓練過程使用的尺度。但crop的大小是固定的:224×224。總之 S 不小于224,但當 S=224 時,因為長邊大于等于224,,是以 crop 尺寸可以大體上捕捉整幅圖檔。而當訓練的圖像尺度S遠遠大于224時,crop 将隻會對應圖像的一小部分或者某些物體的部分。

作者使用兩種方法設定訓練圖像的尺度S:

  1. 固定訓練圖像的最短邊S,用這種單一尺度去訓練。即使是短邊固定了,但依然對原圖 crop 得到多種尺度的資訊。作者使用S=256(借鑒AlexNet等人)和S=384。作者先用 S=256 crop出的圖像去訓練網絡,之後再用 S=384 crop出的圖像去fine-tune網絡(該過程用了比S=256時更小的學習率0.001);
  2. 多種短邊尺度S訓練。給定S的一個範圍,作者使用[256, 512]。這樣帶來的好處是需要分類或者 localize 的物體本身在圖像上的像素就不同,這樣在訓練中就把這一因素考慮進去。這也可以看做是 data augmentation 裡的尺度擴增(scale jittering),這樣訓練同一個模型時是基于不同尺度的圖像進行的。作者依然是為了speed reason(太假了,明顯是因為fine-tine效果好,還不承認),基于model A 去 fine-tune了所有層。但是pre-train mode是采用固定尺寸384的最短邊的訓練圖像crop出的224的圖,去train-from-scratch的.

3.2 測試階段

測試階段先對輸入圖像的短邊rescale到預設尺度Q(測試圖像的尺度),測試圖像的尺寸Q和訓練圖像的尺寸 S 沒必要完全一樣。後文中作者提到對于每個訓練圖像的尺寸S,都有幾個不同的Q來去預測,可以得到更好地性能。

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

原圖比方左上角有個 5×5 的區域,crop出的224×224的左上角可以在裡面移動(也就是說圖像crop前,要resize到可以移動5×5格子的size,即224+5-1=228),另外加上水準翻轉帶來的可能性,那就是5x5x2=50種情況,作者總共在test階段用了三個scale,即三個Q,那麼一張圖總共有150 crops。網絡将會分别跑一張圖的150個crops,然後将結果average,作者的150crops相比GoogLeNet(Szegedy et al. (2014))的 4 scale的 144 crops(可以算一下,每個scale是36crops,如果其中包含水準翻轉的話,那麼就是18crops,可能是一個3×6的 regular grid,類似的方法,因為沒看文章這裡隻是猜測),并沒有很大的性能提升。

3.2.1 全連接配接轉為卷積

下面這段來自作者原文test小節的具體流程:

At test time, given a trained ConvNet and an input image, it is classified in the following way.

First, it is isotropically rescaled to a pre-defined smallest image side, denoted as Q (we also refer to it as the test scale). We note that Q is not necessarily equal to the training scale S (as we will show in Sect. 4, using several values of Q for each S leads to improved performance).

Then, the network is applied densely over the rescaled test image in a way similar to (Sermanet et al., 2014). Namely, the fully-connected layers are first converted to convolutional layers (the first FC layer to a 7 × 7 conv. layer, the last two FC layers to 1 × 1 conv. layers). The resulting fully-convolutional net is then applied to the whole (uncropped) image. The result is a class score map with the number of channels equal to the number of classes, and a variable spatial resolution, dependent on the input image size.

Finally, to obtain a fixed-size vector of class scores for the image, the class score map is spatially averaged (sum-pooled).

We also augment the test set by horizontal flipping of the images; the soft-max class posteriors of the original and flipped images are averaged to obtain the final scores for the image.

其中比較特别的一點在這句:

Namely, the fully-connected layers are first converted to convolutional layers (the first FC layer to a 7 × 7 conv. layer, the last two FC layers to 1 × 1 conv. layers).

也就是說,作者在測試階段把網絡中原本的三個全連接配接層依次變為 1 個conv7x7,2 個 conv1x1,也就是三個卷積層。改變之後,整個網絡由于沒有了全連接配接層,網絡中間的feature map不會固定,是以網絡對任意大小的輸入都可以處理,因而作者在緊接着的後一句說到: The resulting

fully-convolutional net is then applied to the whole (uncropped) image。

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

上圖是VGG網絡最後三層的替換過程,上半部分是訓練階段,此時最後三層都是全連接配接層(輸出分别是4096、4096、1000),下半部分是測試階段(輸出分别是1x1x4096、1x1x4096、1x1x1000),最後三層都是卷積層。下面我們來看一下詳細的轉換過程(以下過程都沒有考慮bias,略了):

先看訓練階段,有 4096 個輸出的全連接配接層FC6的輸入是一個 7x7x512 的feature map,因為全連接配接層的緣故,不需要考慮局部性, 可以把 7x7x512 看成一個整體,25508(=7x7x512)個輸入的每個元素都會與輸出的每個元素(或者說是神經元)産生連接配接,是以每個輸入都會有 4096 個系數對應4096個輸出,是以網絡的參數(也就是兩層之間連線的個數,也就是每個輸入元素的系數個數)規模就是 7x7x512x4096。對于FC7,輸入是4096個,輸出是4096個,因為每個輸入都會和輸出相連,即每個輸出都有4096條連線(系數),那麼4096個輸入總共有4096×4096條連線(系數),最後一個FC8計算方式一樣,略。

再看測試階段,由于換成了卷積,第一個卷積後要得到 4096(或者說是1x1x4096)的輸出,那麼就要對輸入的 7x7x512的feature map的寬高(即width、height次元)進行降維,同時對深度(即Channel/depth次元)進行升維。要把 7×7 降維到1×1,那麼幹脆直接一點,就用 7×7 的卷積核就行,另外深度層級的升維,因為 7×7 的卷積把寬高降到 1×1,那麼剛好就升高到4096就好了,最後得到了 1x1x4096 的feature map。這其中卷積的參數量上,把 7x7x512 看做一組卷積參數,因為該層的輸出是4096,那麼相當于要有4096組這樣 7x7x512 的卷積參數,那麼總共的卷積參數量就是:[7x7x512]x4096,這裡将 7x7x512 用中括号括起來,目的是把這看成是一組,就不會懵。

第二個卷積依舊得到 1x1x4096 的輸出,因為輸入也是 1x1x4096,三個次元(寬、高、深)都沒變化,可以很快計算出這層的卷積的卷積核大小也是1×1,而且,通道數也是4096,因為對于輸入來說,1x1x4096 是一組卷積參數,即一個完整的 filter,那麼考慮所有4096個輸出的情況下,卷積參數的規模就是 [1x1x4096]x4096。第三個卷積的計算一樣,略。

其實VGG的作者把訓練階段的全連接配接替換為卷積是參考了OverFeat的工作,如下圖是OverFeat将全連接配接換成卷積後,帶來可以處理任意分辨率(在整張圖)上計算卷積,而無需對原圖resize的優勢。

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

不過可以看到,訓練階段用的是 crop 或者 resize 到14×14的輸入圖像,而測試階段可以接收任意次元,如果使用未經crop的原圖作為輸入(假設原圖比crop或者resize到訓練尺度的圖像要大),這會帶來一個問題:feature map變大了。比方 VGG 訓練階段用224x224x3的圖作為模型輸入,經過5組卷積和池化,最後到7x7x512次元,最後經過無論是三個卷積或者三個全連接配接,次元都會到1x1x4096->1x1x4096->1x1x1000,而使用 384x384x3 的圖做模型輸入,到五組卷積和池化做完(即 25=32 2 5 = 32 ),那麼feature map變為12x12x512,經過三個由全連接配接變的三個卷積,即feature map 經曆了 6x6x4096->6x6x4096->6x6x1000 的變化過程後,再把這個 6x6x1000 的 feature map 最終交給SoftMax進行分類。

此外,我有想到四個問題:

  1. 文中說對 class score 做 average,但并未說這個 class score 是在 softmax 前還是後得到的。具體而言,作者在這裡沒有具體說明是将6x6x1000的 feature map 先做average到 1x1x1000 的次元後再做 SoftMax,還是先給 SoftMax 分類,得到 6x6x1000 的結果,再對每個結果進行average?因為作者沒有說清楚,不過我覺得兩個都可以試試,看哪種效果好用哪個。後來我想到 softmax 前必須是1k維的,因為 softmax 隻是一個 soft-max,具體可以看看softmax的公式,這一來如果是 6x6x1000 的 feature map 需要在 softmax 前做 average 到 1x1x1000 才行;
  2. 直接把訓練階段的全連接配接參數當做測試階段的卷積參數,不需要做參數微調嘛?做和不做,哪個效果更好?不過我可以想來如果用同樣資料,效果可能不好或者持平,但是解決不同的問題或許再做 fine-tune,效果說不定會更好;
  3. 有實驗表明将最後所有FC層轉為CONV後,比方 384x384x3 的圖,最後得到 6x6x1000 的feature map 與不轉換 fc 為 conv 的單個網絡跑36次,效果會更好嘛?
  4. 單個網絡模型下,同樣或者不同尺寸的圖輸入到轉換前和轉換後的網絡,全卷積網絡的性能更好嗎?

以上問題都需要做實驗才能得出,最近懶得動,也就捂臉不多說了。

4. 分類實驗

12年到14年的挑戰賽都使用的是 1000 個類别的ILSVRC-2012資料集(Large Scale Visual Recognition Challenge),其中:

  • 訓練集:130萬張圖檔;
  • 驗證集:5萬張圖檔;
  • 測試集:10萬張圖檔,這組資料的label沒有給出(with held-out class labels)。

兩個性能評估準則:top-1 和 top-5 error。前一個是多類分類錯誤率,錯分的圖像的比率。後一個是ILSVRC中主要的評估名額,計算的是預測出來的top5的類别裡沒有ground truth的比率,即top-5 error。

因為作者自己在下面實驗的緣故,當然沒有測試集的 ground truth 類别,是以作者就用驗證集當做測試集來觀察模型性能。這裡作者使用兩種方式來評估模型在測試集(實際的驗證集)的性能表現:single scale evaluation 和 multi-scale evaluation。

4.1 單尺度評估

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

對每個網絡(總共六個)進行單獨評估,測試圖像尺寸依訓練時的尺寸設定分為兩種情況:

  1. 訓練圖像的尺寸S固定時,設定訓練圖像尺寸S等于測試圖像尺寸Q;
  2. 訓練圖像尺寸S是介于 [Smin,Smax] [ S m i n , S m a x ] 時,設定測試圖像尺寸 Q=0.5(Smin+Smax) Q = 0.5 ( S m i n + S m a x ) 。
    VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

作者發現,即使是單一尺度(Scale),訓練時進行尺度随機(scale jittering)resize再crop圖像( S∈[256;512] S ∈ [ 256 ; 512 ] )的方式比固定最小邊後crop圖檔(S=256或者S=384)去訓練的效果好。也再次印證了對訓練圖像以scale jittering的方式做augmentation(捕捉多尺度資訊上)是有效果的。

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

實驗結論:

  1. LRN層無性能增益(A和A-LRN)。作者通過網絡A和A-LRN發現AlexNet曾經用到的LRN層(local response normalization,LRN是一種跨通道去normalize像素值的方法)沒有性能提升,是以在後面的4組網絡中均沒再出現LRN層。

    當然我也感覺沒啥用,想到 max-pooling 比 average-pooling 效果好,我就感覺這個LRN沒啥用,不過如果把 LRN 改成跨通道的 max-normal,我感覺說不定會有性能提升。特征得到retain更明顯。

  2. 深度增加,分類性能提高(A、B、C、D、E)。從11層的A到19層的E,網絡深度增加對top1和top5的error下降很明顯,是以作者得出這個結論,但其實除了深度外,其他幾個網絡寬度等因素也在變化,depth matters 的結論不夠 convincing。
  3. conv1x1的非線性變化有作用(C和D)。C和D網絡層數相同,但D将C的3個conv3x3換成了conv1x1,性能提升。這點我了解是,跨通道的資訊交換/融合,可以産生豐富的特征易于分類器學習。conv1x1相比conv3x3不會去學習local的局部像素資訊,專注于跨通道的資訊交換/融合,同時為後面全連接配接層(全連接配接層相當于global卷積)做準備,使之學習過程更自然。
  4. 多小卷積核比單大卷積核性能好(B)。作者做了實驗用B和自己一個不在實驗組裡的較淺網絡比較,較淺網絡用conv5x5來代替B的兩個conv3x3。多個小卷積核比單大卷積核效果好,換句話說當考慮卷積核大小時:depths matters。

    非常非常感謝嚴謹的Ant同學,這裡第四個結論的描述不夠嚴謹及結論表述不清導緻的這個錯誤。原文中說到:在同樣感受野範圍下,用5×5的卷積去等效替代3×3卷積的網絡性能下降。因而我得出“多小卷積核比單大卷積核性能好”這一結論。這一結論我描述的不夠嚴謹,應該改為:“多個小卷積核的堆疊比有同樣感受野規模的大卷積性能好。”

    然而另一點是我沒有仔細看原文造成的。在原文中剛剛那個結論後的描述前有一句:it is also important to capture spatial context by using conv. filters with non-trivial receptive fields (D is better than C).,也就是說,還有一組實驗是同樣深度為16層的網絡C和網絡D的比較。網絡C在5個組卷積的後3個組卷積中,每個組卷積中的最後一個卷積都是1×1卷積(而網絡D均為3×3卷積),性能不如網絡D。這恰恰是一個1×1的卷積核性能要比3×3的大卷積性能差的對照組。與我先前得出的結論是相反的,但需要注意的是這組實驗若參照上一組的結論(多個小卷積核的堆疊比有同樣感受野規模的大卷積性能好)可以發現感受野不同因而沒有可比性。但因層數相同(也是非線性變化相同),我們可以勉強得到另一個初步結論:層數(非線性變換)相同下,小卷積核性能不如大卷積核。因為其他有關卷積的超參數存在,還需要進一步做更多的實驗來驗證這個結論。最後再一次非常感謝Ant同學!

4.2 多尺度評估

也就是對輸入圖像在一定範圍内的随機尺度縮放,模型最終的結果,是基于不同尺度(賭赢多個不同值的Q)且是crop後的圖像跑網絡得到的softmax結果的平均。

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition
  • 用固定大小的尺度S訓練的模型,用三種尺寸Q去評估,其中 Q=[S–32,S,S+32] Q = [ S – 32 , S , S + 32 ] ;
  • 用尺度S随機的方式訓練模型, S∈[Smin;Smax] S ∈ [ S m i n ; S m a x ] ,評估使用更大的尺寸範圍 Q={Smin,0.5(Smin+Smax),Smax} Q = { S m i n , 0.5 ( S m i n + S m a x ) , S m a x } 。
    VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

多尺度評估結果如上表所示,C、D、E這三組有随機尺度訓練,發現效果比固定尺度訓練的模型帶來的性能更好。但我認為也很有可能是尺寸大帶來的結果,之前我在跑120類狗分類資料集時,尺寸設定224和512分别訓練,訓練集和驗證集的準确率基本收斂時,分辨率224×224的top1

accuracy 在30%左右,而分辨率512×512的top1 accuracy在50%~60%。是以我覺得這個實驗不夠說明随機 scale 帶來的性能優勢,因為固定尺寸的最大尺寸(384)比随機尺寸的最大尺寸(512)要小很多。當然,仍舊是深度随着遞增越來越深(C、D、E,也要考慮寬度)的網絡性能越好。

4.3 多crop評估

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

作者比較了dense ConvNet evaluation 和 multi-crop evaluation。發現multi-crop比dense ConvNet 的 evaluation 性能稍好,二者通過 averaging softmax output 結合起來使用效果比二者之一要好。作者得到這樣的結論有假定,這句話:

As noted above, we hypothesize that this is due to a different treatment of convolution boundary conditions.

沒看懂這裡的 convolution boundary conditions 是指什麼,另外,關于dense crop/application/evaluation,這是在OverFeat有講到的、偏工程刷比賽的做法,沒什麼實質性意義,經常刷比賽的同學可以去查查 OverFeat 中的 dense evaluation。

4.4 卷積網絡融合(ConvNet Fusion)

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

多模型融合是基于多個網絡softmax輸出的結果的平均,該方法在AlexNet和OverFeat中也有用到。

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

融合多卷積網絡前,作者單尺度或者多尺度訓練了模型,七個模型ensemble後的性能可以達到7.3%的top-5 error。最終作者選出兩個最好的多尺度模型(D、E)融合,并使用dense和multi-crop的evaluation,top-5 error降到7.0%。最好的單模型是E,top-5 error為7.1%。

4.5 與其他SOTA模型比較

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

與其他state of the art的模型比較來看,單模型裡最好的還是VGG,比GoogLeNet最好的單模型也要少0.9%的top-5 error。作者認為自己隻是繼承了1989年LeNet的卷積架構的基礎上,主要就是加深了深度帶來如此性能提升,當然我覺得這樣說不合理,前面已經說過了,略。

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

5. Localization

作者在結論部分就是說模型在其他資料及上的性能也不錯,另外就是深度matters。好了不說這些了,下面看看VGGNet是如何做到Localization第一的。

首先說一下localization,這是object detection的一種特例:

It can be seen as a special case of object detection, where a single object bounding box should be predicted for each of the top-5 classes, irrespective of the actual number of objects of the class.

預測出一個物體邊界框,框需要給出top-5類别的每個邊界框,而無需關注具體類别。在這裡,作者采用的方法和2014年OverFeat(Sermanet et al獲得ILSVRC-2013的localisation冠軍)所使用的方法基本一緻,略有修改。

物體定位也是使用卷積網絡來實作,隻是把最後原本分類的類别分數預測換成檢測框的位置坐标預測。預測的檢測框是一個4-D的向量,存儲了中心點的坐标以及該檢測框的寬度和高度,總共4個值。此外,對檢測框預測的類别數也可以進行選擇,這樣就會有兩種:

  • 單類回歸(single-class regression,SCR),OverFeat作者提出;
  • 每類回歸(class-specific regression,也就是per-class regression,PCR)。

第一種單類回歸,最後的預測輸出是4-D,而第二種最後的預測輸出因為資料包含了1000個類别,是以是4000-D。作者使用在分類任務中表現最好的16層的VGG(D網絡)來做這個任務。

5.1 訓練

與前文所述的分類訓練基本相同,主要不同在于将分類的邏輯斯特回歸的目标函數換成了歐氏距離損失(Euclidean loss):

12N∑Ni=1|x1i–x2i|22 1 2 N ∑ i = 1 N | x i 1 – x i 2 | 2 2

  • Header:

    ./include/caffe/layers/euclidean_loss_layer.hpp

  • CPU implementation:

    ./src/caffe/layers/euclidean_loss_layer.cpp

  • CUDA GPU implementation:

    ./src/caffe/layers/euclidean_loss_layer.cu

上面是來自caffe文檔的歐氏距離損失,可以看一下cpu的實作:

template
void EuclideanLossLayer::Forward_cpu(const vector<Blob*>& bottom,
const vector<Blob*>& top) {
int count = bottom[]->count();
caffe_sub(
count,
bottom[]->cpu_data(),
bottom[]->cpu_data(),
diff_.mutable_cpu_data());
Dtype dot = caffe_cpu_dot(count, diff_.cpu_data(), diff_.cpu_data());
Dtype loss = dot / bottom[]->num() / Dtype();
top[]->mutable_cpu_data()[] = loss;
}
           

用caffe_sub來實作預測值和真實值相減,再用caffe_cpu_dot實作內插補點的平方最後把結果儲存在dot變量裡,并除以2N後将loss儲存。

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

作者訓練了兩個不同尺度S的模型:S=256、S=384。因為ImageNet比賽 deadline緣故,沒有做訓練圖像的尺度随機(scale jittering)resize的 augmentation。訓練初始化是用對應的分類模型(同樣尺度規模),初始學習率為0.001。作者嘗試了fine-tune所有層以及前兩個全連接配接層兩種,OverFeat也曾使用過的方法。最後一個全連接配接層随機初始化并從頭訓練。作者正文寫的是VGG用于分類的描述,這裡差別是将最後一個SoftMax層(SoftMax就是邏輯斯特回歸的更一般形式,雖名為回歸,但實際一般是用于分類問題,“邏輯”我的了解是最後的值映射範圍在零與一之間的小數,即邏輯值。上圖的Sigmoid即S型函數,也是邏輯回歸函數的形式,這一形式包括Tanh也是傳統的激活函數的形式)換成歐氏距離等可以衡量距離的損失/目标函數的形式。

這裡檢測框的資訊是通過歐氏距離度量來計算誤差,得到損失函數并去優化,進行參數更新疊代。除了歐氏距離,其他關于距離度量的函數還有曼哈頓距離、切比雪夫距離、闵可夫斯基距離、标準化歐氏距離、馬氏距離、漢明距離、傑卡德距離&傑卡德相似系數,當然還可以用相關系數&相關距離來計算,另外我查到還有資訊熵也可以用于相似性度量,那麼我想用于決策樹特征分叉的基尼系數也是可以的咯!關于更多有關度量學習,可以參考這個CMU的Liu Yang做的Matlab工具箱DistLearnKit和其綜述:

  • A Matlab Toolkit for Distance Metric Learning

    http://www.cs.cmu.edu/~liuy/distlearn.htm

5.2 測試

作者使用兩種測試方法:

  1. crop resize 到Q尺度的圖像的中間區域,然後喂給網絡回歸出4-D的檢測框結果;
  2. 對全圖使用 localisation 的卷積網絡做dense evaluation。與分類任務類似,不同在于将最後一個用于産生類别分數特征的全連接配接層換成檢測框預測的特征。拿到最後的檢測框預測是通過貪心合并的過程(Sermanet等人2014年的OverFeat),該過程會首先通過平均某些坐标值來合并時空接近的預測,之後再基于卷積網絡算出的類别分數來排序。當使用多個localisation網絡,我們先把所有預測出的檢測框結果進行貪心合并過程(和剛剛說的方法一樣,通過平均坐标來合并空間臨近的預測結果)。作者沒有使用OverFeat所使用的 Multiple pooling offsets technique,該方法類似非最大值抑制,可以增加預測出來的檢測框的spatial resolution和結果性能,沒了解這裡說的spatial resolution是什麼,感覺像是空間辨識能力,畢竟該方法和最大值抑制,應該是篩掉一些結果,使得預測的檢測框更具突出(差異性,或許也就是作者所說的spatial resolution)。

5.3 Localization實驗

作者使用第一種測試評估的方法确定 Localization 的設定,我的了解是某些超參數的設定。之後再次使用第二種測試評估方法,即 fully-fledged。定位的誤差是根據ILSVRC标準确定的(Russakovsky等人2014),例如預測的檢測框與ground-truth檢測框的IOU(intersection-over-union)大于0.5就視為預測正确。

5.3.1 參數設定

因為有在測試時根據預測的類别數,分為兩種測試方法:第一種單類回歸(SCR),最後的預測輸出是4-D,而第二種每類回歸(PCR),最後的預測輸出包含了1000個類别即4000-D。作者比較發現單類回歸效果比多類要好,這和OverFeat實驗得出的結論相反。

其實我的了解更傾向于OverFeat 的結論:單類回歸(PCR)比每類回歸(SCR)結果好。是可能單類回歸(SCR)的效果更好,我認為單類相比每類回歸,無論是模型參數的分布抑或學習目标都是基于4-D的,學習壓力會小許多,而讓模型一次考慮太多如1000類,反而可能在考慮太多類的情況下去平衡每個類,網絡學到的參數可能并不好。當然,因為我并沒做實驗,隻是根據RCNN中用SVM來分類而不是SoftMax這一個點的感性的了解,RCNN認為用 SVM 相比 SoftMax 的優勢在于:1. 收斂快(跑1個epoch後,SVM基本就收斂);2. 效果好(比SoftMax好,這也是最主要的)。

此外,作者還發現 fine-tune 所有層後的性能要比僅 fine-tune 全連接配接層拿到的結果好。這是對于作者用CNN做Localization來說的(其它分類任務時,CNN隻是用來提取特征,用SVM來做分類)。

VGGNet 閱讀了解 - Very Deep Convolutional Networks for Large-Scale Image Recognition論文了解 - VGGNet - Very Deep Convolutional Networks for Large-Scale Image Recognition

上圖是作者根據下面的參數設定得到的性能結果,比較流程如下:

  1. 比較單類回歸(SCR)和每類回歸(PCR)的性能。發現每類回歸效果好;
  2. 對比在 Localization 任務中,fine-tune所有層比僅fine-tune全連接配接層拿到的模型性能好(這點和OverFeat得出的結論一樣);
  3. 圖像的訓練尺寸。這點其實和選擇的 pre-trained 模型有關,作者發現最短邊S=384或者256性能差不多(the result with S=256 exhibit the same behavior and are not shown for brevity)。但仍然選擇的是S=384的pre-trained模型;
  4. 全面評估(fully-fledged evaluation)。和正文裡分類時類似, Localization 用了densely-computed bounding box預測,同時将預測得比較臨近的檢測框使用 OverFeat 的方法進行檢測框的合并。同時作者發現,用整幅圖比用圖中心的 crop 來回歸,得出的性能好,此外作者還使用了不同的scale去測試,而且還通過結合多個網絡的預測結果,得到了更好的性能。

5.3.2 與其他SOTA比較

作者拿到2014年 localization 問題的第一名,相比前一年的冠軍OverFeat,VGG用了更少的scale并且沒有使用分辨率增強技術(resolution enhancement technique)。當然作者也認為如果用上了這樣的技術,VGG模型的性能會更好,又再一次強調了模型深度帶來更好的localization性能,盡管是一個比較簡單的localization方法,但特征的表達非常卓越。其實說白了,還是看特征提取的好不好,是以我想,總結出來那就是:性能不好、特征不夠,變換多尺度多模型來湊。

6. 評價

最後貼出CS231n的評價:

The runner-up in ILSVRC 2014 was the network from Karen Simonyan and Andrew Zisserman that became known as the VGGNet. Its main contribution was in showing that the depth of the network is a critical component for good performance. Their final best network contains 16 CONV/FC layers and, appealingly, features an extremely homogeneous architecture that only performs 3×3 convolutions and 2×2 pooling from the beginning to the end. Their pretrained model is available for plug and play use in Caffe. A downside of the VGGNet is that it is more expensive to evaluate and uses a lot more memory and parameters (140M). Most of these parameters are in the first fully connected layer, and it was since found that these FC layers can be removed with no performance downgrade, significantly reducing the number of necessary parameters.

我這裡對其簡單總結下:

  1. 深度提升性能;
  2. 最佳模型:VGG16,從頭到尾隻有3×3卷積與2×2池化。簡潔優美;
  3. 開源pretrained model。與開源深度學習架構Caffe結合使用,助力更多人來學習;
  4. 卷積可代替全連接配接。整體參數達1億4千萬,主要在于第一個全連接配接層,用卷積來代替後,參數量下降(這裡的說法我認為是錯的,替代前後用同樣的輸入尺寸,網絡參數量、feature map、計算量三者沒有變化)且無精度損失。

參考

以下是一些參考文獻,雖然不少地方引用了,但是偷懶沒有在文中具體标明。老實說,有時間能看原汁原味的東西就不要看别人吃過的,即使我寫的這篇,看原版的東西我覺得收獲更大一些。

  • ILSVRC-2014 presentation
  • http://www.robots.ox.ac.uk/~karen/pdf/ILSVRC_2014.pdf
  • http://cs231n.stanford.edu/slides/2017/cs231n_2017_lecture9.pdf
  • Convolutional neural networks on the iPhone with VGGNet
  • A Matlab Toolkit for Distance Metric Learning
  • 圖像進行中的L1-normalize 和L2-normalize – CSDN部落格 - 注:公式寫錯了
  • Feature Visualization
  • TensorFlow 教程 #14 – DeepDream(多圖預警)
  • caffe/pooling_layer.cpp at 80f44100e19fd371ff55beb3ec2ad5919fb6ac43 · BVLC/caffe
  • VGG網絡中測試時為什麼全連結改成卷積? – 知乎
  • pooling mean max 前向和反向傳播 – CSDN部落格
  • caffe/pooling_layer.cpp at 80f44100e19fd371ff55beb3ec2ad5919fb6ac43 · BVLC/caffe
  • Deep learning:四十七(Stochastic Pooling簡單了解) – tornadomeet – 部落格園
  • Convolutional Neural Networks – Basics · Machine Learning Notebook
  • 在 Caffe 中如何計算卷積? – 知乎
  • High Performance Convolutional Neural Networks for Document Processing

    Kumar Chellapilla, Sidd Puri, Patrice Simard

  • https://hal.archives-ouvertes.fr/file/index/docid/112631/filename/p1038112283956.pdf

繼續閱讀