深度學習:CNN原理
想必剛踏入深度學習 Computer Vision(CV)領域的各位常常會聽到CNN這個名詞,每當跟朋友討論時大家總會說:『喔!我都用CNN來做圖像辨識』,到底CNN有什麼魔力讓大家趨之若鶩,今天就讓我們來一探究竟。
ANN(Artificial neural network)
接觸CNN前,相信大家對一般的 Fully connected(FC)的結構都有一定的認識,還不熟的朋友也不用擔心,讓我們來快速回顧一下。
一般的神經網路由三個部分組成,分別是輸入層(Input Layers)、隱藏層(Hidden Layers)以及輸出層 (Output Layers)。
輸入層
輸入層顧名思義就是輸入資料(Data)的特徵值 (Features),舉個例來說,今天要預測一個人是男生還是女生,我們有的資料可能是這個人的身高、體重、髮長,而身高、體重、髮長就是你要放入輸入層的特徵值。
隱藏層
隱藏層說穿了就是在做運算,由神經元(Neuron)組成,透過前向傳播(Forward propagation) 計算出我們的Output值。
輸出層
而輸出層則是透過輸入特徵,經過隱藏層的運算所得到的預測值,我們藉由縮小預測值與實際標註值(Label),更新我們隱藏層的參數,最終訓練出一組權重(weights)。
什麼是CNN (Convolutional Neural Network)?
CNN概念
既然有了一般的NN層,為什麼我們還要CNN呢?這裡有兩個重要的觀念要跟大家分享
權值共享
讓我們來想想,今天假如是一般的FC架構,我們輸入一張28*28*1的灰階照片(784個特徵),隱藏層使用100個神經元,那麼我們需要多少個參數?答案是:
100*784 (weights)+100 (bias)= 78500個參數
哇!單單一層隱藏層參數就瞬間爆量,然而,如果我們使用CNN層的話情況就有所不同了。CNN權值共享的概念可以這樣想像,在一般的圖像內有許多的特徵是相同的,如特定的輪廓或線條,那我們就可以讓相同幾個神經元組成的卷積核去學這個特徵,透過滑動窗口對整張圖片進行卷積,進而達到節省參數的效果,聽起來有有點抽象?別擔心,詳細原理容我留到下方解釋。
保留位置資訊
CNN還有一大特色就是能保留圖像的位置資訊,不難想像圖片中的像素 (Pixels)與其鄰近的像素會有一定的關聯度,如果我們使用FC的結構來訓練圖像資訊的話,要先通過一個展開(Flatten)的步驟,把高維的資訊拉成一條直線,如此一來就會大量失去特徵之間的空間資訊,效果當然會大打折扣。
CNN原理
那究竟CNN是怎麼做到權值共享與保留位置資訊的呢?我們先用簡短兩句話詮釋CNN中卷積(Convolution)的基本概念:
透過卷積核(Kernels)滑動對圖像做訊息提取,並藉由步長(Strides)與填充 (Padding)控制圖像的長寬
卷積核
卷積核(Kernel)又稱為Filters、Features Detectors
我們可以藉由選擇Kernel的張數控制 Feature maps (圖像經由Kernel卷積後的結果,也就是下圖中粉紅色的部分)的深度,藉由調整Kernel大小決定Kernels的特徵接受域 (Receptive field)。
Kernel的起始值與運算
上圖中黃色區塊就是一個3*3的Kernel,其中的值就是我們預訓練的權重,通常用常態分佈隨機產生,再經由訓練更新。大家不要誤會圖中的1,0是我們設的,其只是為了計算方便,不然應該都是一些隨機或常態分佈的小數。
而卷積是怎麼完成的呢?我們觀察圖中可以發現3*3的Kernel每次對到我們圖像中的像素也是3*3,藉由各點相乘後,相加算出一個值,再往下一步走(先往右走,再往下走),直到走完整張的圖像。
Kernel的張數
控制張數主要就是控制學習的參數量,沒有一定幾張就是對的,常見是16、32或64,如果我們使用16張Kernels就能達到很好的效果,那也就不需要浪費額外的參數去增加學習與計算量。
Kernel大小
Kernel大小與其Receptive field有關,Receptive field直觀來說就是Kernel提取資訊的尺度,要是我們預偵測的主體在整張圖像裡的比例很大,結果我們都選用很小的Kernel來卷積,那效果可能就不是這麼好,同理,要是主體很小卻都用很大的Kernel來卷積,想必也不是這麼妥當。現在普遍流行的方式是選用不同大小的Kernel對圖像做卷積後,再把輸出的Feature maps合併或平均。常見的Kernel大小有1*1, 3*3, 5*5, 7*7。然而也有人提出,兩層3*3的Kernel 卷積與一層的5*5Kernel 卷積擁有相近的Receptive field,並且使用較少的參數量,因此大家不妨去嘗試看看不同組合的效果。
小知識:為什麼Kernel大小都是奇數呢?其實偶數也可以,但基數Kernel有幾個先天上的優勢,第一個原因是由於基數的卷積核有中心點,較容易對齊確認位置資訊,再者是因為基數的卷積核能確保Padding的對稱性(下文會詳細說明)。
步長
步長(Strides)為控制圖像長寬尺寸的方式之一,下圖中的Kernel步長分別為1、2,可以觀察到輸出的Feature map大小也不同,雖然通常長寬上的步長會設為相等,但我們也可以透過不同的長寬步長控制Feature map不同維度尺度的變化。
填充
填充 (Padding)是透過在圖像周圍補值為0的像素,其與Strides及Kernel 尺寸決定輸出Feature map的大小。下圖為3*3的Kernel, Stride為 『1』,Padding也為 『1』,可以發現輸出的Feature map與輸入的圖像擁有一樣的尺寸。
而通常Padding 又可以分為兩類,分別為:
Same Padding
『Same Padding』在Stride為1時,會讓輸出Feature map與輸入圖像維持一樣的尺寸,可參考下方程式碼。而當Stride大於1時,輸出Feature map寬、高等於輸入影像寬、高/Stride(小數值無條件進位)。
Valid Padding
『Valid Padding』不會特別去補邊,因此會讓輸出的Feature map尺寸下降,而當遇到卷積無法完整卷積的狀況則會直接捨棄多出來的像素。
公式化輸出尺寸如下:
SAME Padding
Valid Padding
輸出Feature map尺寸
卷積過後Feature map尺寸可藉由下方公式計算,其中 input=輸入圖像、p=Padding、f=Filters size、s=Strides。如果我們使用3*3 filter size, Padding =1, Stride=1,經過計算後就會發現Output=Input。
Output = (Input+2p-f)/s+1
CNN圖像辨識
好了!相信目前為止大家對CNN有了一定的認識,不過要構成一個較為完整的圖像辨識模型,我們還需要了解幾個步驟。
上圖替我們了展示了一個簡單的CNN圖像辨識模型架構,主要可以拆解為:
[卷積層→激勵函數(activation function)→Batch Normalization]=卷積組合
輸入圖像→[卷積組合→最大池化(Max Pooling)]*n→攤平(Flatten)→全連接層(Fully Connected layers)→分類
輸入圖像
一般來說CNN的輸入圖像為四維的Tensor
Tensorflow:[Batch_size,Height,Width,Channels]
Pytorch:[Batch_size,Channels,Height,Width]
Batch_size是你的一個Batch放了幾張照片,可以不用先設定,height、width就是輸入圖像的長寬尺寸,channels指輸入圖像的深度,一般RGB彩色圖像為3,灰階圖為1。
卷積組合
卷積層就如同我們上面所敘述的,通常還會經過激勵函數(增加非線性性)與Batch Normalization(加速收斂並同時達到一定的regularization效果),激勵函數與Batch Normalization的細節會另外再介紹。
最大池化
常見Pooling 為 Average Pooling 與 Max Pooling,其中又以Max Pooling 最常見,其原理是透過window對應Feature map並提取其最大值。Max Pooling主要用於提取重要特徵、加速收斂並縮小Feature map尺寸。通常都會使用2*2的window,並且設置Stride為2,如此一來output size就會變為原本的1/2。
不過近期也有諸多學者提出,Max Pooling會導致大量特徵消失,因此逐漸採用其他方式代替Max Pooling來降低Feature map尺度。
攤平
攤平(Flatten)這個步驟主要是要銜接CNN層與全連接層,主要是因為FC層需要一維的輸入,常見其他方式還有Global average pooling。
全連接層
全連接層(FC)主要在做最後的特徵提取,並且利用最後一層FC當作分類器。
分類
那要怎麼使用FC最後一層作為分類器呢?假如我們要分的類別有10類,那FC最後一層就會接10個神經元,並且經過Softmax function。下圖為Softmax原理,數值經過softmax function後,其加總值會變為1,因此,我們可以把各項的輸出值當作機率,而目標就是要縮小預測機率值與實際Label值。以下圖為例,預測輸出為[0.7,0.2,0.1],Label可能為[1,0,0],因此我們要讓[0.7]去接近[1],實際做法是用Cross Entropy計算。
Cross Entropy 常用在分類器的Loss Function上面,相較於Mean Square Error(MSE)更能凸顯機率分佈之間的差異,之後有時間再來細談。由於我們是多類的問題,所以使用Categorical Cross Entropy。
Softmax
Cross Entropy
實際練習
Tensorflow
Keras
總結
今天為各位介紹了CNN的基本架構,並用Tensorflow、Keras簡單實作,之後會再帶大家深入探討一些細節觀念,與經典的CNN架構,有問題的朋友們都歡迎留言或私訊討論。