第11章 卷積神經網絡(CNNs)


第11章 卷積神經網絡(CNNs)

      我們回顧了整個機器學習和深度學習知識,現在我們學習CNNs(Convolutional Neural Networks)以及它在深度學習中的作用。在傳統的前饋神經網絡中,輸入層的每一個神經元都與下一層的每一個輸入神經元相連,我們稱之為FC(fully-connected,全連接)層。但是,在CNNs中,我們直到網絡中的最后一層才使用FC層。因此,我們可以將CNN定義為神經網絡,該網絡在專用的“卷積(convolutional)”層中交換,代替網絡中至少一個層的“FC”層。

      一個激活函數例如ReLU將緊跟在卷積層后處理,且這種卷積==>激活的處理過程將持續(中間伴隨着其它層類型的處理,這些層幫助減少輸入值的長寬大小且幫助降低過擬合)直到到達網絡的最后層次,然后我們實施一到兩個FC層獲得最終的輸出分類。

      CNNs的每一層通常應用不同的過濾器集合,通常幾百上千個,將這些結果組合起來,輸入到下一層。在訓練過程中,CNN自動的學習這些過濾器的值。

      在圖像分類背景下,我們的CNN可以用來:在第一層中從原始像素數據檢測邊緣、在第二層中使用這些邊緣檢測形狀、在網絡的更高層中使用這些形狀檢測更高級的特征,如面部結構、汽車部件等。在CNN的最后一層,使用這些更高層的特征做出關於圖像內容的預測。

實際上CNN給我們帶來兩個關鍵好處:局部不變性和組合性(local invariance and compositionality)。局部不變性的概念允許我們將分類一副圖像看作是包含特定目標的過程,而不管圖像中該目標出現在什么地方。我們通過“pooling layer”的使用來獲得這種局部不變性,pooling層用對特定過濾器的高響應來標識輸入卷(input volume)的區域。第二個優勢是組合性,每個過濾器都將底層特征的部分組合到一起構成高層表示,這種組合允許我們的網絡可以在網絡的更深層次上學習到更富有的特征。例如,我們的網絡可以從原始像素構建邊緣、由邊緣構建形狀、由形狀構建復雜物體,所有這些都在訓練過程中自然地自動發生。這種從底層構建高層特征的概念正是CNN應用於計算機視覺的強大原因。

剩下內容,將討論什么是卷積以及它在深度學習中的作用。之后將討論CNN的構建塊:層(layers)和你用於構建自己的CNN的層的類型。我們將通過查看常見的模式來總結本章,這些模式用於堆疊這些構建塊以創建CNN架構,這些架構在一組不同的圖像分類任務中表現良好。

在本章之后,我們可以(1)理解CNN、理解構建一個CNN的思考過程(2)使用一些CNN“配方”構建自己的網絡架構。

1         理解卷積

本節中,我們提出了一些問題包括什么是圖像卷積?它們能做什么?為什么我們要使用它?怎樣將它們應用到圖像上?卷積在深度學習上有什么作用?

對圖像進行模糊/平滑、邊緣檢測、銳化…這些都是卷積,卷積是計算機視覺和圖像處理中最重要、最基礎的構建塊之一。

在深度學習領域中,圖像卷積就是兩個矩陣對應元素相乘、然后求和。這就是卷積了:取兩個矩陣(具有相同維度)、對應元素相乘、結果加到一起。在接下來我們將學到卷積、核(kernel)以及如何應用到CNN中。

1.1 卷積與互相關

具有計算機視覺和圖像處理背景的讀者可能將我描述的卷積作為互相關(cross-correlation)了,使用互相關代替卷積是在實際設計中使用的。一個二維的輸入圖像I和二維的核K的卷積為:

 

但是幾乎所有的機器學習和深度學習庫都使用簡化的互相關函數:

 

這兩個的差異僅僅是在應用到圖像上時,如何調整卷積核K,當互相關時,我們不需要翻轉K,而卷積時需要翻轉。

注意,在幾乎所有深度學習庫中都使用簡化的互相關操作且稱為卷積,這里我們也將使用這種術語約定。

1.2 大矩陣和小矩陣類比

一副圖像是多維矩陣。我們的圖像具有寬度width(列column)和高度height(行row)就像矩陣一樣,但是圖像還有深度deep即圖像的通道channels。考慮到這些,我們稱圖像是大矩陣、稱核kernel或卷積矩陣為小矩陣,小矩陣用於模糊、銳化、邊緣檢測和其它處理函數。特別的,小矩陣“坐”在大圖像上部,並且從左往右、從上往下滑動,在原始圖像的每一個(x, y)坐標上應用數學操作(如卷積)。

