深度學習:CNN原理

Cinnamon AI Taiwan
11 min readJun 5, 2019

--

想必剛踏入深度學習 Computer Vision(CV)領域的各位常常會聽到CNN這個名詞,每當跟朋友討論時大家總會說:『喔!我都用CNN來做圖像辨識』,到底CNN有什麼魔力讓大家趨之若鶩,今天就讓我們來一探究竟。

ANN(Artificial neural network)

接觸CNN前,相信大家對一般的 Fully connected(FC)的結構都有一定的認識,還不熟的朋友也不用擔心,讓我們來快速回顧一下。

Fully connected layers[Resource]

一般的神經網路由三個部分組成,分別是輸入層(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)。

滑動卷積的原理[Source]

Kernel的起始值與運算

上圖中黃色區塊就是一個3*3的Kernel,其中的值就是我們預訓練的權重,通常用常態分佈隨機產生,再經由訓練更新。大家不要誤會圖中的1,0是我們設的,其只是為了計算方便,不然應該都是一些隨機或常態分佈的小數。

而卷積是怎麼完成的呢?我們觀察圖中可以發現3*3的Kernel每次對到我們圖像中的像素也是3*3,藉由各點相乘後,相加算出一個值,再往下一步走(先往右走,再往下走),直到走完整張的圖像。

卷積運算[Source]

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不同維度尺度的變化。

不同步長造成輸出Feature map大小的差異[Source]

填充

填充 (Padding)是透過在圖像周圍補值為0的像素,其與Strides及Kernel 尺寸決定輸出Feature map的大小。下圖為3*3的Kernel, Stride為 『1』,Padding也為 『1』,可以發現輸出的Feature map與輸入的圖像擁有一樣的尺寸。

Padding為1就是在圖像周圍補一圈值為0的像素[Source]

而通常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圖像辨識模型架構[Source]

上圖替我們了展示了一個簡單的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尺度。

Maxpooling[Source]

攤平

攤平(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

Softmax原理[Source]

Cross Entropy

Categorical Cross Entropy [Source]

實際練習

Tensorflow

Keras

總結

今天為各位介紹了CNN的基本架構,並用Tensorflow、Keras簡單實作,之後會再帶大家深入探討一些細節觀念,與經典的CNN架構,有問題的朋友們都歡迎留言或私訊討論。

--

--

Cinnamon AI Taiwan
Cinnamon AI Taiwan

No responses yet