卷積神經網路就是這麼簡單就能學會
卷積神經網路(CNN)
卷積神經網路和前幾次介紹的神經網路非常相似:它們都是由神經元組成,神經元中有具有學習能力的權重和偏差。每個神經元都得到一些輸入資料,進行內積運算後再進行啟用函式運算。整個網路依舊是一個可導的評分函式:該函式的輸入是原始的影象畫素,輸出是不同類別的評分。在最後一層(往往是全連線層),網路依舊有一個損失函式(比如SVM或Softmax),並且在神經網路中我們實現的各種技巧和要點依舊適用於卷積神經網路。
那麼有哪些地方變化了呢?卷積神經網路的結構基於一個假設,即輸入資料是影象,基於該假設,我們就向結構中添加了一些特有的性質。這些特有屬性使得前向傳播函式實現起來更高效,並且大幅度降低了網路中引數的數量。
用來構建卷積網路的各種層
一個簡單的卷積神經網路是由各種層按照順序排列組成,網路中的每個層使用一個可以微分的函式將啟用資料從一個層傳遞到另一個層。卷積神經網路主要由三種類型的層構成: 卷積層 , 池化(Pooling)層 和 全連線層 (全連線層和常規神經網路中的一樣)。通過將這些層疊加起來,就可以構建一個完整的卷積神經網路。
網路結構例子
這僅僅是個概述,下面會更詳解的介紹細節。一個用於CIFAR-10影象資料分類的卷積神經網路的結構可以是[輸入層-卷積層-ReLU層-池化層-全連線層]。細節如下:
輸入[32x32x3]存有影象的原始畫素值,本例中影象寬高均為32,有3個顏色通道;
-
卷積層 中,神經元與輸入層中的一個區域性區域相連,每個神經元都計算自己與輸入層相連的小區域與自己權重的內積。卷積層會計算所有神經元的輸出。如果我們使用12個濾波器(也叫作核),得到的輸出資料體的維度就是[32x32x12];
-
ReLU層 將會逐個元素地進行啟用函式操作,比如使用以0為閾值的
作為啟用函式。該層對資料尺寸沒有改變,還是[32x32x12];
-
池化層 在在空間維度(寬度和高度)上進行降取樣(downsampling)操作,資料尺寸變為[16x16x12];
-
全連線層 將會計算分類評分,資料尺寸變為[1x1x10],其中10個數字對應的就是CIFAR-10中10個類別的分類評分值。正如其名,全連線層與常規神經網路一樣,其中每個神經元都與前一層中所有神經元相連線。
由此看來,卷積神經網路一層一層地將影象從原始畫素值變換成最終的分類評分值。其中有的層含有引數,有的沒有。具體說來,卷積層和全連線層(CONV/FC)對輸入執行變換操作的時候,不僅會用到啟用函式,還會用到很多引數(神經元的突觸權值和偏差)。而ReLU層和池化層則是進行一個固定不變的函式操作。卷積層和全連線層中的引數會隨著梯度下降被訓練,這樣卷積神經網路計算出的分類評分就能和訓練集中的每個影象的標籤吻合了。
小結 :
-
簡單案例中卷積神經網路的結構,就是一系列的層將輸入資料變換為輸出資料(比如分類評分);
-
卷積神經網路結構中有幾種不同型別的層(目前最流行的有卷積層、全連線層、ReLU層和池化層);
-
每個層的輸入是3D資料,然後使用一個可導的函式將其變換為3D的輸出資料;
-
有的層有引數,有的沒有(卷積層和全連線層有,ReLU層和池化層沒有);
-
有的層有額外的超引數,有的沒有(卷積層、全連線層和池化層有,ReLU層沒有)。
卷積層
卷積層是構建卷積神經網路的核心層,它產生了網路中大部分的計算量。
概述和直觀介紹 :
首先討論的是,在沒有大腦和生物意義上的神經元之類的比喻下,卷積層到底在計算什麼。卷積層的引數是有一些可學習的濾波器集合構成的。每個濾波器在空間上(寬度和高度)都比較小,但是深度和輸入資料一致。
舉例來說,卷積神經網路第一層的一個典型的濾波器的尺寸可以是5x5x3(寬高都是5畫素,深度是3是因為影象應為顏色通道,所以有3的深度)。在前向傳播的時候,讓每個濾波器都在輸入資料的寬度和高度上滑動(更精確地說是卷積),然後計算整個濾波器和輸入資料任一處的內積。當濾波器沿著輸入資料的寬度和高度滑過後,會生成一個2維的啟用圖(activation map),啟用圖給出了在每個空間位置處濾波器的反應。直觀地來說,網路會讓濾波器學習到當它看到某些型別的視覺特徵時就啟用,具體的視覺特徵可能是某些方位上的邊界,或者在第一層上某些顏色的斑點,甚至可以是網路更高層上的蜂巢狀或者車輪狀圖案。
在每個卷積層上,我們會有一整個集合的濾波器(比如12個),每個都會生成一個不同的二維啟用圖。將這些啟用對映在深度方向上層疊起來就生成了輸出資料。
以大腦做比喻 :
如果你喜歡用大腦和生物神經元來做比喻,那麼輸出的3D資料中的每個資料項可以被看做是神經元的一個輸出,而該神經元只觀察輸入資料中的一小部分,並且和空間上左右兩邊的所有神經元共享引數(因為這些數字都是使用同一個濾波器得到的結果)。現在開始討論神經元的連線,它們在空間中的排列,以及它們引數共享的模式。
區域性連線 :
在處理影象這樣的高維度輸入時,讓每個神經元都與前一層中的所有神經元進行全連線是不現實的。相反,我們讓每個神經元只與輸入資料的一個區域性區域連線。該連線的空間大小叫做神經元的 感受野(receptive field) ,它的尺寸是一個超引數(其實就是濾波器的空間尺寸)。
在深度方向上,這個連線的大小總是和輸入量的深度相等。需要再次強調的是,我們對待空間維度(寬和高)與深度維度是不同的:連線在空間(寬高)上是區域性的,但是在深度上總是和輸入資料的深度一致。
左邊 :紅色的是輸入資料體(比如CIFAR-10中的影象),藍色的部分是第一個卷積層中的神經元。卷積層中的每個神經元都只是與輸入資料體的一個區域性在空間上相連,但是與輸入資料體的所有深度維度全部相連(所有顏色通道)。在深度方向上有多個神經元(本例中5個),它們都接受輸入資料的同一塊區域( 感受野 相同)。至於深度列的討論在下文中有。
右邊 :神經網路章節中介紹的神經元保持不變,它們還是計算權重和輸入的內積,然後進行啟用函式運算,只是它們的連線被限制在一個區域性空間。
池化層
通常,在連續的卷積層之間會週期性地插入一個池化層。它的作用是逐漸降低資料體的空間尺寸,這樣的話就能減少網路中引數的數量,使得計算資源耗費變少,也能有效控制過擬合。
池化層使用Max操作,對輸入資料體的每一個深度切片獨立進行操作,改變它的空間尺寸。最常見的形式是池化層使用尺寸2x2的濾波器,以步長為2來對每個深度切片進行降取樣,將其中75%的啟用資訊都丟掉。每個Max操作是從4個數字中取最大值(也就是在深度切片中某個2x2的區域)。深度保持不變。池化層的一些公式:
-
輸入資料體尺寸
-
有兩個超引數:
空間大小
步長
輸出資料體尺寸 ,其中:
因為對輸入進行的是固定函式計算,所以沒有引入引數
在匯聚層中很少使用零填充
在實踐中,最大池化層通常只有兩種形式:一種是 ,也叫重疊池化(overlapping pooling),另一個更常用的是
。對更大感受野進行池化需要的池化尺寸也更大,而且往往對網路有破壞性。
普通池化(General Pooling) :
除了最大池化,池化單元還可以使用其他的函式,比如 平均池化 (average pooling) 或 L-2正規化 池化 (L2-norm pooling) 。平均池化歷史上比較常用,但是現在已經很少使用了。因為實踐證明,最大池化的效果比平均池化要好。