手動設計核來獲得不同的圖像處理函數是正常的。實際上,你可能熟悉模糊blurring (average smoothing, Gaussian smoothing, median smoothing, etc.), edge detection (Laplacian, Sobel, Scharr, Prewitt, etc.), and sharpening,所有這些都是用於手動設計的專門用於執行特定的功能。

那么,有自動學習這些類型過濾器的方式嗎?甚至使用這些過濾器用於圖像分類和目標檢測嗎?答案是肯定的,但在我們在那之前先更深入的學習核與卷積的知識。

1.3 Kernels核

 

圖1 大矩陣與小矩陣示例

現在考慮如圖1所示的圖像大矩陣和核小矩陣的例子,核(紅色區域)沿着原始圖像從左往右、從上到下滑動。在原始圖像的每一個(x,y)坐標處,我們停止並檢查位於圖像核中心的像素的鄰域。之后取這個像素的鄰域、將它們與核卷積、然后獲得一個單個輸出值。這個輸出值位於輸出圖像的相同的(x,y)坐標處作為核的中心。

下面我們先看看核看起來是什么:

上面我們定義了一個3×3的核。核可以是任意的M×N大小,暗含了M和N都為奇整數。(應用於深度學習和CNNs的核大小一般都是N×N的核,這允許我們可以最有效的方式利用矩陣乘法。)

使用奇數核大小是確保在圖像中心有一個有效的坐標(x,y),如圖2所示,在右側核中,中心坐標0.5,0.5,這在圖像中是不存在的。

 

圖2 奇數核和偶數核示例

1.4 卷積手動計算示例

在圖像處理中,卷積需要三個參數:

(1)一個輸入圖像;

(2)將應用到圖像上的核矩陣;

(3)存儲卷積后的輸出結果的輸出圖像。

卷積的計算很簡單,即:

(1)從原始圖像選擇(x,y)坐標

(2)將核的中心放在該(x,y)坐標處

(3)將核與輸入圖像的對應坐標一一相乘,然后將這些乘積求和成為一個值。這些乘積求和的操作成為核輸出(kernel output)。

(4)在輸出圖像上的與(1)中相同的(x,y)坐標處存儲核輸出。

例如,將上面定義的卷積核與圖1中所在區域卷積:

 

因此:

 

即在該卷積之后,我們設置輸出圖像O在(i,j)處的值Oi,j為132。這就是卷積計算了,卷就就是卷積核與卷積核在原始圖像的覆蓋區域的元素一一對應相乘求和的結果。

1.5 卷積python計算示例

為了更好地理解卷積,我們看實際代碼如何處理。源代碼不僅可以幫助來理解卷積計算是怎樣的,還可以用於理解在訓練CNN時卷積做了什么。現在可從git上下載chapter11/convolutions.py的文件,瀏覽代碼。

通過執行python convolutions.py –image home.img即可。通過點擊后可依次顯示不同的模糊、銳化、邊緣檢測等手動卷積效果。

其中,除了手動設計的卷積計算,作者還給出了cv2.fiter2D(image, -1, K)的opencv調用結果用於對比查看卷積效果。

1.6 深度學習中卷積的作用

就像在上節中演示的,手動設計的卷積核都是很好地,但是有沒有一種方式可以自動學習這些卷積核的參數呢?那么定義一種可以在輸入圖像上尋找並且可以最終學習到這些操作類型的機器學習算法是可能的嗎?答案就是本書關注的算法:CNNs。

通過實施卷積過濾器、非線性激活函數、pooling和BP算法,CNNs可以在網絡的較低級層上學習到可以檢測邊緣和類似塊的結構的過濾器,之后使用這些邊緣和結構作為“構建塊”,最終在網絡的較深層次上檢測到高級對象(例如人臉、貓、狗等等)。

使用較低層學習到更高層特性的過程就是前面介紹的圖像的組合性。但是CNN如何精確的做到的?答案是以有目的的方式堆疊一組特定的層。下一節,我們將討論這些層的類型,並且看一些廣泛用於許多圖像分類任務中的層堆疊模式。

 

2         CNN構建塊

就像在第10章介紹的,神經網絡接收一個輸入圖像/特征向量(一個輸入節點對應一個入口)且將它們通過一個通常是非線性激活函數的隱藏層傳輸。每個隱藏層也由多個神經元構成,且每一個神經元都全連接到前一層的神經元上。神經網絡的最后一層也是全連接的且通常表示網絡的最終分類輸出。但是,這種傳統神經網絡通常工作在原始像素上,隨着像素數目增加,輸入節點數目急劇增加,且網絡不能很好地分類性能。

