1. 程式人生 > >使用卷積神經網路進行圖片分類 1

使用卷積神經網路進行圖片分類 1

卷積神經網路原理

一、實驗介紹

1.1 實驗內容

本課程將會先帶你理解卷積神經網路的原理,瞭解卷積神經網路的一些特性。然後動手使用caffe深度學習框架訓練一個卷積神經網路模型,並用訓練好的模型進行圖片分類。

學習本課程之前,請先學習課程814 使用python實現深度神經網路以瞭解必要的基本概念,本實驗中涉及到的深度學習基本概念將不會再次闡述。同時建議學習課程744 深度學習初探——入門DL主流框架(該課為訓練營課程)中的caffe相關部分,但本課程中涉及到caffe的內容也會盡量講解。  

本實驗作為本課程的第一次實驗,將會向大家講解卷積神經網路的相關基本原理。除非你已經知道什麼是卷積神經網路,否則我強烈建議你仔細學習本次實驗,理解原理將非常有助於你在實際問題中合理地使用卷積神經網路。

1.2 實驗知識點

  • 卷積神經網路的結構

1.3 先學課程

  • 814 使用python實現深度神經網路(必學,否則可能無法理解本課程中的一些概念)
  • 744 深度學習初探——入門DL主流框架(選學)

1.4 實驗環境

  • python 2.7
  • caffe 1.0.0 (實驗樓環境中已經預先安裝)

二、實驗步驟

2.1 什麼是“卷積”

在課程814 使用python實現深度神經網路中,我們已經構建過深度神經網路,注意在那個網路中,除了啟用函式層和損失函式層之外,發揮主要作用的是全連線層,我們的網路引數全部都在全連線層中。那麼既然使用全連線層構成的神經網路就已經實現了對圖片的分類,為什麼我們還需要“卷積神經網路”呢?為了回答這個問題,我們先來了解到底什麼是卷積(convolution)

2.1.1 卷積操作

“卷積”這一詞在多個領域裡都有定義(比如訊號處理領域的傅立葉變換中也有卷積)。具體在影象處理領域,卷積操作是指使用一個小的“模板視窗”對一個圖片中的所有與模板大小相同的區域進行“卷積運算”。“卷積運算”其實很簡單,就是將模板中的每一個數字與圖片中相同大小區域的對應數字(畫素值)進行相乘,再求和。具體操作如下圖:

此處輸入圖片的描述“模板視窗”每移動到一個位置,就和圖片中的對應元素進行一次卷積運算,注意我們一般把“模板視窗”稱為卷積核(kernel)

比如在第一個位置,圖片上的四個畫素值為[[0,0],[1,1]], 而卷積核中的數值為[[-1,1],[-1,1]], 對應元素相乘再求和,得到0*-1+0*1+1*-1+1*1=0

比如在第二個位置,圖片上的四個畫素值為[[0,0],[1,0]], 對應元素相乘再求和,得到0*-1+0*1+1*-1+0*1=-1

對圖片中的所有可能位置進行卷積操作,就得到了最終的卷積結果。

2.1.2 為什麼卷積操作適合用來處理影象

上圖中的卷積核,其實是經過精心設定的。觀察被卷積的影象和卷積結果你會發現,該卷積核其實可以用來檢測圖片中的垂直邊緣。如果卷積後得到的數字絕對值大,就說明圖片上的對應地方有一條垂直方向的邊緣(即畫素數值變化較大)。如果卷積後得到的數字絕對值很小,則說明圖片上的對應地方畫素值變化不大,沒有邊緣存在。同樣的道理,你可以構造一個檢測水平方向邊緣的卷積核:此處輸入圖片的描述你可以嘗試用這個卷積核去對上面的圖片進行卷積操作,驗證這個卷積核是不是檢測出了水平方向的圖片邊緣。卷積操作還可以有更多強大的功能,在數字影象處理中經常會用到。

說到這裡,你也許已經能夠體會為什麼我們需要卷積神經網路。對於將整個圖片視為一個向量的全連線層來說,它忽略了影象本身所具有的的“二維空間特性”,或者說區域性特性。而卷積操作則十分擅長處理這種區域性特性,能夠更有效地提取出圖片中的更多有用資訊(比如圖片中的邊緣)。實際上,卷積神經網路幾乎已經成為了神經網路中處理影象的標配。

2.2 神經網路中的卷積層

在具體的將卷積操作運用到神經網路的過程當中,有許多細節需要注意(包括很多超引數)。首先需要明確的是,和課程814 使用python實現深度神經網路中介紹的一樣,卷積層中的引數(即卷積核中的每個數字)也是通過學習演算法(隨機梯度下降演算法)學習得到的,不需要手工設定。

2.2.1 特徵個數

一個卷積核,只能檢測一種特徵(feature)(比如垂直方向的邊緣),而圖片中的資訊往往很複雜,一個卷積核顯然不夠。所以神經網路中,一個卷積層往往會有多個卷積核,這樣卷積層的輸出就會有多層。如下圖:此處輸入圖片的描述

