與以前的神經網絡不一樣之處在於,CNN明確指定了輸入就是圖像,這容許咱們將某些特徵編碼到CNN的結構中去,不只易於實現,還能極大減小網絡的參數。git
與通常的神經網絡不一樣,卷積神經網絡尤爲特殊之處。通常的神經網絡每一層與前一層之間採用全鏈接;一層中的神經元之間也是互相獨立的,並不共享權值;最後一層全鏈接層陳偉輸出層,在分類任務中出表示類別得分。CIFAR-10中圖像是32*32*3=3072,因此,與輸入相連的第一個隱層的每一個神經元的參數都有3072個,若是圖像尺寸更大,那麼每一個神經元的參數更多,這將形成巨大的參數冗餘,訓練中也會很快致使過擬合問題。以下圖左所示。github
神經網絡算法 |
卷積神經網絡網絡 |
卷積神經網絡限定了輸入的是圖像,它能夠採用更合理的方式安排神經元。CNN不將圖像調整爲向量以後再輸入,而是直接以原始的3D矩陣形式(高x寬x通道數)給輸入層,而後輸出3D數據矩陣,並依次進行學習、表示。機器學習
卷積神經網絡是由一系列的層Layer組成的,下面介紹主要的層(包括卷積層 Convolutional layer,池化層 Pooling layer,全鏈接層 Fully-connected layer)。ide
以應用於CIFAR-10數據集的卷積神經網絡爲基礎,介紹以下結構的卷積神經網絡,函數
[ INPUT - CONV - RELU - POOL - FC ]性能
ReLU與Pool都是固定的函數,訓練時 只對 CONV layer與FC進行權重更新學習
卷積層是卷積神經網絡的核心模塊,它承擔了主要的計算工做大數據
卷積層的參數是一系列能夠學習的濾波器。每一個濾波器都是[ filter_寬xfilter_高x通道數 ],第一個卷積層的典型濾波器尺寸是 5x5xx3。前向傳播時,咱們把每一個濾波器沿着輸入數據的高度與寬度滑動(卷積),計算濾波器係數與濾波器窗口所覆蓋的輸入區域 之間的點積,隨着濾波器沿着輸入數據的高度x寬度所有滑動一遍,就會獲得二維的輸出映射(activation map),activation map 保存的是濾波器在輸入上滑動時,在空間每個點的響應(點積 .*)。這樣一個濾波器就獲得一個 activation map,12個濾波器就會獲得12個activation map,而後沿着深度的方向將這12個二維的 activation map(輸出映射)組合成輸出,做爲下一層的輸入。
一個濾波器對圖像卷積,convolved feature即爲濾波器的 activation map,即從圖像學到的特徵 |
第一層對原始圖像卷積後,學到多個二維 activation maps,而後按照Z軸(深度)組合起來,傳遞給後面的 pooling layer 進行下采樣 |
直覺上卷積神經網絡學習到的濾波器應該是這樣的,它們在遇到特定的結構時會激活,好比有的濾波器在遇到邊緣時會激活,有的在遇到某個直角會激活,...; 並且不一樣的層的濾波器檢測的形狀也不同,前面的層,它們的濾波器檢測基本的形狀,越靠後面的層,這些基本特徵組合成複雜形狀,後面層的濾波器檢測複雜形狀,最後網絡就能檢測出車輪,或者花朵之類的物體。
1.1 局部鏈接
局部鏈接就是指小尺寸的濾波器,與高維的輸入之間的鏈接。以卷積神經網絡第一層爲例,採起輸入是原始圖像,因爲不可能像通常的神經網絡那樣實行全鏈接(參數太多!),因此定義小尺寸的濾波器 [filer_寬,filter_高,圖像通道數],必須保證濾波器深度與圖像的深度是一致的,這樣濾波器在圖像上面滑動(卷積)時,只考慮在圖像 寬x高 的空間面上滑動,因此產生的是二維的輸出。濾波器在圖像上滑動時,它所可以覆蓋的輸入圖像的區域,就是局部的小區域(大小是 filter_寬 x filter_高),卷積運算也就是在濾波器與小區域之間進行,獲得一個卷積結果數值,隨後再滑動必定的步長,再次進行卷積。局部鏈接就是每次卷積時,神經元只與覆蓋的小區域鏈接。
輸出的大小
卷積層對輸入進行卷積後,獲得activation maps,而後再以某種形式安排這些數據,造成輸出,主要的參數有深度,步長,零填充。
一個例子,輸入是 NxNx3;濾波器是 mxmx3,共有K個;步長是 S;零填充是使用P個0在邊界填充,則輸出activation maps的 高度(=寬度)應該是 (N+2P-m)/ S + 1。
CIFAR-10 的圖像是 32x32x3, 選擇 濾波器尺寸 5x5x3,步長 S=1,填充 P= 0,則輸出是 28x28;若是步長S=3,則輸出是 10x10。
1.2 權值共享(參數共享)
一個例子是ImageNet 2012,圖像是 227x227x3,m = 11,S=4,P=3,K=96,則第一層卷積的輸出是 55x55x96。若是按照通常神經網絡的設置,55x55x96的輸出須要 55*55*96 =290400 個神經元,每一個神經元須要的參數是 11*11*3 + 1 =364,所以在第一層就有 290400*364 =105,705,600個參數,這是很是多的。
卷積神經網絡採用了權值共享的思路,對於一個濾波器來講,它的任務是檢測某個特徵,好比說檢測水平線,那麼它檢測到了(x1,y1)位置處的水平線,那麼若是在(x1,y2)位置處有水平線,它應該也能檢測出來。所以,它應該使用相同的參數來檢測不一樣位置處的水平線,因此,就設計一個濾波器在輸入的全部位置(x,y)上滑動時,它的參數都是相同的,也就是說,濾波器在輸入的全部位置上,都是用相同的參數來檢查某一特徵(體現爲卷積操做),而後將卷積的結果就是它的activation map。這樣就使得網絡的參數大大減小,卷積神經網絡第一層的參數就變爲 96*11*11*3 + 96 = 34944。
注意:有的地方不須要權值共享,有時輸入圖像具備特定的中心結構,咱們還但願學到這種結構。那就不須要權值共享了。好比,面部出如今圖像中心,咱們指望學到不一樣的位置的眼睛或者頭髮特徵,那就不須要權值共享,而只須要局部鏈接就好了。
卷積的實現(Python):經過 im2col 的方法來實現,用矩陣相乘完成卷積操做
假設輸入X [227x227x3],96個濾波器 [ 11x11x3 ],步長S=4,那麼一個濾波器卷積的輸出維度應該是 (227-11)/ 4 = 55,卷積層的輸出應該是 55x55x96。
在連續的卷積層之間加入池化層很常見,pooling layer 的做用是逐步的減少從圖像中提取的表達representation的尺寸,進而減小網絡的參數與計算量,同時還能控制過擬合。最多見的pooling layer的下采樣尺寸 2x2,步長s=2,它沿着 activation maps的 寬度x高度面下采樣,並不影響深度。
主要有兩種pooling方法,max pooling與mean pooling,主要有 尺寸 2x2,與步長S兩個採樣參數。但並不更新,是固定的,pooling layer只執行固定的下采樣做用。下圖示意圖。
pooling |
max pooling |
max pooling ,採樣尺寸 2x2, 步長s=1,在2x2採樣窗口所覆蓋的輸入區域內,取輸入區域最大值max(...),做爲對應的輸出數據點(也就是輸入的2x2數據產生一個輸出數據);而後採樣窗口根據步長規定移動,再對下一個窗口覆蓋的輸入數據採樣,做爲輸出數據值,...,直至採樣完成。max pooling的常見尺寸是 3x3, 步長S=2(重疊採樣),或者 2x2,步長=2
mean pooling:與max pooling相似,只是取輸入的均值做爲輸出值。如今更經常使用 max pooling,實際效果比 mean pooling 好。
注意:下采樣時通常不用零填充
3. FC layers to CONV layers
實際中將全鏈接層轉換成具備相同效果的卷積層,加快速度,提高效率。
卷積神經網絡主要有: CONV, POOL(max), ReLU, FC 組成。
最多見的卷積網絡結構是: [ 一些 CONV - ReLU 層,接着是一些 POOL 層 ],重複以上結構,直到圖像合併成比較小的圖,而後是 一些FC 層,最後一層 FC 層保存類別得分之類的輸出,
以下所示:
INPUT -> [ [CONV -> RELU] *N -> POOL? ]*M -> [FC -> RELU]*K -> FC
* 表示重複,POOL? 表示可選的 pooling層, 一般 0 <= N <= 3,M >= 0,0 <= K < 3。
3.1 以下是常見的一些 卷積網絡結構:
3個 3x3 CONV 效果 等同於 1個 7x7 CONV,可是更傾向於 多個小尺寸 CONV ,由於多個小尺寸 CONV層 能夠 1. 更有效的表達特徵,2. 減小參數。
1. 輸入層(INPUT)應該可以被 2 整除不少次,一般有 32(CIFAR-10),64,96(STL-10),224,384,512
2. CONV layer使用小的 filter(3x3,最可能是 5x5),步長S=1,須要對輸入進行零填充以保持輸入的大小 ( 寬度x高度 ). 若是非要使用 大的filter(好比7x7),只有在跟輸入的圖像相鄰的第一個卷積層上使用。
3. POOL layer 控制對輸入的下采樣,通常是Max pooling,最經常使用的是 2x2 ,步長S=2,這個設置就捨棄了 75%的下采樣層的輸入(即上一層的activation map);另一個不常常用到的設置是 3x3,步長 S=2。對於 max pooling,採樣窗口大於 3x3 會致使損失太大,性能不佳,不多用。
VGGNet 分析:
CONV layers執行3x3卷積,步長S=1,零填充P=1; POOL layers執行2x2 max pooling,步長S=2,不進行零填充P=0。
追蹤每一步的 表達size 與 參數size:
INPUT: [224x224x3] memory: 224*224*3=150K weights: 0 CONV3-64: [224x224x64] memory: 224*224*64=3.2M weights: (3*3*3)*64 = 1,728 CONV3-64: [224x224x64] memory: 224*224*64=3.2M weights: (3*3*64)*64 = 36,864 POOL2: [112x112x64] memory: 112*112*64=800K weights: 0 CONV3-128: [112x112x128] memory: 112*112*128=1.6M weights: (3*3*64)*128 = 73,728 CONV3-128: [112x112x128] memory: 112*112*128=1.6M weights: (3*3*128)*128 = 147,456 POOL2: [56x56x128] memory: 56*56*128=400K weights: 0 CONV3-256: [56x56x256] memory: 56*56*256=800K weights: (3*3*128)*256 = 294,912 CONV3-256: [56x56x256] memory: 56*56*256=800K weights: (3*3*256)*256 = 589,824 CONV3-256: [56x56x256] memory: 56*56*256=800K weights: (3*3*256)*256 = 589,824 POOL2: [28x28x256] memory: 28*28*256=200K weights: 0 CONV3-512: [28x28x512] memory: 28*28*512=400K weights: (3*3*256)*512 = 1,179,648 CONV3-512: [28x28x512] memory: 28*28*512=400K weights: (3*3*512)*512 = 2,359,296 CONV3-512: [28x28x512] memory: 28*28*512=400K weights: (3*3*512)*512 = 2,359,296 POOL2: [14x14x512] memory: 14*14*512=100K weights: 0 CONV3-512: [14x14x512] memory: 14*14*512=100K weights: (3*3*512)*512 = 2,359,296 CONV3-512: [14x14x512] memory: 14*14*512=100K weights: (3*3*512)*512 = 2,359,296 CONV3-512: [14x14x512] memory: 14*14*512=100K weights: (3*3*512)*512 = 2,359,296 POOL2: [7x7x512] memory: 7*7*512=25K weights: 0 FC: [1x1x4096] memory: 4096 weights: 7*7*512*4096 = 102,760,448 FC: [1x1x4096] memory: 4096 weights: 4096*4096 = 16,777,216 FC: [1x1x1000] memory: 1000 weights: 4096*1000 = 4,096,000 TOTAL memory: 24M * 4 bytes ~= 93MB / image (only forward! ~*2 for bwd) TOTAL params: 138M parameters
計算上的考慮
如今構建卷積神經網絡最大的瓶頸就是內存瓶頸,進行網絡構建時提早計算所需內存大小:
1. 每層的activation maps,梯度。
2. 參數數量
3. 其他所需數據,好比 image data等。
總結一些理解與觀察CNN的方法
1. 可視化層的activation
最直白的可視化就是在CNN計算前向傳播時,可視化神經網絡的輸出映射activation maps。若是存在某些 activation maps,對於許多不一樣的輸入這些activation maps的值都是0,那麼就暗示這些濾波器 filters是「死」的濾波器,多是學習率過大的標誌。
2. CONV / FC Fliters
第二個經常使用方法是可視化權重,通常第一個卷積層的權重可視化後最易於解釋,由於它鏈接的原始圖像,後續的也應該能夠可視化。權重可視化的用途在於,對於訓練很好的網絡,它的濾波器權重可視化後通常都是平滑流暢的無噪聲圖像。有噪聲的可視化圖像暗示着網絡訓練的時間不夠長,或者是正則化強度過低致使了過擬合。
左側是訓練好的AlexNet的第一個卷積層的濾波器可視化,圖中彩色/灰度在一塊兒是 由於AlexNet網絡有兩個獨立的處理流,結果就是一個開發高頻灰度圖像,另外一個開發低頻彩色圖像 |
右側是訓練好的AlexNet第二個卷積層的濾波器可視化,可視化圖像沒法明確的解釋,可是這些圖像都是光滑的、無噪聲圖像 |
3.檢索出可以使神經元有最大激活的圖像
另外一個可視化方法就是將一個大的圖像集輸入給網絡,追蹤能夠最大激活某些神經元的圖像,而後將圖像顯示出來。以此來觀察這些神經元在它的感覺野以內,它尋找的是什麼樣的圖像。一個這樣的可視化方法就是 Rich feature hierarchies for accurate object detection and semantic segmentation by Ross Girshick et al.:
AlexNet的第5個POOL 的某些神經元的 最大激活圖像,激活值和感覺野以白色顯示 |
ReLU的神經元自己沒有什麼語義含義, http://cs231n.github.io/understanding-cnn/
4. 根據 t-SNE嵌入圖像
t-SNE(t-distributed stochastic neighbor embedding):t-分佈隨機領域嵌入,是用於降維的一種機器學習算法,是由 Laurens van der Maaten 和 Geoffrey Hinton在08年提出來。此外,t-SNE 是一種非線性降維算法,很是適用於高維數據降維到2維或者3維,進行可視化。
思路就是將數據從高維降維到地位,而後將低維上距離相近的圖像靠近,完成可視化。爲了嵌入,咱們能夠將圖像集合輸入卷機網絡,提取他們的CNN碼,CNN碼能夠是AlexNet中分類器以前的 4096-維矢量,而後將CNN碼插入t-SNE而後獲得圖像的2-維矢量,以下:
根據CNN碼將圖像進行t-SNE嵌入。CNN「認爲」靠的近的圖像更類似,這種類似性是語義與類別上類似性,而不是顏色或者像素值的類似性。 more related visualizations at different scales refer to t-SNE visualization of CNN codes. |
5. 遮擋圖像的一部分
若是CNN網絡將一幅圖像斷定爲「dog」,那麼如何肯定CNN網絡實際斷定的依據呢?它是依據圖中的dog來斷定的?仍是依據圖像上下文或者其餘物體來斷定的呢?爲了明確這一點,能夠經過遮擋圖像以後,畫出CNN網絡的預測類別來觀察。具體的就是,逐塊的遮擋圖像中的區域,使要遮擋的區域設置爲0,而後觀察CNN判斷類別爲 dog 的機率。還能夠將機率畫做2-位熱力圖,Matthew Zeiler 已經使用此方法 Visualizing and Understanding Convolutional Networks:
三幅圖像,遮擋都是以灰色區塊表示。最左側的 Dog 圖像,Dog圖像下方是 CNN斷定次圖像類別是 Dog 的機率,能夠看出當遮擋了上面圖像中Dog的臉部區域後,CNN斷定Dog類別的機率就大幅降低(表現爲藍色),這說明,Dog的臉部是斷定的主要依據。而那些遮擋後 類別機率不變的部位,對於類別斷定的影響能夠忽略。 |
Data Gradient.
Deep Inside Convolutional Networks: Visualising Image Classification Models and Saliency Maps
DeconvNet.
Visualizing and Understanding Convolutional Networks
Guided Backpropagation.
Striving for Simplicity: The All Convolutional Net
Understanding Deep Image Representations by Inverting Them
Do ConvNets Learn Correspondence? (tldr: yes)
ImageNet Large Scale Visual Recognition Challenge
Explaining and Harnessing Adversarial Examples
What I learned from competing against a ConvNet on ImageNet
實際上,不多有人從零訓練整個卷積網絡,由於不多有足夠數目的數據供其訓練使用。通常都是使用一個大數據集(如ImageNet)來預訓練一個卷積模型,而後對於目標任務,使用這個模型做爲初始模型或者做爲固定特徵抽取器。三個主要的遷移學習場景以下,
怎樣調優?什麼時候調優? 兩個重要的因素是新數據的大小、新數據集與原數據集的類似程度。