相反, 我們可以使用利用輸入圖像結構的CNNs且定義一個更好的網絡結構。不像標准的神經網絡,CNNs的層組織成3D卷(volume)的三維形式:寬度、高度、深度(即圖像的寬、高、通道,深度就是卷的第三個維度)。例如在CIFAR-10數據集中的圖像:輸入卷有32*32*3的維度。后續層中的神經元只會連接到其前面層的一個小部分區域(而不是標准神經網絡的全連通結構)——我們稱之為局部連通(local connectivity),它使我們能夠在網絡中保存大量的參數。最后輸出層將是一個1×1×N的卷,表示圖像分類成類別分數的單個向量。在CIFAR-10例子中,N=10,即最后一層是一個1×1×10的卷。

2.1 層類型

存在許多層類型用於CNNs,但是你最可能見到的是:

 

將這些層以特定的方式堆疊到一起就是CNN。我們常用一個文本圖表描述一個CNN:INPUT => CONV => RELU => FC => SOFTMAX。這里描述了一個輸入圖像應用卷積層、之后激活層、全連接層,然后進入softmax分類器獲得最終的分類概率。Softmax激活層常常在網絡圖表中忽略,因為假定是跟在最后的FC層之后的。

在這些層中,CONV和FC(以及較少使用的BN)是唯一包含在訓練過程中學習的參數的層。RELU和DO層本身不考慮作為真正的“層”,包含在網絡圖表中只是為了使架構更清晰。Pool層與CON和FC層同等重要,因為它對一副圖像的空間維度的改變具有重大影響。CONV、RELU、POOL和FC層在構建網絡架構時是最重要的層。

2.2 Convolutional layer(卷積層)

CONV層是構建CNN的核心層。CONV層參數由K個可學習的過濾器(核)構成,每個核都有寬和高,通常相同。這些核很小,但是通常延伸到volume的整個深度上(即這些二維核計算時是在整個卷上計算?)。

對於CNN的輸入,depth通常是圖像的通道數。對於網絡中更深層次的卷,其深度將是應用在上一層的過濾器的數量(我的理解是,后一層的輸入深度為上一層卷積核的數量,當然這個卷積核的數量為多少根據具體CNN框架是具體問題具體分析的)。如圖6所示,K個核的每一個核分別在輸入圖像上滑動計算卷積,和的輸出值就是就是一個2D激活圖(activation map)。

 

圖6 激活圖計算示意圖

圖6中左圖表示要作用到輸入圖上的K個核,中圖表示每個核都與輸入圖滑動計算卷積,右圖表示每個核都輸出一個激活圖。在應用K個核作用到輸入卷之后,我們計算得到了K個激活圖,我們將這K個激活圖沿着深度維度方向堆疊到一起構成了最終的輸出卷,如圖7所示,

 

圖7 獲得K個激活圖,堆疊到一起構成網絡下一層的輸入卷

      輸出卷的每一個輸入都是神經元的輸出,神經元只“看到”輸入的一小塊區域。通過這種方式,網絡“學習”過濾器,當他們在輸入卷中看到給定的空間位置上的特定類型的特征時,就會激活。在網絡的較低層,當過濾器看到類似邊或角的區域可能就會激活。那么,在網絡的較高層,當存在高級特征如人臉的部分、狗的爪子、車的輪子時,過濾器就會激活。激活的概念就是當神經元在輸入圖像中看到特定模式時就“興奮”且“激活”了。

      將小的過濾器與大的輸入卷作卷積的概念在CNNs中有特殊的含義——具體的說,就是神經元的局部連接性(local connectivity)和感受野(receptive field)。在處理圖像時,將當前卷中的神經元與上一個卷中的所有神經元連接起來往往是不現實的——有太多的連接、太多的權重,使得無法在空間尺寸較大的圖像上訓練深層網絡。相反,在利用CNNs時,我們選擇將每個神經元連接到輸入卷的局部區域——我們稱這個局部區域的大小為神經元的感受野(或簡稱為變量F)。

      例如,在CIFAR-10中輸入卷是一個32×32×3的輸入大小,即每個圖像有32像素寬、32像素高和3深度(即RGB通道數目)。如果感受野是3×3大小,那么在CONV層中的每個神經元將連接到這個圖像的一個3×3的局部區域,總共有3×3×3=27個權重值(記住,過濾器的深度延伸到輸入圖像的整個深度,這個例子為3個通道)。

      現在,讓我們假設我們的輸入卷的空間尺寸已經縮小到一個較小的尺寸,但是我們的深度現在更大了,因為在網絡中使用了更多的過濾器,所以現在的卷尺寸是16×16×94。再次假定感受野的大小為3×3,那么在CONV層中的每個神經元對這個輸入卷將總共有3×3×94=846個連接。簡單的說,感受野F是過濾器的大小,即F×F的核與輸入卷進行卷積。(注意注意注意!!!!這里說對於深度94,那么感受野3×3時,一個通道對應一個核,所以總共有3×3×94=846個參數,但是在現代CNN中,利用權值共享,即對於通道維度上的同一個感受野使用一個核代替所有通道上的核,即這94個核可由1個3×3的核代替,那么此時由於利用權值共享,我們的參數只有3×3=9個權值了。這應該在作者的后續書籍中會闡述,這里僅根據自己已知的理解,添加在這里。但是根據作者書籍中學到這里,我們默認還是以每個通道對應一個核的解釋進行論述,慢慢深入理解。)

      此時,我們闡述了神經元的連接性,但是沒有涉及輸出卷的尺寸大小。有三個參數控制輸出卷的大小:depth、stride和zero-padding尺寸。