為了簡便,在一些深度學習框架(比如本課程會用到的caffe)中,在運算時可以將特徵個數與影象通道數等同看待。所以對於一個通道數為1的圖片,若卷積層特徵個數為3,則可將輸出的卷積結果視為通道數為3的圖片。對於一個通道數為3的圖片(此時,卷積核是一個三維的“體”),若卷積層特徵個數為16,則可將輸出的卷積結果視為通道數為16的圖片。

2.2.2 stride

上面的示意圖中,卷積核在水平和垂直方向上每次都移動一個畫素的距離,在實際的卷積神經網路中,卷積核可能一次移動不止一個畫素。卷積核每次移動的“步長”被稱為stridestride的大小會影響最後卷積結果的大小。比如將水平和垂直方向的stride都從1改成2,原來的示意圖就會變成這樣:此處輸入圖片的描述

2.2.3 卷積核尺寸(kernel size)

上面的示意圖中卷積核的尺寸是2x2, 但在實際當中,很少見到邊長為偶數的卷積核。且一般卷積核的最小邊長為3(也存在邊長為1的卷積核,你也許會覺得奇怪,邊長為1的卷積層與全連線層豈不是幾乎沒有區別了,這個問題保留在這裡,我們以後也許會來回答這個問題)。

2.2.4 padding

觀察上面的圖片你會發現,卷積操作得到的卷積結果與原來的圖片相比尺寸變小了。這樣會帶來一個問題,有的卷積神經網路會非常“深”(比如幾十層,甚至上百上千層)如果每經過一個卷積層我們的圖片都變小一點,那到最後,有可能我們的圖片都沒有卷積核大,沒辦法繼續卷積下去了。為了解決這個問題,人們對卷積層引入了邊緣填充(padding):在卷積前,先將圖片擴大一點點,然後再進行卷積。對於擴大部分,一般會填入0值。如下圖(為了作圖方便,卷積核與卷積結果之間只使用了一個箭頭進行指示):此處輸入圖片的描述

2.2.5 計算卷積結果的尺寸

對於一個尺寸為w*w的正方形圖片,卷積結果的尺寸(假設其尺寸是o*o),會受到上面的特徵個數feature步長stride卷積核尺寸kernel邊緣padding四個超引數的影響。你可以嘗試一下推導卷積結果尺寸的公式,其實很簡單:

o=(w+2*padding-kernel)/stride+1 且輸出結果的通道數等於feature

這個公式只適合於輸入圖片為正方形,卷積核也為正方形,步長在水平和垂直方向一致,padding在四個方向都一樣的情況(不滿足這些條件的情況你可以自己推導)。比如對於尺寸為17*17的輸入圖片,padding為1,kernel的尺寸為3*3, stride為1,則卷積之後的輸出邊長為:(17+2*1-3)/1+1=17,沒有變化。

注意根據上面的公式,你會發現卷積層的幾個超引數之間需要滿足如下關係:(w+2*padding-kernel)%stride==0其中的%為取模符號,即(w+2*padding-kernel)需要是stride的整數倍,不然無法除盡。

2.3 卷積層的實現

卷積層相對全連線層來說比較複雜(從其中超引數的個數很多你就能看出來)。你可以接著課程814嘗試自己使用python實現卷積層,其實原理都是一樣的,關鍵都是運用鏈式法則去求梯度。不過除非你有特別的興趣,不然不推薦自己“造輪子”(作者自己造了一個,如果你對程式碼有興趣,請到Github檢視)。幸運的是好多現有的深度學習框架已經幫我們實現好了卷積層(比如本課程會用到的caffe),直接拿過來用就好了。

三、實驗總結

本次實驗我們學習了卷積操作的基本概念。掌握了這些基本概念,之後的實驗對你來說會非常容易。如果你對其中的一些概念還感到困惑,不用感到受挫,剛開始接觸新東西都會有這種感覺。請你再仔細思考一遍這些概念的含義,然後去繼續做之後的實驗,當碰到相應的概念時就回過頭來看一看,相信這些對你來說都不難掌握。

本次實驗,我們學習了:

  • 對於影象處理,卷積層比全連線層更有優勢。
  • 可以將使用卷積核對影象進行的卷積操作視作對影象提取特徵的過程。
  • 卷積層中含有多個超引數,包括特徵數feature、卷積核尺寸kernel、邊緣填充padding、卷積步長stride。

四、課後作業

以下的作業都能根據上面的文件推測出答案。

  1. 請你設計一個卷積核,用來檢測圖片對角線方向的邊緣。
  2. 請你計算,對於一個3*100*100(3通道圖片)尺寸的圖片,使用padding=1(四個方向都填充一個畫素的長度), kernel=7(kernel為正方形), stride=5(水平和垂直方向的stride相同)的卷積層進行卷積後,得到的輸出的尺寸。