池化層在輸入資料體的每個深度切片上,獨立地對其進行空間上的降取樣。
左邊:本例中,輸入資料體尺寸[224x224x64]被降取樣到了[112x112x64],採取的濾波器尺寸是2,步長為2,而深度不變。
右邊:最常用的降取樣操作是取最大值,也就是最大池化,這裡步長為2,每個取最大值操作是從4個數字中選取(即2x2的方塊區域中)。
歸一化層
在卷積神經網路的結構中,提出了很多不同型別的歸一化層,有時候是為了實現在生物大腦中觀測到的抑制機制。但是這些層漸漸都不再流行,因為實踐證明它們的效果即使存在,也是極其有限的。對於不同型別的歸一化層,可以看看Alex Krizhevsky的關於cuda-convnet library API 的討論。
全連線層
在全連線層中,神經元對於前一層中的所有啟用資料是全部連線的,這個常規神經網路中一樣。它們的啟用可以先用矩陣乘法,再加上偏差。更多細節請檢視神經網路章節。
案例學習
下面是卷積神經網路領域中比較有名的幾種結構:
-
LeNet : 第一個成功的卷積神經網路應用,是Yann LeCun在上世紀90年代實現的。當然,最著名還是被應用在識別數字和郵政編碼等的LeNet 結構。
-
AlexNet : AlexNet 卷積神經網路在計算機視覺領域中受到歡迎,它由Alex Krizhevsky,Ilya Sutskever和Geoff Hinton實現。AlexNet在2012年的ImageNet ILSVRC 競賽 中奪冠,效能遠遠超出第二名(16%的top5錯誤率,第二名是26%的top5錯誤率)。這個網路的結構和LeNet非常類似,但是更深更大,並且使用了層疊的卷積層來獲取特徵(之前通常是隻用一個卷積層並且在其後馬上跟著一個匯聚層)。
-
ZF Net : Matthew Zeiler和Rob Fergus發明的網路在ILSVRC 2013比賽中奪冠,它被稱為ZFNet (Zeiler & Fergus Net的簡稱)。它通過修改結構中的超引數來實現對AlexNet的改良,具體說來就是增加了中間卷積層的尺寸,讓第一層的步長和濾波器尺寸更小。
-
GoogLeNet : ILSVRC 2014的勝利者是谷歌的Szeged等 實現的卷積神經網路。它主要的貢獻就是實現了一個 奠基模組 ,它能夠顯著地減少網路中引數的數量(AlexNet中有60M,該網路中只有4M)。還有,這個論文中沒有使用卷積神經網路頂部使用全連線層,而是使用了一個平均匯聚,把大量不是很重要的引數都去除掉了。GooLeNet還有幾種改進的版本,最新的一個是Inception-v4 。
-
VGGNet : ILSVRC 2014的第二名是Karen Simonyan和 Andrew Zisserman實現的卷積神經網路,現在稱其為VGGNet 。它主要的貢獻是展示出網路的深度是演算法優良效能的關鍵部分。他們最好的網路包含了16個卷積/全連線層。網路的結構非常一致,從頭到尾全部使用的是3x3的卷積和2x2的池化。他們的預訓練模型 是可以在網路上獲得並在Caffe中使用的。VGGNet不好的一點是它耗費更多計算資源,並且使用了更多的引數,導致更多的記憶體佔用(140M)。其中絕大多數的引數都是來自於第一個全連線層。後來發現這些全連線層即使被去除,對於效能也沒有什麼影響,這樣就顯著降低了引數數量。
-
ResNet : 殘差網路 (Residual Network)是ILSVRC2015的勝利者,由何愷明等實現。它使用了特殊的 跳躍連結 ,大量使用了批量歸一化 (batch normalization)。這個結構同樣在最後沒有使用全連線層。讀者可以檢視何愷明的的演講(視訊 ,PPT ),以及一些使用Torch重現網路的實驗 。ResNet當前最好的卷積神經網路模型(2016年5月)。何開明等最近的工作是對原始結構做一些優化,可以看論文Identity Mappings in Deep Residual Networks ,2016年3月發表。
計算上的考量
在構建卷積神經網路結構時,最大的瓶頸是記憶體瓶頸。大部分現代GPU的記憶體是3/4/6GB,最好的GPU大約有12GB的記憶體。要注意三種記憶體佔用來源:
-
來自中間資料體尺寸: 卷積神經網路中的每一層中都有啟用資料體的原始數值,以及損失函式對它們的梯度(和啟用資料體尺寸一致)。通常,大部分啟用資料都是在網路中靠前的層中(比如第一個卷積層)。在訓練時,這些資料需要放在記憶體中,因為反向傳播的時候還會用到。但是在測試時可以聰明點:讓網路在測試執行時候每層都只儲存當前的啟用資料,然後丟棄前面層的啟用資料,這樣就能減少巨大的啟用資料量;
-
來自引數尺寸: 即整個網路的引數的數量,在反向傳播時它們的梯度值,以及使用momentum、Adagrad或RMSProp等方法進行最優化時的每一步計算快取。因此,儲存引數向量的記憶體通常需要在引數向量的容量基礎上乘以3或者更多;
-
卷積神經網路實現還有各種零散的記憶體佔用,比如成批的訓練資料,擴充的資料等等。
一旦對於所有這些數值的數量有了一個大略估計(包含啟用資料,梯度和各種雜項),數量應該轉化為以GB為計量單位。把這個值乘以4,得到原始的位元組數(因為每個浮點數佔用4個位元組,如果是雙精度浮點數那就是佔用8個位元組),然後多次除以1024分別得到佔用記憶體的KB,MB,最後是GB計量。如果你的網路工作得不好,一個常用的方法是降低批尺寸(batch size),因為絕大多數的記憶體都是被啟用資料消耗掉了。
如果想加入我們“ 計算機視覺戰隊 ”,請掃二維碼加入學習群,我們一起學習進步,探索領域中更深奧更有趣的知識!