(1)depth

      輸出卷的深度控制在CONV層中連接到輸入卷的局部區域的神經元(即過濾器)的數目。對於一個給定的CONV層,激活層的深度就是K,或者僅僅是當前層中我們要學習的過濾器的數目。“查看”輸入的相同(x,y)位置的一組過濾器稱為深度列(depth column)。

      (2)stride

      前面描述的小矩陣在大矩陣上滑動,這種描述類似於滑動窗口(sliding window)。在卷積描述中,我們通常每次滑動都只移動一步即一個像素,然后在感受野范圍內使用K個卷積核計算深度卷,且產生一個3D卷。當創建CONV層時,通常使用一個stride步長(即滑動步長)稱為S,大小一般S=1或S=2。較小的stride,將產生重疊的感受野、較大的輸出卷;較大的stride,將產生不重疊的感受野、較小的輸出卷。如表1與2所示的stride為1和2時的輸出卷示例:

      

               表1 輸入5×5,核3×3                        表2 左stride=1,右stride=2

我們可以看到,僅僅改變stride大小就可以改變輸入卷的空間維度。根據后續內容,卷積層和pooling層是降低輸入空間大小的主要方法。

(3)zero-padding

Pad即修補的意思,這里指的是在圖像的四周“pad”上像素,可簡化后續處理,zero-padding即在圖像周圍填上值為0的額外像素。使用zero-padding,通過這種技術可以使我們輸出卷的大小與輸入卷大小一致。Pad的大小通常用參數P表示。

當我們開始研究深度CNN體系結構時,這種技術尤其重要,這些體系結構在彼此之間應用了多個CONV過濾器。例如在表1中當S=1時,我們看到圖中的左側輸出為3×3,要比輸入卷5×5要小。如果我們在輸入卷上使P=1,即在輸入卷上下左右各補上1使之成為7×7的卷,則此時S=1時的輸出卷為表3所示:

 

表3 3×3應用到pad=1的7×7卷積示例

沒有zero padding,輸入卷的空間維度將快速減少,即我們不能訓練很深的網絡(因為輸入卷將太小而不能學習到有用的模式形式)。

將這些參數結合到一起,我們可以計算輸出卷的大小作為數據卷大小(W,輸入卷大小,通常為正方形)、感受野F、stride S、zero-pad大小P的函數。為了構建一個有效的CONC層,我們需要確保下述公式為整數,如果它不是一個整數,那么這些stride就被錯誤地設定了,神經元就不能被平鋪成對稱的大小:

((W – F + 2P) / S) + 1

舉個例子,考慮AlexNet體系結構的第一層,它贏得了2012年ImageNet分類的挑戰,對當前應用到圖像分類的深度學習的熱潮負有巨大的責任。論文[1]中,描述了如圖8所示的CNN架構:

 

圖8 文中描述的原始的AlexNet架構圖

注意這里的第一層大小為224×224,由上述公式這是不可能的,因為(224 – 11 + 2*0) / 4 + 1 = 54.25不是一個整數,這很可能會對初學者造成困惑,作者最可能使用的輸入大小為227×227,此時((227-11 +2(0))/4) + 1 = 55,正好是后一層的輸入卷大小。這樣的錯誤比你想象的更常見,所以在從出版物中實現CNNs時,一定要自己檢查參數,而不是簡單地假設列出的參數是正確的。

作為總結,CONV層和Karpathy[2]描述的一樣優雅:

l  接受一個大小為Winput×Hinput×Dinput的輸入卷(輸入大小通常為正方形,即Winput = Hinput)。

l  需要4個參數:

