1. 卷積神經網路——卷積層、池化層和激活函數
2018年11月20日,在看tensorflow的時候發現還是有很多概念沒有理解透徹,發現一個很贊的資源(估計大家都知道的,只有我現在才發現),吳恩達老師在網易雲課堂上開的深度學習的 課程 ,感覺很贊.本文實際上是吳恩達卷積神經網路視頻學習筆記。
2019年2月14日,再次溫故這部分的內容,添加了1.1章節的自問自答,添加了對池化層實現反向傳播的方式,添加了激活函數relu和sigmoid的對比。
通過一個3 * 3的每列值相同、第一列為1,第二列為0,第三列為-1的過濾器可以檢測垂直的邊沿。注意到1表示亮,-1表示暗。這樣可以發現正負值的邊沿。
對於垂直邊緣過濾器而言,重要的是中間一列為0,左右兩列的值可以相差盡可能的大。
這個過濾器的數值也是可以通過反向傳播皮運行演算法學習的,不一定需要在演算法開始之前就決定。
深度學習甚至可以去學習其他的邊沿,無論是45度、73度乃至是其他的角度,雖然比手工要復雜一些,但是確實具有這樣的能力。
為什麼需要填充?大家都知道,卷積就是用過濾器(f x f)從左到右、從上到下的掃描一個矩陣(n x n)。有兩種卷積操作,一種稱為valid-conv,一種稱為same-conv。每次卷積的時候,過濾器右側碰到矩陣右邊界就結束當前行的掃描,下側碰到矩陣下邊界就結束掃描,因此通過過濾器的圖像都會縮小,變為(n-f+1) * (n-f+1)。valid-conv就是這樣的卷積操作,而same-conv會在卷積之前填充原始圖,使得卷積之後的大小不變。
一般來說燃嘩,若原圖像大小為n * n,過濾器大小為f * f,那麼需要padding的大小為p=(f-1)/2。一般來說我們會設置f為奇數,很少看見偶數的過濾器。其中的原因之一就是為了對稱填充。另一個原因可能是一般需要將過濾器的中間點用於定位卷積的位置,而偶數過濾器沒有中間點。
上面的提到的卷積過程每次只移動一步。實際上過濾器可以移動不止一步,用s表示步長。那麼n x n的矩陣輸入, f x f的過濾器, p填充padding,以及s步長的情況下,輸出的矩陣大小為 (n+2p-f)/2+1 x (n+2p-f)/2+1 ,這里是向下取整的,這意味過濾器只能在輸入圖像內部移動,不可以移動出邊緣。
注意 在tensorflow中,有兩種填充方式,一種是same,一種是valid。same是填充,而valid是不填充。如果遇到valid,那麼實際計算矩陣大小的時候,是向上取悄襪整,而不是這里提到的向下取整。如果是same模式,那麼最後的矩陣形狀是n/s,也是向上取整
上面提到的卷積的輸入是n x n的,這一般是灰度圖像。對應彩色圖像則存在RGB三個顏色channel,這樣的圖片是n x n x 3。此時的過濾器也必須存在第三個維度,即channel維度,且一個過濾器的channel維度必須和輸入的channel維度一致。這樣的卷積結果就是三個維度上,過濾器和輸入的重疊位置乘積之和。最後的輸出是(n - f + 1) x ( n - f +1)的。 注意,輸出是二維的
我們可以使用N個不同的過濾器得到不同的N個二維輸出,按照輸入的格式將其疊起來,這樣輸出就是 (n - f + 1) x ( n - f +1) x N了。
在上面一節中已經講了如何得到輸入和一個過濾器卷積之後的結果。通常會給卷積的結果添加一個偏執,然後使用非線性的函數進行處理,得到的就是這層網路的輸出。將過濾器的參數標記為W,偏置為 b(一個channel的輸出矩陣Wa的偏置是一個實數,而非一個矩陣。一個layer的偏置b的維度和通道數channel一致) , 輸入數據為上層的激活值。這樣每個過濾器處理之後的結果就可以看成是經過了該layer一個節點之後的輸出。
下面是每層的符號標記,以及根據上一層計算下一層輸入大小的公式,右下角是使用BP學習更新的時候參數更新的次數。可以看到每層的參數的個數只和這層的filter的大小、數目有關,而和輸入的規模無關。這樣就可以通過控制參數的數量避免過擬合了。
可以從下面的課件中看到,卷積神經網路的趨勢是長度和高度逐漸減少,而channel逐漸加深。最後一層會將卷積層平鋪開來,形成一個全連接。全連接層會連接到最後一個判別函數上,判別函數可以是logistic或者softmax層,用於輸出類別或者概率。
一般情況下,卷積網路除了卷積層之外,還會有池化層和全連接層,這些層可以提供更好的學習。
池化層一般在卷積層之後,可以也可以看成一個過濾器,實際上實現的一個采樣的功能,其主要的思想是,著重提取具有某種傾向的特徵,比如最大池化對應的是更顯著的特徵;平均池化對應的是更加平滑的特徵。過濾器有幾點不同
一般常用的池化層有max_pooling和average_pooling.max_pooling更加常用。 ,最大池化層意味著檢測某個特徵,並始終將這個特徵留在池化層的輸出中 。
池化層的輸入n x n x nc,過濾器 f x f,步長s,輸出 ((n-f)/s+1) x ((n-f)/s+1) * nc。
一般取s=2,這意味著輸入的長寬減小一半。
比較好奇的一個問題是,池化層的存在對反向傳播有什麼影響?我們都知道在傳統的神經網路中,反向傳播演算法實際上就是利用函數的梯度進行反向傳播的,那麼池化層這種既改變了矩陣大小又不好求導的情況,怎麼處理呢?
(下面的內容來自 迷川浩浩_ZJU 的博客 )
mean pooling的前向傳播就是把一個patch中的值求取平均來做pooling,那麼反向傳播的過程也就是把某個元素的梯度等分為n份分配給前一層,這樣就保證池化前後的梯度(殘差)之和保持不變,還是比較理解的。mean pooling比較容易讓人理解錯的地方就是會簡單的認為直接把梯度復制N遍之後直接反向傳播回去,但是這樣會造成loss之和變為原來的N倍,網路是會產生梯度爆炸的。
2、max pooling
max pooling也要滿足梯度之和不變的原則,max pooling的前向傳播是把patch中最大的值傳遞給後一層,而其他像素的值直接被舍棄掉。那麼反向傳播也就是把梯度直接傳給前一層某一個像素,而其他像素不接受梯度,也就是為0。所以max pooling操作和mean pooling操作不同點在於需要記錄下池化操作時到底哪個像素的值是最大,也就是max id
一般概念上的一層包括卷積層和池化層,之所以不把池化層當做新的一層是因為池化層沒有需要學習的參數,一般意義上的layer是有權重和參數需要學習的。
盡量不要自己設置超參數,而是盡量參考別人論文裡面使用的超參數,選擇一個在別人任務中效果很好的超參數。
下面的表中列舉了上面的網路每一層的數據規模a^(l)以及參數數量。可以發現數據的規模逐漸減小。主卷積層的參數比較少,而進入全連接層之後參數數量很大。(表格中最後三列的參數數量可能存在錯誤,應該是48000 + 120, 120 * 84 + 84, 84 * 10 + 10)
以上的兩個特徵可以明顯的減少參數。減少過擬合
(內容來自 迷川浩浩_ZJU 的博客 )
常用的激活函數有sigmoid函數和relu函數.
Relu(x)={if x>0 then x;else 0}為了在反向傳播演算法中可以正常使用,將其在x=0x=0處的導數置為1,所以它的導數也就變為了 δRelu(x)={if x>0 then 1 else 0}
Relu是一個非常優秀的激活哈數,相比較於傳統的Sigmoid函數,有三個作用
2. 卷積神經網路
1、二維互相關運算
二維互相關(cross-correlation)運算的輸入是一個二維輸入數組和一個二維核(kernel)數組,輸出也是一個二維數組,其中核數組通常稱為卷積核或過濾器(filter)。卷積核的尺寸通常小於輸入數組,卷積核在輸入數組上滑動,在每個位置上,卷積核與該位置處的輸入子數組按元素相乘並求和,得到輸出數組中相應位置的元素。圖1展示了一個互相關運算的例子,陰影部分分別是輸入的第一個計算區域、核數組以及對應的輸出。
2、二維卷積層
卷積層得名於卷積運算,但卷積層中用到的並非卷積運算而是互相關運算。我們將核數組上下翻轉、左右翻轉,再與輸入數組做互相關運算,這一過程就是卷積運算。由於卷積層的核數組是可學習的,所以使用互相關運算與使用卷積運算並無本質區別。
二維卷積層將輸入和卷積核做互相關運算,並加上一個標量偏置來得到輸出。卷積層的模型參數包括卷積核和標量偏置。
3、特徵圖與感受野
二維卷積層輸出的二維數組可以看作是輸入在空間維度(寬和高)上某一級的表徵,也叫特徵圖(feature map)。影響元素x的前向計算的所有可能輸入區域(可能大於輸入的實際尺寸)叫做x的感受野(receptive field)。
以圖1為例,輸入中陰影部分的四個元素是輸出中陰影部分元素的感受野。我們將圖中形狀為2×2的輸出記為Y,將Y與另一個形狀為2×2的核數組做互相關運算,輸出單個元素z。那麼,z在Y上的感受野包括Y的全部四個元素,在輸入上的感受野包括其中全部9個元素。可見,我們可以通過更深的卷積神經網路使特徵圖中單個元素的感受野變得更加廣闊,從而捕捉輸入上更大尺寸的特徵。
4、填充和步幅
我們介紹卷積層的兩個超參數,即填充和步幅,它們可以對給定形狀的輸入和卷積核改變輸出形狀。
4.1 填充(padding)
是指在輸入高和寬的兩側填充元素(通常是0元素),圖2里我們在原輸入高和寬的兩側分別添加了值為0的元素。
如果原輸入的高和寬是 和 ,卷積核的高和寬是 和 ,在高的兩側一共填充 行,在寬的兩側一共填充 列,則輸出形狀為:
)
我們在卷積神經網路中使用奇數高寬的核,比如3×3,5×5的卷積核,對於高度(或寬度)為大小為2k+1的核,令步幅為1,在高(或寬)兩側選擇大小為k的填充,便可保持輸入與輸出尺寸相同。
4.2 步幅(stride)
在互相關運算中,卷積核在輸入數組上滑動,每次滑動的行數與列數即是步幅(stride)。此前我們使用的步幅都是1,圖3展示了在高上步幅為3、在寬上步幅為2的二維互相關運算。
一般來說,當高上步幅為 ,寬上步幅為 時,輸出形狀為:
如果 ,那麼輸出形狀將簡化為:
更進一步,如果輸入的高和寬能分別被高和寬上的步幅整除,那麼輸出形狀將是:(nh/sh)×(nw/sw)
當 時,我們稱填充為p;當 時,我們稱步幅為s。
5、多輸入通道和多輸出通道
之前的輸入和輸出都是二維數組,但真實數據的維度經常更高。例如,彩色圖像在高和寬2個維度外還有RGB(紅、綠、藍)3個顏色通道。假設彩色圖像的高和寬分別是h和w(像素),那麼它可以表示為一個3×h×w的多維數組,我們將大小為3的這一維稱為通道(channel)維。
5.1 多輸入通道
卷積層的輸入可以包含多個通道,圖4展示了一個含2個輸入通道的二維互相關計算的例子。
5.2 多輸出通道
卷積層的輸出也可以包含多個通道,設卷積核輸入通道數和輸出通道數分別為ci和co,高和寬分別為kh和kw。如果希望得到含多個通道的輸出,我們可以為每個輸出通道分別創建形狀為ci×kh×kw的核數組,將它們在輸出通道維上連結,卷積核的形狀即co×ci×kh×kw。
對於輸出通道的卷積核,我們提供這樣一種理解,一個ci×kh×kw的核數組可以提取某種局部特徵,但是輸入可能具有相當豐富的特徵,我們需要有多個這樣的ci×kh×kw的核數組,不同的核數組提取的是不同的特徵。
5.3 1x1卷積層
最後討論形狀為1×1的卷積核,我們通常稱這樣的卷積運算為1×1卷積,稱包含這種卷積核的卷積層為1×1卷積層。圖5展示了使用輸入通道數為3、輸出通道數為2的1×1卷積核的互相關計算。
1×1卷積核可在不改變高寬的情況下,調整通道數。1×1卷積核不識別高和寬維度上相鄰元素構成的模式,其主要計算發生在通道維上。假設我們將通道維當作特徵維,將高和寬維度上的元素當成數據樣本,那麼1×1卷積層的作用與全連接層等價。
6、卷積層與全連接層的對比
二維卷積層經常用於處理圖像,與此前的全連接層相比,它主要有兩個優勢:
一是全連接層把圖像展平成一個向量,在輸入圖像上相鄰的元素可能因為展平操作不再相鄰,網路難以捕捉局部信息。而卷積層的設計,天然地具有提取局部信息的能力。
二是卷積層的參數量更少。不考慮偏置的情況下,一個形狀為(ci,co,h,w)的卷積核的參數量是ci×co×h×w,與輸入圖像的寬高無關。假如一個卷積層的輸入和輸出形狀分別是(c1,h1,w1)和(c2,h2,w2),如果要用全連接層進行連接,參數數量就是c1×c2×h1×w1×h2×w2。使用卷積層可以以較少的參數數量來處理更大的圖像。
X=torch.rand(4,2,3,5)
print(X.shape)
conv2d=nn.Conv2d(in_channels=2,out_channels=3,kernel_size=(3,5),stride=1,padding=(1,2))
Y=conv2d(X)
print('Y.shape: ',Y.shape)
print('weight.shape: ',conv2d.weight.shape)
print('bias.shape: ',conv2d.bias.shape)
輸出:
torch.Size([4, 2, 3, 5])
Y.shape: torch.Size([4, 3, 3, 5])
weight.shape: torch.Size([3, 2, 3, 5])
bias.shape: torch.Size([3])
7、池化
7.1 二維池化層
池化層主要用於緩解卷積層對位置的過度敏感性。同卷積層一樣,池化層每次對輸入數據的一個固定形狀窗口(又稱池化窗口)中的元素計算輸出,池化層直接計算池化窗口內元素的最大值或者平均值,該運算也分別叫做最大池化或平均池化。圖6展示了池化窗口形狀為2×2的最大池化。
二維平均池化的工作原理與二維最大池化類似,但將最大運算符替換成平均運算符。池化窗口形狀為p×q的池化層稱為p×q池化層,其中的池化運算叫作p×q池化。
池化層也可以在輸入的高和寬兩側填充並調整窗口的移動步幅來改變輸出形狀。池化層填充和步幅與卷積層填充和步幅的工作機制一樣。
在處理多通道輸入數據時,池化層對每個輸入通道分別池化,但不會像卷積層那樣將各通道的結果按通道相加。這意味著池化層的輸出通道數與輸入通道數相等。
CNN網路中另外一個不可導的環節就是Pooling池化操作,因為Pooling操作使得feature map的尺寸變化,假如做2×2的池化,假設那麼第l+1層的feature map有16個梯度,那麼第l層就會有64個梯度,這使得梯度無法對位的進行傳播下去。其實解決這個問題的思想也很簡單,就是把1個像素的梯度傳遞給4個像素,但是需要保證傳遞的loss(或者梯度)總和不變。根據這條原則,mean pooling和max pooling的反向傳播也是不同的。
7.2 mean pooling
mean pooling的前向傳播就是把一個patch中的值求取平均來做pooling,那麼反向傳播的過程也就是把某個元素的梯度等分為n份分配給前一層,這樣就保證池化前後的梯度(殘差)之和保持不變,還是比較理解的,圖示如下:
mean pooling比較容易讓人理解錯的地方就是會簡單的認為直接把梯度復制N遍之後直接反向傳播回去,但是這樣會造成loss之和變為原來的N倍,網路是會產生梯度爆炸的。
7.3 max pooling
max pooling也要滿足梯度之和不變的原則,max pooling的前向傳播是把patch中最大的值傳遞給後一層,而其他像素的值直接被舍棄掉。那麼反向傳播也就是把梯度直接傳給前一層某一個像素,而其他像素不接受梯度,也就是為0。所以max pooling操作和mean pooling操作不同點在於需要記錄下池化操作時到底哪個像素的值是最大,也就是max id。
源碼中有一個max_idx_的變數,這個變數就是記錄最大值所在位置的,因為在反向傳播中要用到,那麼假設前向傳播和反向傳播的過程就如下圖所示。
7.4 Pytorch 實現池化層
我們使用Pytorch中的nn.MaxPool2d實現最大池化層,關注以下構造函數參數:
kernel_size – the size of the window to take a max over
stride – the stride of the window. Default value is kernel_size
padding – implicit zero padding to be added on both sides
forward函數的參數為一個四維張量,形狀為 ,返回值也是一個四維張量,形狀為 ,其中N是批量大小,C,H,W分別表示通道數、高度、寬度。
X=torch.arange(32,dtype=torch.float32).view(1,2,4,4)
pool2d=nn.MaxPool2d(kernel_size=3,padding=1,stride=(2,1))
Y=pool2d(X)
print(X)
print(Y)
練習
1、假如你用全連接層處理一張256 \times 256256×256的彩色(RGB)圖像,輸出包含1000個神經元,在使用偏置的情況下,參數數量是:
答:圖像展平後長度為3×256×256,權重參數和偏置參數的數量是3× 256× 256 × 1000 + 1000 =196609000。
2、假如你用全連接層處理一張256×256的彩色(RGB)圖像,卷積核的高寬是3×3,輸出包含10個通道,在使用偏置的情況下,這個卷積層共有多少個參數:
答:輸入通道數是3,輸出通道數是10,所以參數數量是10×3×3×3+10=280。
3、conv2d = nn.Conv2d(in_channels=3, out_channels=4, kernel_size=3, padding=2),輸入一張形狀為3×100×100的圖像,輸出的形狀為:
答:輸出通道數是4,上下兩側總共填充4行,卷積核高度是3,所以輸出的高度是104 - 3 + 1=102104−3+1=102,寬度同理可得。
4、關於卷積層,以下哪種說法是錯誤的:
A.1×1卷積可以看作是通道維上的全連接
B.某個二維卷積層用於處理形狀為3×100×100的輸入,則該卷積層無法處理形狀為3×256×256的輸入
C.卷積層通過填充、步幅、輸入通道數、輸出通道數等調節輸出的形狀
D .兩個連續的3×3卷積核的感受野與一個5×5卷積核的感受野相同
答:選B,對於高寬維度,只要輸入的高寬(填充後的)大於或等於卷積核的高寬即可進行計算。
the first layer is a 3 × 3 convolution, the second is a fully connected layer on top of the 3 × 3 output grid of the first layer (see Figure 1). Sliding this small network over the input activation grid boils down to replacing the 5 × 5 convolution with two layers of 3 × 3 convolution.
我們假設圖片是5*5的
我們使用5*5的卷積核對其卷積,步長為1,得到的結果是:(5-5)/1+1=1
然後我們使用2個卷積核為3*3的,這里的兩個是指2層:
第一層3*3:
得到的結果是(5-3)/1+1=3
第二層3*3:
得到的結果是(3-3)/1+1=1
所以我們的最終得到結果感受野大小和用5*5的卷積核得到的結果大小是一樣的!!!
5、關於池化層,以下哪種說法是錯誤的:
A.池化層不參與反向傳播
B.池化層沒有模型參數
C.池化層通常會減小特徵圖的高和寬
D.池化層的輸入和輸出具有相同的通道數
答:A
選項1:錯誤,池化層有參與模型的正向計算,同樣也會參與反向傳播
選項2:正確,池化層直接對窗口內的元素求最大值或平均值,並沒有模型參數參與計算
選項3:正確
選項4:正確
參考文獻:
https://www.boyuai.com/
https://blog.csdn.net/qq_21578849/article/details/94667699
https://www.hu.com/question/265791259/answer/298610437
https://blog.csdn.net/zouxiaolv/article/details/97366681
3. 卷積神經網路
卷積神經網路 (Convolutional Neural Networks,CNN)是一種前饋神經網路。卷積神經網路是受生物學上感受野(Receptive Field)的機制而提出的。感受野主要是指聽覺系統、本體感覺系統和視覺系統中神經元的一些性質。比如在視覺神經系統中,一個神經元的感受野是指視網膜上的特定區域,只有這個區域內的刺激才能夠激活該神經元。
卷積神經網路又是怎樣解決這個問題的呢?主要有三個思路:
在使用CNN提取特徵時,到底使用哪一層的輸出作為最後的特徵呢?
答:倒數第二個全連接層的輸出才是最後我們要提取的特徵,也就是最後一個全連接層的輸入才是我們需要的特徵。
全連接層會忽視形狀。卷積層可以保持形狀不變。當輸入數據是圖像時,卷積層會以3維數據的形式接收輸入數據,並同樣以3維數據的形式輸出至下一層。因此,在CNN中,可以(有可能)正確理解圖像等具有形狀的數據。
CNN中,有時將 卷積層的輸入輸出數據稱為特徵圖(feature map) 。其中, 卷積層的輸入數據稱為輸入特徵圖(input feature map) , 輸出數據稱為輸出特徵圖(output feature map)。
卷積層進行的處理就是 卷積運算 。卷積運算相當於圖像處理中的「濾波器運算」。
濾波器相當於權重或者參數,濾波器數值都是學習出來的。 卷積層實現的是垂直邊緣檢測 。
邊緣檢測實際就是將圖像由亮到暗進行區分,即邊緣的過渡(edge transitions)。
卷積層對應到全連接層,左上角經過濾波器,得到的3,相當於一個神經元輸出為3.然後相當於,我們把輸入矩陣拉直為36個數據,但是我們只對其中的9個數據賦予了權重。
步幅為1 ,移動一個,得到一個1,相當於另一個神經單元的輸出是1.
並且使用的是同一個濾波器,對應到全連接層,就是權值共享。
在這個例子中,輸入數據是有高長方向的形狀的數據,濾波器也一樣,有高長方向上的維度。假設用(height, width)表示數據和濾波器的形狀,則在本例中,輸入大小是(4, 4),濾波器大小是(3, 3),輸出大小是(2, 2)。另外,有的文獻中也會用「核」這個詞來表示這里所說的「濾波器」。
對於輸入數據,卷積運算以一定間隔滑動濾波器的窗口並應用。這里所說的窗口是指圖7-4中灰色的3 × 3的部分。如圖7-4所示,將各個位置上濾
波器的元素和輸入的對應元素相乘,然後再求和(有時將這個計算稱為乘積累加運算)。然後,將這個結果保存到輸出的對應位置。將這個過程在所有位置都進行一遍,就可以得到卷積運算的輸出。
CNN中,濾波器的參數就對應之前的權重。並且,CNN中也存在偏置。
在進行卷積層的處理之前,有時要向輸入數據的周圍填入固定的數據(比如0等),這稱為填充(padding),是卷積運算中經常會用到的處理。比如,在圖7-6的例子中,對大小為(4, 4)的輸入數據應用了幅度為1的填充。「幅度為1的填充」是指用幅度為1像素的0填充周圍。
應用濾波器的位置間隔稱為 步幅(stride) 。
假設輸入大小為(H, W),濾波器大小為(FH, FW),輸出大小為(OH, OW),填充為P,步幅為S。
但是所設定的值必須使式(7.1)中的 和 分別可以除盡。當輸出大小無法除盡時(結果是小數時),需要採取報錯等對策。順便說一下,根據深度學習的框架的不同,當值無法除盡時,有時會向最接近的整數四捨五入,不進行報錯而繼續運行。
之前的卷積運算的例子都是以有高、長方向的2維形狀為對象的。但是,圖像是3維數據,除了高、長方向之外,還需要處理通道方向。
在3維數據的卷積運算中,輸入數據和濾波器的通道數要設為相同的值。
因此,作為4維數據,濾波器的權重數據要按(output_channel, input_channel, height, width)的順序書寫。比如,通道數為3、大小為5 × 5的濾
波器有20個時,可以寫成(20, 3, 5, 5)。
對於每個通道,均使用自己的權值矩陣進行處理,輸出時將多個通道所輸出的值進行加和即可。
卷積運算的批處理,需要將在各層間傳遞的數據保存為4維數據。具體地講,就是按(batch_num, channel, height, width)的順序保存數據。
這里需要注意的是,網路間傳遞的是4維數據,對這N個數據進行了卷積運算。也就是說,批處理將N次的處理匯總成了1次進行。
池化是縮小高、長方向上的空間的運算。比如,如圖7-14所示,進行將2 × 2的區域集約成1個元素的處理,縮小空間大小。
圖7-14的例子是按步幅2進行2 × 2的Max池化時的處理順序。「Max池化」是獲取最大值的運算,「2 × 2」表示目標區域的大小。如圖所示,從
2 × 2的區域中取出最大的元素。此外,這個例子中將步幅設為了2,所以2 × 2的窗口的移動間隔為2個元素。另外,一般來說,池化的窗口大小會和步幅設定成相同的值。比如,3 × 3的窗口的步幅會設為3,4 × 4的窗口的步幅會設為4等。
除了Max池化之外,還有Average池化等。相對於Max池化是從目標區域中取出最大值,Average池化則是計算目標區域的平均值。 在圖像識別領域,主要使用Max池化。 因此,本書中說到「池化層」時,指的是Max池化。
池化層的特徵
池化層有以下特徵。
沒有要學習的參數
池化層和卷積層不同,沒有要學習的參數。池化只是從目標區域中取最大值(或者平均值),所以不存在要學習的參數。
通道數不發生變化
經過池化運算,輸入數據和輸出數據的通道數不會發生變化。如圖7-15所示,計算是按通道獨立進行的。
對微小的位置變化具有魯棒性(健壯)
輸入數據發生微小偏差時,池化仍會返回相同的結果。因此,池化對輸入數據的微小偏差具有魯棒性。比如,3 × 3的池化的情況下,如圖
7-16所示,池化會吸收輸入數據的偏差(根據數據的不同,結果有可能不一致)。
經過卷積層和池化層之後,進行Flatten,然後丟到全連接前向傳播神經網路。
(找到一張圖片使得某個filter響應最大。相當於filter固定,未知的是輸入的圖片。)未知的是輸入的圖片???
k是第k個filter,x是我們要找的參數。?這里我不是很明白。我得理解應該是去尋找最具有代表性的特徵。
使用im2col來實現卷積層
卷積層的參數是需要學習的,但是池化層沒有參數需要學習。全連接層的參數需要訓練得到。
池化層不需要訓練參數。全連接層的參數最多。卷積核的個數逐漸增多。激活層的size,逐漸減少。
最大池化只是計算神經網路某一層的靜態屬性,沒有什麼需要學習的,它只是一個靜態屬性 。
像這樣展開之後,只需對展開的矩陣求各行的最大值,並轉換為合適的形狀即可(圖7-22)。
參數
• input_dim ― 輸入數據的維度:( 通道,高,長 )
• conv_param ― 卷積層的超參數(字典)。字典的關鍵字如下:
filter_num ― 濾波器的數量
filter_size ― 濾波器的大小
stride ― 步幅
pad ― 填充
• hidden_size ― 隱藏層(全連接)的神經元數量
• output_size ― 輸出層(全連接)的神經元數量
• weitght_int_std ― 初始化時權重的標准差
LeNet
LeNet在1998年被提出,是進行手寫數字識別的網路。如圖7-27所示,它有連續的卷積層和池化層(正確地講,是只「抽選元素」的子采樣層),最後經全連接層輸出結果。
和「現在的CNN」相比,LeNet有幾個不同點。第一個不同點在於激活函數。LeNet中使用sigmoid函數,而現在的CNN中主要使用ReLU函數。
此外,原始的LeNet中使用子采樣(subsampling)縮小中間數據的大小,而現在的CNN中Max池化是主流。
AlexNet
在LeNet問世20多年後,AlexNet被發布出來。AlexNet是引發深度學習熱潮的導火線,不過它的網路結構和LeNet基本上沒有什麼不同,如圖7-28所示。
AlexNet疊有多個卷積層和池化層,最後經由全連接層輸出結果。雖然結構上AlexNet和LeNet沒有大的不同,但有以下幾點差異。
• 激活函數使用ReLU。
• 使用進行局部正規化的LRN(Local Response Normalization)層。
• 使用Dropout
TF2.0實現卷積神經網路
valid意味著不填充,same是填充
or the SAME padding, the output height and width are computed as:
out_height = ceil(float(in_height) / float(strides[1]))
out_width = ceil(float(in_width) / float(strides[2]))
And
For the VALID padding, the output height and width are computed as:
out_height = ceil(float(in_height - filter_height + 1) / float(strides[1]))
out_width = ceil(float(in_width - filter_width + 1) / float(strides[2]))
因此,我們可以設定 padding 策略。在 tf.keras.layers.Conv2D 中,當我們將 padding 參數設為 same 時,會將周圍缺少的部分使用 0 補齊,使得輸出的矩陣大小和輸入一致。
4. 構建ResNet卷積神經網路
2015年,微軟亞洲研究院的何凱明團隊發布了一種特殊的卷積神經網路——殘差神經網路(ResNet)。在殘差神經網路出現之前,最深的深度神經網路只有二三十層左右,這該神經網路卻可以在實驗中輕松達到上百層甚至上千層,另外不會佔用過多訓練時間,也正因如此,圖像識別准確率有了顯著增強。此模型更是在同年的ImageNet大賽中,獲得圖像分類、定位、檢測三個項目的冠軍。在國際大賽上取得如此優異的成績,證明了殘差神經網路是個實用性強且優異的模型。在本研究中的貓狗二分類的實驗中,也是基於殘差神經網路來構建分類模型的。
在本文中我們將把kaggle貓狗數據集應用於ResNet-18和ResNet-50網路模型。使用Resnet來探究當前使用卷積神經網路的准確率。如圖4-1為ResNet的經典網路結構圖——ResNet-18。
ResNet-18都是由BasicBlock組成,從圖4-2也可得知50層及以上的ResNet網路模型由BottleBlock組成。在我們就需要將我們預處理過的數據集放入現有的Resnet-18和ResNet-50模型中去訓練,首先我們通過前面提到的圖像預處理把訓練圖像裁剪成一個96x96的正方形尺寸,然後輸入到我們的模型中,這里就介紹一下ResNet-18的網路模型的結構,因為ResNet50與第五章的ResNet-34模型結構相仿。
ResNet-18的模型結構為:首先第一層是一個7×7的卷積核,輸入特徵矩陣為[112,112,64],經過卷積核64,stride為2得到出入特徵矩陣[56,56,64]。第二層一開始是由一個3×3的池化層組成的,接著是2個殘差結構,一開始的輸入的特徵矩陣為[56,56,64],需要輸出的特徵矩陣shape為[28,28,128], 然而主分支與shortcut的輸出特徵矩陣shape必須相同,所以[56,56,64]這個特徵矩陣的高和寬從56通過主分支的stride為2來縮減為原來的一半即為28,再通過128個卷積核來改變特徵矩陣的深度。然而這里的shortcut加上了一個1x1的卷積核,stride也為2,通過這個stride,輸入的特徵矩陣的寬和高也縮減為原有的一半,同時通過128個卷積核將輸入的特徵矩陣的深度也變為了128。第三層,有2個殘差結構,輸入的特徵矩陣shape是[28,28,128],輸出特徵矩陣shape是[14,14,256], 然而主分支與shortcut的輸出特徵矩陣shape必須相同,所以[14,14,256]這個特徵矩陣的高和寬從14通過主分支的stride為2來縮減為原來的一半即為7,再通過128個卷積核來改變特徵矩陣的深度。然而這里的shortcut加上了一個1×1的卷積核,stride也為2,通過這個stride,輸入的特徵矩陣的寬和高也縮減為原有的一半,同時通過256個卷積核將輸入的特徵矩陣的深度也變為了256。第四層,有2個殘差結構,經過上述的相同的變化過程得到輸出的特徵矩陣為[7,7,512]。第五層,有2個殘差結構, 經過上述的相同的變化過程得到輸出的特徵矩陣為[1,1,512]。接著是平均池化和全連接層。
5. 卷積神經網路CNN(Convolutional Neural Network)
上圖計算過程為,首先我們可以將右邊進行卷積的可以稱為過濾器也可以叫做核,覆蓋到左邊第一個區域,然後分別按照對應位置相乘再相加,3*1+1*1+2*1+0*0+0*0+0*0+1*(-1)+8*(-1)+2*(-1)=-5;
按照上述的計算方法逐步按右移一個步長(步長可以設定為1,2,...等),然後按往下移,逐漸計算相應的值,得出最終的值。
如上圖顯示,對於第一個圖像矩陣對應的圖,一邊是白色,一邊是黑色,那麼中間就會存在一個垂直的邊緣,我們可以選擇一個垂直邊緣檢測過濾器,如乘法右邊的矩陣,那麼兩者做卷積後得出的圖會顯示如等號右邊的結果矩陣對應的灰度圖中間會有一個白色的中間帶,也就是檢測出來的邊緣,那為什麼感覺中間邊緣帶會比較寬呢?而不是很細的一個局域呢?原因是我們輸入的圖像只有6*6,過於小了,如果我們選擇輸出更大的尺寸的圖,那麼結果來說就是相對的一個細的邊緣檢測帶,也就將我們的垂直邊緣特徵提取出來了。
上述都是人工選擇過濾器的參數,隨著神經網路的發展我們可以利用反向傳播演算法來學習過濾器的參數
我們可以將卷積的顧慮器的數值變成一個參數,通過反向傳播演算法去學習,這樣學到的過濾器或者說卷積核就能夠識別到很多的特徵,而不是依靠手工選擇過濾器。
- padding 操作,卷積經常會出現兩個問題:
1.每經過一次卷積圖像都會縮小,如果卷積層很多的話,後面的圖像就縮的很小了;
2.邊緣像素利用次數只有一次,很明顯少於位於中間的像素,因此會損失邊緣圖像信息。
為了解決上述的問題,我們可以在圖像邊緣填充像素,也就是 padding 操作了。
如果我們設置在圖像邊緣填充的像素數為p,那麼經過卷積後的圖像是:(n+2p-f+1)x(n+2p-f+1).
如何去選擇p呢
通常有兩種選擇:
-Valid:也就是說不填充操作(no padding),因此如果我們有nxn的圖像,fxf的過濾器,那麼我們進行卷積nxn fxf=(n-f+1)x(n-f+1)的輸出圖像;
-Same:也就是填充後是輸出圖像的大小的與輸入相同,同樣就有(n+2p)x(n+2p) fxf=nxn,那麼可以算,n+2p-f+1=n,得到p=(f-1)/2。
通常對於過濾器的選擇有一個默認的准則就是選擇過濾器的尺寸是奇數的過濾器。
- 卷積步長設置(Strided COnvolution)
卷積步長也就是我們進行卷積操作時,過濾器每次移動的步長,上面我們介紹的卷積操作步長默認都是1,也就是說每次移動過濾器時我們是向右移動一格,或者向下移動一格。
但是我們可以對卷積進行步長的設置,也就是我們能夠對卷積移動的格數進行設置。同樣假如我們的圖像是nxn,過濾器是fxf,padding設置是p,步長strided設置為s,那麼我們進行卷積操作後輸出的圖像為((n+2p-f)/s+1)x((n+2p-f)/s+1),那麼這樣就會出現一個問題,如果計算結果不是整數怎麼辦?
一般是選擇向下取整,也就是說明,只有當我們的過濾器完全在圖像上能夠覆蓋時才對它進行計算,這是一個慣例。
實際上上述所述的操作在嚴格數學角度來說不是卷積的定義,卷積的定義上我們計算的時候在移動步長之前也就是對應元素相乘之前是需要對卷積核或者說我們的過濾器進行鏡像操作的,經過鏡像操作後再把對應元素進行相乘這才是嚴格意義上的卷積操作,在數學角度上來說這個操作不算嚴格的卷積操作應該是屬於互相關操作,但是在深度學習領域中,大家按照慣例都省略了反轉操作,也把這個操作叫做卷積操作
我們知道彩色圖像有RGB三個通道,因此對於輸入來說是一個三維的輸入,那麼對三維輸入的圖像如何進行卷積操作呢?
例子,如上圖我們輸入圖像假設為6×6×3,3代表有RGB三個通道channel,或者可以叫depth深度,過濾器的選擇為3×3×3,其中需要規定的是,顧慮器的channel必須與輸入圖像的channel相同,長寬沒有限制,那麼計算過程是,我們將過濾器的立體覆蓋在輸入,這樣對應的27個數對應相乘後相加得到一個數,對應到我們的輸出,因此這樣的方式進行卷積後我們得出的輸出層為4×4×1。如果我們有多個過濾器,比如我們分別用兩個過濾器一個提取垂直特徵,一個提取水平特徵,那麼輸出圖4×4×2 。也就是代表我們輸出的深度或者說通道與過濾器的個數是相等的。
第l層的卷積標記如下:
加入我們的過濾器是3×3×3規格的,如果我們設定10個過濾器,那麼需要學習的參數總數為每個過濾器為27個參數然後加上一個偏差bias那麼每個過濾器的參數為28個,所以十個過濾器的參數為280個。從這里也就可以看出,不管我們輸入的圖片大小是多大,我們都只需要計算這些參數,因此參數共享也就很容易理解了。
為了縮減模型的大小,提高計算速度,同時提高所提取特徵的魯棒性,我們經常會使用池化層。池化層的計算方式與卷積類似,只是我們需要對每一個通道都進行池化操作。
池化的方式一般有兩種:Max Pooling和Average Pooling。
上面為Max Pooling,那麼計算方法與卷積類似,首先設定超參數比如過濾器的大小與步長,然後覆蓋到對應格子上面,用最大值取代其值作為輸出的結果,例如上圖為過濾器選擇2×2,步長選擇為2,因此輸出就是2×2的維度,每個輸出格子都是過濾器對應維度上輸入的最大值。如果為平均池化,那麼就是選擇其間的平均值作為輸出的值。
因此從上面的過程我們看到,通過池化操作能夠縮小模型,同時能讓特徵值更加明顯,也就提高了提取特徵的魯棒性。
6. 怎樣用python構建一個卷積神經網路
用keras框架較為方便
首先安裝anaconda,然後腔升瞎通過pip安裝keras
7. 卷積神經網路
一般由卷積層,匯聚層,和全連接層交叉堆疊而成,使用反向傳播演算法進行訓練(反向傳播,再重新看一下)
卷積神經網路有三個結構上的特性:局部連接,權重共享以及子采樣
濾波器filter 卷積核convolution kernel
局部連接,其實就是根據時間,權重遞減 最後為0 參數就傳播不到遠處了
局部連接 乘以 濾波器 得特徵映射
互相關,是一個衡量兩個序列相關性的函數,
互相關和卷積的區別在於 卷積核僅僅是否進行翻轉,因此互相關也可以稱為 不翻轉卷積
使用卷積 是為了進行特徵抽取,卷積核 是否進行翻轉和其特徵抽取的能力無關。
當卷積核是可以學習的參數,卷積和互相關是等價的,因此,其實兩者差不多。
Tips:P是代表特徵映射