我對卷積神經網絡(CNN)的理解(包含例子)
Introduce
卷積神經網絡(convolutional neural networks),簡稱CNN。卷積神經網絡相比於人工神經網絡而言更適合於圖像識別、語音識別等任務。本文主要涉及卷積神經網絡的概念介紹,首先介紹卷積神經網絡相比於人工神經網絡的優勢,其次介紹卷積神經網絡的基本結構,最后我們分別介紹神經網絡的各個部件從而完整的了解CNN。
以下均為初學者筆記,若有錯誤請不吝指出。
Advantages of Convolutional Neural Networks
就拿圖像舉例來說,一張圖像的大小為寬X高X通道數(一般是三色通道)。假設有一組圖像的大小為n,那么如果我們用傳統的神經網絡來處理這張圖像的畫,輸入層需要n個神經元,並且若采用全連接結構的話則會有很多很多的權重參數,這對於網絡的訓練來說是非常難且耗時的。並且如果圖像非常復雜,我們不可能通過不斷增加隱層的數量來捕獲更加高級的圖像特征,因為隱層數過多的神經網絡在梯度反向傳播的時候可能會出問題,比如之前講過的梯度爆炸和梯度消失問題。因此傳統神經網絡比較不適合處理圖像任務。反觀卷積神經網絡,其采用了局部連接、權重共享(即卷積核只與一個窗口進行連接,並且該卷積核可由多個窗口共享)以及池化的設計思路,三個策略的疊加使用大大減少了網絡中非常多非常多的不必要的權值參數,使得網絡訓練變得容易。本文余下篇幅將更加全面的介紹CNN,以幫助讀者更加通俗地理解CNN相比傳統神經網絡所具有的優勢。
Basic Structure of Convolution Neural Network
卷積神經網絡包含卷積層(Convolution)、非線性激活層(常用ReLU層)、池化層(pooling)、全連接層(Full-Connected)和Softmax層。卷積神經網絡的基本結構如下圖所示。
文章余下內容將結合具體例子並且按照上述各個部分具體展開介紹。。
舉個梨子: 假設我們要識別下述圖片(菱形)是菱形呀還是三角形呀,還是正方形長方形呀等等。人眼一看肯定想都不用想就知道是菱形了。那么,計算機要怎么才能知道這個圖片是個菱形呢?其實,計算機識別的具體思路是這樣子的: 菱形都有什么特征呀,這種圖片上有沒有滿足菱形的幾個特征呀?帶着這幾個問題呀,計算機首先需要學習菱形具有的幾個特征(對應CNN的訓練過程),其次計算機需要去圖上看是不是能找到菱形的特征,如果都滿足了,那么就判定這是個菱形(對應CNN的預測過程)。以下從該例子逐步介紹CNN模型各個部件所做的事情。
卷積層(Convolution)
卷積層是在做什么呢?卷積層就是利用攜帶某特征的卷積核在圖上逐步匹配看看是否具有該卷積核攜帶的特征。 看了上面對於卷積層的描述(個人理解),我們腦子里肯定還會有兩個疑問。第一,卷積核又是啥東西,怎么攜帶圖片的特征的?第二,卷積核在圖上逐步匹配(就是卷積運算)尋找是否具有該特征,又是怎么匹配的?首先,我們來看第一個問題,卷積核是什么呢? 其實,卷積核就是一個權值矩陣,每個元素為對應的像素值,卷積核可以表示圖片中的邊緣特征,如正負斜線,豎直線和橫直線等等(這些斜線、直線或者曲線等等就是圖片最基本的局部特征,更高階的全局特征(如正方形,長方形等等)捕獲可以通過多層卷積實現)。以下分別展示正斜線、負斜線、豎直線以及橫直線的3X3卷積核,以幫助我們更近一步理解卷積核的概念。
對於第二個問題,怎么判斷圖上是否存在如卷積核所描述的特征呢?即怎么判斷圖上有正斜線、負斜線呢? 其實這是通過在圖上移動窗口(窗口大小=卷積核大小),並且每次都將窗口與卷積核進行卷積運算實現的(其實就是兩個矩陣對應位置相乘求和再取平均!!!)。這樣解釋可能有點抽象,我們結合具體例子來看。假設我們要在上述菱形圖中尋找正斜線(如上圖中3X3的卷積核),那要怎么找呢?首先用3X3的窗口遍歷整個圖,每次都將對應卷積核與窗口進行卷積運算並將所得值依次按序填入新矩陣中,這個新的矩陣我們稱之為特征圖(feature map)。特征圖用來判斷原始圖中對應位置與卷積核的匹配程度,越大則表明原始圖中的這個位置越可能具有該卷積核所攜帶的特征。 現在我們通過代表正斜線特征的卷積核與原始圖片中第一個窗口進行卷積運算來說明卷積運算的過程,一個簡單的卷積示例如下:
如上圖所示我們選取原始圖片中的第一個窗口與正斜線卷積核進行卷積運算,首先兩個矩陣對應位置相乘得到一個新的矩陣(其實我們可以發現,如果對應位置的兩個像素越相近,那么對應相乘起來的值也就越大),再對新的矩陣求和取平均之后可以得到一個代表匹配程度的數值(同理,如果整個窗口與卷積核相似的像素越多,則得到的該數值也就越大),這個數值稍后將填入特征圖的第一行第一列元素,代表原始圖中第一個窗口與卷積核的匹配程度為0.11。
理解了卷積運算之后,我們從左到右,從上到下移動窗口分別與選定卷積核做卷積運算(這邊請注意,窗口的移動步長是可以設置的,這邊默認步長為1),最后可以得到關於該卷積核的特征圖(特征圖中的元素描述圖片對應窗口與該卷積核的匹配程度)。最終得到的特征圖(feature map)如下(可以理解成是一個特征提取過程圖片壓縮過程,作為后續卷積層的輸入):
值得說明的一點是:feature map上的每個元素代表卷積核與原始圖種對應位置特征的匹配程度,值越大原始圖中對應位置與卷積核攜帶的特征越相似。並且,
每一個卷積核與原始圖片進行卷積運算都能得到一個對應的特征圖(feature map),卷積核有多少個,經過卷積層運算之后得到的特征圖就有多少個。
非線性激活層(ReLU)
與傳統神經網絡一樣,卷積神經網絡也需要使用激活函數來融入非線性特征(我覺得卷積運算應該是線性的,而且純做線性變換的也沒什么意思)。而卷積神經網絡中現在比較常用的是ReLU激活函數(其實ReLU函數就是>=0的值不變,小於0的值變為0),ReLU激活函數的介紹可以參考我上一篇博客Pytorch_第九篇_神經網絡中常用的激活函數。那卷積神經網絡中的非線性激活層是怎么作用的呢?我們還是通過上述例子來進行說明:
如上圖所示,對特征圖中每個元素進行ReLU激活,可以得到右圖中特征圖。我們可以發現多了很多0(需要注意的是,ReLU激活之后的數據量比原始圖少了很多很多,后面可以通過池化層進一步削減數據量,畢竟深度學習圖片領域的訓練數據都是又大又多的,因此時間效率還是比較重要的),即我們通過ReLU激活將負相關的數據舍棄了,使得矩陣變成了一個更加稀疏的矩陣,操作起來也更加方便。(並且若是在大規模網絡中,對稀疏矩陣的處理也更加快速,有效率!!)
池化層(pooling)
在介紹池化層之前,我們先捋一捋到現在我們做了什么。卷積層通過卷積運算提取特征,得到比原始圖更小的特征圖,之后我們再通過ReLU層將特征圖中的負相關的數據置為0,得到了一個更加稀疏的特征矩陣,數據量進一步減少了,但是這還不夠,我們這兒通過池化層進一步削減數據量。
首先,我們需要先了解一下池化的概念。有兩種池化方式,分別是最大池化(Max Pooling)、平均池化(Average Pooling)。顧名思義,最大池化就是取最大值,平均池化就是取平均值。其次我們通過上述同樣的例子來理解以下池化層具體做了什么操作。 假設池化窗口我們設置為2X2,類比於卷積層在滑動窗口上不斷做卷積運算,池化層就是在滑動窗口上不斷做池化運算,那池化運算怎么做呢(最大池化,取窗口內的最大值;平均池化,取窗口內的平均值)?以最大池化為例,如下圖所示:
(看着上面這個圖,應該很容易理解最大池化怎么做了吧?)
由於最大池化保留了每個小窗口內的最大值,因此可以認為最大池化相當於保留了窗口內的最佳匹配結果。現在從圖片壓縮角度來看看從卷積層、ReLU層到現在的池化層,我們原始的輸入大小是怎么變化的。原始輸入是5X5的一個矩陣(先假設通道為1,即不算三原色),經過卷積層、ReLU層之后變為3X3稀疏矩陣,再經過池化層之后變為了2X2矩陣,是我們肉眼可見的壓縮啊!!其實每一層也可以理解成是在做特征提取,只是最開始提取的可能是比較局部的特征(比如邊緣啊,斜邊啊啥的),而層層疊加之后提取的可能是比較全局的一個特征,比較形狀啊啥的,對於CNN各層(卷積、ReLU、池化),我個人大概是這么理解的。(以上各層是可以反復使用的,取決於我們的具體需求)
全連接層(Full-Connected)
在講全連接層之前,我們需要知道全連接層之前的所有操作都是在做一個特征提取,提取出來的特征輸入全連接層,利用全連接層來判定該圖片是屬於哪一個類型的圖片(其實就是分類,如菱形、正方形、長方形等等)。之前在pytorch_第四篇_使用pytorch快速搭建神經網絡實現二分類任務(包含示例)我們學習過利用神經網絡來進行分類,那卷積網絡中的全連接層與傳統神經網絡是類似的。接受樣本的特征作為輸入,輸出樣本所屬各個類的概率,這是全連接層所做的事情。那卷積神經網絡中的特征怎么來呢?別忘了,全連接層之前都是在做特征提取,如上述例子所示,假設我們最終得到了一個2X2的特征圖,我們把特征圖攤開來排成一排,也就意味着我們提取了原始圖片的4個特征,這4個特征值輸入全連接層可以幫助我們進行圖片的分類。該層的結構就和傳統的神經網絡類似(全連接),這里不再贅述。
Softmax層
假設每個樣本有一個隸屬向量V,長度為類數,元素值代表該樣本屬於對應類別的概率,我們可以利用softmax函數來進行一個概率歸一化。softmax函數如下所示(對v中第i個向量做歸一化操作,即該元素的指數,與向量中所有元素指數和的比值):
由於多分類任務中模型輸出樣本對多個類的隸屬概率,因此我們再最后一層加入Softmax函數來進行一個概率歸一化。