(1)過濾器K的大小(控制輸出卷的深度)

(2)感受野大小F(用於卷積的K個核的大小,通常正方形,即為F×F大小)

(3)步幅stride:S

(4)zero-padding大小:P

l  之后為卷積層的輸出即Woutput×Houtput×Doutput這里:

——Woutput = ((Winput - F +2P) / S) + 1
——Houtput = ((Hinput - F +2P) / S) + 1
——Doutput = K

      我們將在3.1看到這些參數的設置。

2.3 Activation layer(激活層)

在CNN的每一個CONV層之后,我們將應用一個非線性激活層(activation layer),例如第10章中的ReLU、ELU或其它任何形式的Leaky ReLU變體。在網絡圖表中激活層通常用RELU表示,或僅僅ACT表示。激活層不是“層”技術(因為在激活層內沒有需要學習的參數/權重)且有時候會在網絡圖表中省去,因為通常假定激活層緊跟在CONV層之后。作者傾向於在網絡圖表中明確的顯示激活層,因為這樣可以使網絡中什么時候和怎么用激活函數很清晰,如下面的網絡圖表:INPUT => CONV => RELU => FC。

激活層接受大小為Winput×Hinput×Dinput的輸入卷,然后應用到激活函數,如圖9所示。由於激活層功能是像素一一對應處理的方式(in an element-wise manner),所以激活層的輸出卷大小與輸入卷大小相同:Winput = Woutput,Hinput = Houtput,Dinput = Doutput

 

圖9 應用ReLU函數為max(0, x)的示例

2.4 Pooling layer(池化層)

有兩種方式可以降低輸入卷的大小:stride>1的CONV層和POOL層。在CNN架構中通常在CONV層之間插入POOL層:

INPUT => CONV => RELU => POOL => CONV => RELU => POOL => FC

POOL層的主要功能是逐步縮小輸入卷的空間尺寸大小(例如寬和高)。做這個可以降低網絡中參數和計算的大小,即控制過擬合。

池化層使用最大(max)或平均(average)函數獨立地操作輸入的每個深度片(depth slice)。最大池化通常在CNN架構的中間使用來降低空間大小,而平均池化通常用於網絡(例如GoogLeNet, SqueezeNet, ResNet)的最后層用來希望避免完全使用FC層。池化層最常見的類型是最大池化,盡管隨着更奇異的微架構的引入,這種趨勢正在改變。

通常使用的池化大小為2×2,盡管使用大的輸入圖像(像素大於200)的更深的CNN可能在網絡早期使用3×3池化。我們通常設置的stride大小為S=1或S=2。圖10是應用2×2大小最大池化和S=1的例子,注意這里對每個2×2的塊我們取最大值,然后滑動一步,繼續這種操作,即獲得一個3×3的輸出。

 

圖10 max池化示例

我們可以通過增加stride大小進一步降低輸入卷的大小,例如圖10中stride=2時的例子中輸出卷大小為2×2,通過每次滑動步幅為2。

作為總結,池化層接受大小為Winput×Hinput×Dinput的輸入卷,該層通常需要兩個參數:

l  感受野大小F(稱為池化大小(pool size))

l  滑動步幅stride大小S

應用池化操作獲得一個大小為Woutput×Houtput×Doutput的輸出卷:

l  Woutput = ((Winput - F) / S) + 1

l  Houtput = ((Hinput - F) / S) + 1

l  Doutput = Dinput

現在的池化操作通常有:最大池化、平均池化和全局池化。實際中,常見到兩種最大池化類型:

l  類型1:F=3, S=2稱為重疊池化(overlap pooling)通常應用到具有大空間維度的輸入圖像上。

l  類型2:F=2, S=2稱為非重疊池化(non-overlap pooling),這是最常見的池化類型且常應用到更小空間維度的圖像上。

對於更小網絡輸入圖像(例如32—64像素范圍內)的網絡架構中可能見到F=2, S=1的池化類型。

CONV還是POOL?

在2014年的文章[3]中,作者建議完全丟棄池化層並且僅僅應用具有大stride的CONV層對卷的空間維度進行下采樣處理(downsampling,即降低維度?)。這個工作在不同數據集的演示中證明很好,包括CIFAR-10(小圖像、少類別數目)和ImageNet(大輸入圖像、多類別數目)。這種趨勢在ResNet也可得到驗證。

如果可以避免FC層,在網絡架構的中間不使用池化層並且僅在網絡的末端使用平均池化正變得越來越常見。可能在將來的CNNs將不會有池化層,但是在此時,我們學習它、學些它的作用、應用到我們的網絡架構中是很重要的。

2.5  Full-connected layers(全連接層)

FC層中的神經元與前一層的激活全部相連,因為它是第10章討論的標准的前饋神經網絡。FC層常常在網絡層次的最后。在應用softmax分類器之前通常使用一到兩個FC層,例如:

INPUT => CONV => RELU => POOL => CONV => RELU => POOL => FC => FC

這里我們在應用softmax分類器之前使用了2個FC層,softmax分類器將計算每個類別的最終輸出概率。

2.6  Bach Normalization(批歸一化)

第一次在文獻[4]中介紹,批歸一化層(簡稱為BN層),用於在傳遞到網絡的下一層之前歸一化給定輸入卷的激活(activation)。

如果我們考慮x是我們激活的mini-batch,那么我們可以通過下式計算歸一化的值:

 

在訓練過程中,我們可以在每一個mini-batch β中計算

 

我們這里設置ε為一個小的正數例如1e-7來避免平方根為0。應用這個等式表明離開BN層的激活將具有近似零均值、單位方差。

在測試過程中,我們以在訓練過程中計算的運行平均代替mini-batch 。這確保了我們傳遞圖片通過網絡仍能獲得精確的預測,而不會被來自在訓練時間貫穿網絡的最終mini-batch的偏離(biased)。

實踐證明,BN對於減少訓練神經網絡的epoch數目是非常有效的。BN還有一個幫助穩定(stabilize)訓練的額外好處,允許學習率和正則化強度的大的變化。當然,使用BN並不能減輕調整這些參數的需要,但是,這將通過使學習率和正則化程度降低、更易調整,從而使你的生活變得更加輕松。當在網絡中使用BN時,你還會發現最終損失更低、損失曲線更穩定。BN的最大缺點是它增加了訓練網絡的時間(盡管它降低了epoch次數)。

我建議在幾乎所有情況下使用BN,因為它確實有很大的不同。就像本書后面所說,與相同的不使用BN的網絡架構相比,在網絡架構中使用BN能幫助我們防止過擬合並且能夠以更少的epoch次數獲得極大的更高的分類精確度。

那么,BN層將用到哪個地方呢?在最早的文章[4]中他們將BN層放在激活層之前,基於這種機制,利用BN的網絡架構像這樣:

INPUT => CONV => BN => RELU ...

但是從統計學的角度看,這種BN層機制是沒有意義的。這種BN層對CONV層之后的輸出特征進行歸一化,這個特征有可能是負的,也就是它可能被之后的ReLU層截斷為0。那么我們將BN處理后的具有負值的零中心特性的BN結果輸入到POOL層,則POOL層將會破壞我們應用BN層的零均值、單位方差的初衷。

因此,我們將BN層放在ReLU層之后,文獻[5]確認將BN層放在激活層之后在幾乎所有場景下將獲得更高的精確度和更低的損失。那么這種結構類似於:INPUT => CONV => RELU => BN ...。

在作者的CNN實驗中,這種放置確實能夠稍微能夠獲得更高的精確度和更低的損失。在后面的實驗中將對此說明。

2.7  Dropout(丟棄)

我們討論的最后的層類型是Dropout。Dropout實際上是正則化的一種形式,目的是通過增加測試精確度可能降低訓練精確度來防止過擬合。在我們訓練集的每一次mini-batch中,我們以dropout層以概率p隨機地將網絡架構中從前一層到后一層的連接斷開。圖11為在給定的mini-batch中在兩個FC層之間以概率p=0.5隨機斷開的示例:

圖11 隨機dropout與沒有dropout的示例

在這次mini-batch的前向和后向計算完畢后,我們重新連接被dropout斷開的連接,然后同樣的另一個連接將開始dropout。

我們應用dropout降低過擬合的原因是明確的在訓練時間內改變了網絡架構。隨機丟棄連接確保了當呈現一個給定模式時網絡中沒有單個節點負責“激活”。相反,dropout確保了當呈現一個類似輸入時有多個、冗余節點將激活,這反過來使我們的模型更具泛化能力。

最常見的是將p=0.5的dropout層放在網絡架構的FC層之間,這里最后的FC層假定是我們的softmax分類器:

 

但是就像在3.2中討論的,我們也可能以更小的概率(例如p=0.10-0.25)將dropout放在網絡的早期(通常跟隨下采樣,或者通過max pool或者CONV)。

 

3         常見的架構和訓練模式

就像本章說的,CNN通常由4種主要層構成:CONV、ReLU、POOL、FC。取這些層且將它們按照特定模式堆疊在一起就形成了一個特定CNN架構。

CONV層和FC層(和BN)是唯一的實際可以學習參數的網絡的層,其它層僅僅執行給定的功能。激活層和dropout層技術上不是層,但是常常包含在CNN架構圖表中,是為了使操作更清晰明確,在這里我們也將使用這種描述。

3.1  層模式

到目前為止,最常見的CNN架構是堆疊一些CONV層和ReLU層,后面跟着POOL操作。我們重復這種次序直到卷的寬度和高度足夠小,在這個點上我們應用一到兩個FC層,那么我們可以獲得最常見的CNN架構:

 

這里的*表示一個或多個,?表示可選的操作。通常的選擇為:

l  0 <= N <= 3

l  M >= 0

l  0 <= K <= 2

下面是我們見到的一些CNN架構的模式例子:

 

在第12章我們回顧一個只包含一個卷積層的非常淺的CNN:

 

下面是一個類似AlexNet的CNN架構:

 

對於更深的網絡架構如VGGNet,我們可能在POOL之前堆疊多個CONV層,如:

 

一般來說,我們應用很深的網絡架構時當我們(1)有大量標記的訓練數據(2)分類問題具有足夠的挑戰。在應用一個POOL層之前堆疊多個CONV層,是在執行破壞性的池化操作之前,允許CONV層發展出(develop)更復雜的特性。

就像在ImageNet Bundle中討論的,有很多從這些模式中推導出的奇異的網絡架構,並且反過來創建了它們自己的模式。一些架構完全移除了POOL層操作,依賴CONV層對卷進行下采樣,之后在網絡的最后應用平均池化而不是FC層來獲得到softmax分類器的輸入。

如GoogLeNet、ResNet和SqueezeNet的網絡架構時這種模式的強大的示例並且示例說明了如何移除FC層導致較少的參數和更快的訓練時間。

這些類型的網絡架構也在通道維度上堆疊和連接過濾器:GoogLeNet應用1×1、3×3和5×5的過濾器並且將它們在通道維度上堆疊在一起來學習多層特征。(這里,我認為是過濾器在每個通道上是不同的。)即這些架構更奇異也更高級。

如果你對這些更高級的CNN架構感興趣,去看Practitioner Bundle;否則,你希望堅持這種基本的層堆疊模式直到你學習到了深度學習的基礎。

3.2  經驗法則

本節中我將回顧在構建自己的CNNs時的常見的經驗法則。首先,輸入層的的圖像應當是正方形。使用正方形輸入可以利用線性代數優化庫。常見的輸入層大小包括32 × 32、64 × 64、 96 × 96、 224 × 224、227 × 227和229 × 229(這里為了說明方便省略了通道數量)。

第二,輸入層在應用第一次CONV操作之后還應該被2整除。你可以通過調整過濾器大小和步幅stride大小完成。“被2整除法則”使我們網絡中的空間輸入以一種有效的方式通過POOL操作可被方便的下采樣。

一般來說,你的CONV層應該使用較小的過濾器尺寸如3×3和5×5。微小的1×1過濾器用於學習局部特征,但是僅用在更高級的網絡架構中。較大的過濾器尺寸如7×7和11×11可用於網絡的第一個CONV層(為了降低空間輸入尺寸,假定你的圖像大於200×200像素);但是在這個初始化CONV層之后,過濾器尺寸應該急劇降低,否則你降低你的卷的空間尺寸將太快。

對於CONV層,你常使用步幅S=1,至少對於較小的空間輸入卷來說(接收大的輸入卷的網絡可以在第一層CONV層使用S>=2)。使用S=1使我們的CONV層學習過濾器而POOL層負責下采樣。但是注意,並不是所有網絡都是這種模式,一些網絡架構跳過了max pooling操作而且利用CONV層stride來降低卷尺寸。

作者個人的建議是傾向於將zero-padding應用到CONV層來確保輸出維度尺寸匹配輸入維度尺寸,這條規則唯一的例外是如果我們想通過卷積有目的降低空間尺寸。在堆疊多個CONV層時在每個輸入都應用zero-padding,這在實際中被證明可以提高分類精確度。就像本書后面介紹的,keras庫可以自動計算zero-padding,使得構建CNN架構更簡單。

作者的第二個建議是使用POOL層(而不是CONV層)來降低輸入的空間尺寸,至少直到你能在構建自己的CNN架構中更有經驗。一旦你到達這一步,你就可以開始實施CONV層來降低空間輸入尺寸並且嘗試從你的架構中移除max pooling。最常見的,你將看到用2×2感受野尺寸和步幅S=2的max pooling,你也可能見到3×3的感受野尺寸。但是對於尺寸大於3的感受野大小是極其不常見的因為它會極大的破壞輸入。

