2014年,牛津大學計算機視覺組(Visual Geometry Group)和Google DeepMind公司的研究員一塊兒研發出了新的深度卷積神經網絡:VGGNet,並取得了ILSVRC2014比賽分類項目的第二名(第一名是GoogLeNet,也是同年提出的).論文下載 Very Deep Convolutional Networks for Large-Scale Image Recognition。論文主要針對卷積神經網絡的深度對大規模圖像集識別精度的影響,主要貢獻是使用很小的卷積核(\(3\times3\))構建各類深度的卷積神經網絡結構,並對這些網絡結構進行了評估,最終證實16-19層的網絡深度,可以取得較好的識別精度。 這也就是經常使用來提取圖像特徵的VGG-16和VGG-19。html
VGG能夠當作是加深版的AlexNet,整個網絡由卷積層和全鏈接層疊加而成,和AlexNet不一樣的是,VGG中使用的都是小尺寸的卷積核(\(3\times3\))。python
對比,前文介紹的AlexNet的網絡結構圖,是否是有種賞心悅目的感受。整個結構只有\(3\times3\)的卷積層,連續的卷積層後使用池化層隔開。雖然層數不少,可是很簡潔。網絡
例如\(7 \times 7 \times 512\)的層要跟4096個神經元的層作全鏈接,則替換爲對\(7 \times 7 \times 512\)的層做通道數爲409六、卷積核爲\(1 \times 1\)卷積。
這個「全鏈接轉卷積」的思路是VGG做者參考了OverFeat的工做思路,例以下圖是OverFeat將全鏈接換成卷積後,則能夠來處理任意分辨率(在整張圖)上計算卷積,這就是無需對原圖作從新縮放處理的優點。
架構
VGG網絡相比AlexNet層數多了很多,可是其結構卻簡單很多。函數
VGG論文主要是研究網絡的深度對其分類精度的影響,因此按照上面的描述設計規則,做者實驗的了不一樣深度的網絡結構
性能
全部網絡結構都聽從上面提到的設計規則,而且僅是深度不一樣,也就是卷積層的個數不一樣:從網絡A中的11個加權層(8個卷積層和3個FC層)到網絡E中的19個加權層(16個卷積層和3個FC層)。卷積層的寬度(通道數)至關小,從第一層中的64開始,而後在每一個最大池化層以後增長2倍,直到達到512。
上圖給出了各個深度的卷積層使用的卷積核大小以及通道的個數。最後的D,E網絡就是大名鼎鼎的VGG-16和VGG-19了。
AlexNet僅僅只有8層,其可訓練的參數就達到了60M,VGG系列的參數就更恐怖了,以下圖(單位是百萬)
學習
因爲參數大多數集中在後面三個全鏈接層,因此雖然網絡的深度不一樣,全鏈接層確實相同的,其參數區別倒不是特別的大。測試
論文首先將訓練圖像縮放到最小邊長度的方形,設縮放後的訓練圖像的尺寸爲\(S \times S\)。網絡訓練時對訓練圖像進行隨機裁剪,裁剪尺寸爲網絡的輸入尺寸\(224 \times 224\)。若是\(S =224\),則輸入網絡的圖像就是整個訓練圖像;若是\(S > 224\),則隨機裁剪訓練圖像包含目標的部分。ui
對於訓練集圖像的尺寸設置,論文中使用了兩種方法:es5
多尺度評估,測試圖像的尺度抖動對性能的影響
對同一張測試圖像,將其縮放到不一樣的尺寸進行測試,而後取這幾個測試結果的平均值,做爲最終的結果(有點像集成學習,所不一樣的是,這裏是測試圖像的尺寸不一樣)。使用了三種尺寸的測試圖像:\(Q\)表示測試圖像,\(S\)表示訓練是圖像尺寸:\(Q = S - 32\),\(Q = S + 32\),前面兩種是針對訓練圖像是固定大小的,對於訓練時圖像尺寸在必定範圍內抖動的,則可使用更大的測試圖像尺寸。\(Q = \{S_{min},0.5(S_{min} + S_{max}),S_{max}\}\).
評估結果以下:
評估結果代表,訓練圖像尺度抖動優於使用固定最小邊S。
稠密和多裁剪圖像評估
Dense(密集評估),即指全鏈接層替換爲卷積層(第一FC層轉換到7×7卷積層,最後兩個FC層轉換到1×1卷積層),最後得出一個預測的score map,再對結果求平均。
multi-crop,即對圖像進行多樣本的隨機裁剪,將獲得多張裁剪獲得的圖像輸入到網絡中,最終對全部結果平均
從上圖能夠看出,多裁剪的結果是好於密集估計的。並且這兩種方法確實是互補的,由於它們的組合優於其中的每一種。
因爲不一樣的卷積邊界條件,多裁剪圖像評估是密集評估的補充:當將ConvNet應用於裁剪圖像時,卷積特徵圖用零填充,而在密集評估的狀況下,相同裁剪圖像的填充天然會來自於圖像的相鄰部分(因爲卷積和空間池化),這大大增長了整個網絡的感覺野,所以捕獲了更多的圖像內容信息。
依照VGG的設計原則,只使用小尺寸的\(3\times3\)卷積核以及\(2 \times 2\)的池化單元,實現一個小型的網絡模型。
class MiniVGGNet: @staticmethod def build(width,height,depth,classes): model = Sequential() inputShape = (height,width,depth) chanDim = -1 if K.image_data_format() == "channels_first": inputShape = (depth,height,width) chanDim = 1 model.add(Conv2D(32,(3,3),padding="same",input_shape=inputShape)) model.add(Activation("relu")) model.add(BatchNormalization(axis=chanDim)) model.add(Conv2D(32,(3,3),padding="same")) model.add(Activation("relu")) model.add(BatchNormalization(axis=chanDim)) model.add(MaxPooling2D(pool_size=(2,2))) model.add(Dropout(0.25)) model.add(Conv2D(64,(3,3),padding="same")) model.add(Activation("relu")) model.add(BatchNormalization(axis=chanDim)) model.add(Conv2D(64,(3,3),padding="same")) model.add(Activation("relu")) model.add(BatchNormalization(axis=chanDim)) model.add(MaxPooling2D(pool_size=(2,2))) model.add(Dropout(0.25)) model.add(Flatten()) model.add(Dense(512)) model.add(Activation("relu")) model.add(BatchNormalization()) model.add(Dropout(0.25)) model.add(Dense(classes)) model.add(Activation("softmax")) return model
最終輸出10分類,應用於CIFAR10,表現以下: