1. 程式人生 > >第15章 MiniVGGNet:更深的CNNs

第15章 MiniVGGNet:更深的CNNs

文獻 ide 訓練數據 git 交互 nal mod 目前 keras

第15章 MiniVGGNet:更深的CNNs

VGGNet(或簡稱為VGG),第一次在文獻《Very Deep Learning Convolutional Neural Networks for Large-Scale Image Recognition》提出。它們的貢獻是具有非常小(3×3)的網絡架構可被訓練增加到很深的層次(16-19層)並且能夠在ImageNet分類挑戰上獲得最新的分類。

之前,在深度學習文獻的網絡架構中使用混合核大小:CNN的第一層通常核大小為7×7或11×11,之後的層次中核大小逐漸減小到5×5,最後僅在網絡的非常深的層次上使用3×3的核。

VGGNet獨特的原因是它在整個網絡架構中使用唯一的3×3的核。任何時候你看到一個網絡架構整個都用3×3的核,你可以認為它來自於VGGNet。直接看VGGNet的整個16層或19層目前CNN的介紹來說太高深了,對於更細節的VGG16或VGG19,看ImageNet Bundle的第11章。

我們將回顧VGGNet的架構構成,且定義CNN要實現該架構必須滿足的特性。之後,我們實現一個VGGNet的變種——MiniVGGNet。這個網絡也將演示如何使用兩個重要的層——BN層和Dropout層。

1 VGG家族

VGG家族的CNN構成主要有兩個部分:

(1)所有的CONV層僅使用3×3的核;

(2)在應用POOL操作之前堆疊多個CONV=>RELU層(隨著網絡越深,連續的CONV=>RELU數目通常減少)。

1.1 (Mini)VGG架構

在ShallowNet和LeNet網絡中我們應用了一系列CONV=>RELU=>POOL層。但是,在VGGNet中,我們在應用單個POOL層之前將堆疊多個CONV=>RELU層。這個操作允許網絡在通過POOL層對輸入空間尺寸做下采樣之前可以從CONV層中學習到更豐富的特征。

整體上,MiniVGGNet包含CONV => RELU => CONV => RELU => POOL這樣的兩個集合,之後跟著FC => RELU => FC => SOFTMAX層。前兩個CONV層將學習32個3×3的核。後兩個CONV層將學習64個同樣是3×3的核。我們的POOL層將執行2×2核、stride為2×2的max pool操作。我們也將在每個激活層之後跟著BN層並且在POOL和FC層之後跟上Dropout層。

技術分享圖片

表15.1 MiniVGGNet層次表

網絡架構細節見表15.1,網絡的輸入大小為32×32×3,因為我們在CIFAR-10上訓練網絡。再次註意,我們是如何在網絡架構中應用BN層和Dropout層的。應用BN層可以降低過擬合的風險並且增加分類正確率。

2 實現MiniVGGNet

根據網絡藍圖如表15.1,我們使用keras庫實現它。與第14章實現類似,我們在nn.conv子目錄下新建minivggnet.py,作為我們MiniVGGNet的實現。且不要忘記在當前目錄的__init__.py中添加導出的類名MiniVGGNet。

我們通過keras.layers.normalization import BatchNormalization,通過keras.layers.core import Dropout導入丟棄層。在定義類MiniVGGNet中,我們增加了一個變量chanDim表示通道優先順序。因為BN層工作在通道上,我們需要該變量指明BN工作在哪個axis上。

之後的構建模型,根據藍圖一層一層構建即可,註意裏面在構建POOL層時,我們用model.add(MaxPooling2D(pool_size=(2, 2)))而沒有明確的指明stride的2×2大小,在keras中不指定stride時,默認stride大小等於該pool_size大小。我們還註意到model.add(Dropout(0.25))表示當前層的節點以25%的概率不連接到下一層節點上。我們第一模塊的CONV層核大小為32,第二模塊的CONV層核大小為64,即隨著網絡中越深空間輸入尺寸越小,增加核的數目是很常見的操作。最後我們的FC層使用512節點,且註意到我們在兩個FC層之間使用Dropout層,丟棄概率為50%,即在FC層之間通常的Dropout設置為0.5。

3 在CIFAR-10上演示MiniVGGNet

訓練腳本類似於第14章的操作模式:加載CIFAR-10數據集、初始化MiniVGGNet架構、訓練MiniVGGNet、評估網絡性能。

我們創建minivggnet_cifar10.py的腳本,見GitHub。

技術分享圖片

我們首先導入必要的模塊,這裏使用matplotlib後臺用AGG,表明我們將創建一個非交互性的僅保存到磁盤的結果文件,因為在一些通過ssh等遠程登錄的運行中,直接顯示圖片會造成matplotlib錯誤,因此這裏直接使用agg作為使用,表示在訓練完成後,直接把結果保存到磁盤上。

最重要的初始化優化器語句opt = SGD(lr=0.01, decay=0.01 / 40, momentum=0.9, nesterov=True),表示我們學習率α=0.01並且動量參數γ=0.9。設置nesterov=True表明我們在SGD中使用Nesterov加速。這裏我們還使用一個特別的參數decay=0.01/40,用於隨著時間緩慢的降低學習率參數。就像在下一章討論的,降低學習率在降低過擬合和增加分類正確率方面很有用——學習率越小,權重更新越小。通常,decay的設置為學習率除以epoch數目。這裏的epoch設置為40,初始學習率為lr=0.01,即設置decay=0.01/40。我們在評估MiniVGGNe時,采用兩種方式,即一個具有BN層,另一個不具有BN層。

                                    技術分享圖片

圖15.2 具有BN層和不具有BN層損失對比圖

3.1 具有BN層

我們首先在chapter15/下創建一個輸入結果保存文件:output/cifar10_minivggnet_with_bn.png。然後直接執行python minivggnet_cifar10.py --output output/cifar10_minivggnet_with_bn.png即可開始訓練,且將最終結果保存到該文件中。

結果如圖15.2左圖所示,可看到具有BN層的MiniVGGNet分類正確率大約在83%左右,這個結果要比ShallowNet的60%的分類正確率高很多。

3.2 不具有BN層

我們將nn/conv/minivggnet.py文件中的所有BN層註釋掉,即獲得不具有BN層的MiniVGGNet網絡模型。之後我們創建保存的圖片文件:output/cifar10_minivggnet_without_bn.png。然後執行python minivggnet_cifar10.py --output output/cifar10_minivggnet_without_bn.png即可重新訓練不具有BN層的結果。

訓練結果如圖15.2右圖所示。我們註意到不具有BN層的訓練要比具有BN層訓練的快,但是訓練完成後,它的驗證正確率將只有79%左右。

通過上述圖對比,我們可看到BN層的影響:在不具有BN層的圖表中驗證損失在30epoch後將增加,這表明網絡在訓練數據上過擬合了。我們還看到在25epoch後,驗證損失變得比較平穩了。另一方面,具有BN層的MiniVGGNet更穩定。盡管損失和精確率在35epoch之前不平穩,但是它沒有過擬合。這也是為什麽建議在網絡中使用BN層的原因。

4 總結

本章討論了CNNs的VGG家族。一個CNN可考慮是類VGG網絡,如果(1)它不管網絡多深,只使用3×3核;(2)在應用POOL層之前,堆疊多個CONV=>RELU層。

之後我們實現了一個類VGG網絡——MiniVGGNet,這個網絡考慮兩個((CONV=>RELU)*2)=>POOL的結構,之後跟著FC => RELU => FC => SOFTMAX結構,我們也在每個激活層後跟著BN層以及在每個POOL核FC層後跟著Dropout層。

之後,我們在CIFAR-10上評估MiniVGGNet性能,結果建議在訓練自己的網絡時加入BN層。

第15章 MiniVGGNet:更深的CNNs