BN層在訓練你的CNN時會多花費2~3倍的時間,但是作者建議在幾乎所有場景下都使用BN層。盡管BN確實增加了訓練時間,但是它傾向於“穩定”訓練,能夠更簡單的調整其它超參數(當然,會有一些例外,作者將在ImageNet Bundle中詳細描述這種例外架構)。作者將BN放在激活層之后,將BN插入到上面描述的常見的層模式:

 

你不需要在softmax分類器之前應用BN,因為在此時我們假定我們的網絡已經在網絡的早期學習到了有差別的特征。

DO層通常以50%的丟棄概率應用在FC層之間,你應該在你創建的幾乎每一個架構中應用dropout。作者也喜歡在POOL層和CONV層之間包含dropout層(以非常小的概率,10%~25%),盡管這種方式不常見。由於CONV層的局部連接性,丟棄在這里不是很有效,但是作者發現它對克服過擬合很有幫助。

在充分熟悉這些傳統的構建CNNs的方法之后,我們將在ImageNet Bundle中探索更高級的架構技術。

4         CNNs對轉換、旋轉、縮放具有不變性嗎?

通常的問題是,CNNs對轉換(translation)、旋轉(rotation)、縮放(scale)的變化具有不變性嗎?為什么CNNs具有如此強大的圖像分類能力?為了回答這個問題,我們首先需要區分網絡中的單個過濾器和最終經過訓練的網絡。CNN中的單個濾波器對圖像旋轉方式的變化並非不變的,我們將在ImageNet Bundle中的第12章進行論證。

但是一個CNN作為一個整體可以學習到當一個模式呈現在一個特定的方向時可以激活的過濾器。如圖12所示:

 

圖12 CNN可學習到旋轉變化時的過濾器

      我們看到存在於CNN中底部的數字9和CNN學到的一些中部的過濾器。圖12左邊的旋轉10°左右的輸入數字9被網絡中的的一個過濾器學習到,該過濾器將被“點燃”且產生一個強的激活。這個大的激活值將在POOL層捕獲並最終反映到最終分類上。類似的過程反映到圖12右側,有個近似旋轉45°的數字9將被另一個過濾器捕獲且進行同樣的類似操作反映到最終分類器上。

      除非你的訓練數據包含所有360°方向上的數字,否則你的CNN就不是真正的旋轉不變性。類似的也是在縮放上,過濾器本身不是縮放不變性的,最可能的是你的CNN已經學會了一套過濾器,當模式以不同的規模存在時,它就會“點燃”。

但是,CNN對轉換不變性是很擅長的。記住,過濾器會在輸入時從左到右和從上到下滑動,當它碰到一個特定的邊緣區域、角落或顏色斑點時會激活。在池化操作過程中,發現了這種大的響應,從而通過一個更大的激活來“擊敗”它的所有鄰居。因此,可以把CNNs看作是“不在乎”一個激活fire的地方,簡單是它fire了——以這種方式,我們在CNN內部自然地進行處理轉換。Therefore, CNNs can be seen as “not caring” exactly where an activation fires, simply that it does fire – and, in this way, we naturally handle translation inside a CNN.

5         下一步

在下一章,我們將基於上面提到的層模式使用keras實現第一個CNN:ShallowNet。在將來的章節里還將討論更深的網絡架構,如LeNet架構以及VGGNet的變體。

6         文獻參考

[1] Alex Krizhevsky, Ilya Sutskever, and Geoffrey E Hinton. “ImageNet Classification with Deep Convolutional Neural Networks”. In: Advances in Neural Information Processing Systems 25. Edited by F. Pereira et al. Curran Associates, Inc., 2012, pages 1097–1105.URL: http://papers.nips.cc/paper/4824-imagenet-classification-withdeep-convolutional-neural-networks.pdf (cited on pages 113, 185, 192, 229).

[2] Andrej Karpathy. Convolutional Networks. http://cs231n.github.io/convolutionalnetworks/ (cited on pages 186, 187, 191)

[3] Jost Tobias Springenberg et al. “Striving for Simplicity: The All Convolutional Net”. In: CoRR abs/1412.6806 (2014). URL: http://arxiv.org/abs/1412.6806 (cited on page 188).

[4] Sergey Ioffe and Christian Szegedy. “Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift”. In: CoRR abs/1502.03167 (2015). URL: http://arxiv.org/abs/1502.03167 (cited on pages 189, 193).

[5] Reddit community contributors. Batch Normalization before or after ReLU? https://www.reddit.com/r/MachineLearning/comments/67gonq/d_batch_normalization_before_or_after_relu/ (cited on page 190).


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM