人臉檢測及識別python實現系列(4)——卷積神經網絡(CNN)入門


人臉檢測及識別python實現系列(4)——卷積神經網絡(CNN)入門

      上篇博文我們准備好了2000張訓練數據,接下來的幾節我們將詳細講述如何利用這些數據訓練我們的識別模型。前面說過,原博文給出的訓練程序使用的是keras庫,對我的機器來說就是tensorflow版的keras。訓練程序建立了一個包含4個卷積層的神經網絡(CNN),程序利用這個網絡訓練我的人臉識別模型,並將最終訓練結果保存到硬盤上。在我們實際動手操練之前我們必須先弄明白一個問題——什么是卷積神經網絡(CNN)?

      CNN(Convolutional Neural Network)——卷積神經網絡,人工神經網絡(Neural Network,NN)的一種,其它還有RNN、DNN等類型,而CNN就是利用卷積進行濾波的神經網絡。換句話說,CNN就是卷積神經網絡。網上關於CNN的資料非常多,度娘一搜一大堆,良莠不齊,有不少資料過於艱深,對於剛入行的小白來說一上來看這種資料會迷失方向,產生極強的挫折感,有可能會讓你失去學習的信心和興趣。作為一個過來人,我對此深有體會。幸運的是,我還是找到了一些關於CNN講得很不錯的資料,首先是這個:

卷積神經網絡詳解 (1)

知乎上專欄作者張覺非的文章,講得很不錯,比較通俗。微信公眾號“新智元”轉發了此文,上面給出的鏈接就是轉發地址,其原文鏈接為:https://zhuanlan.zhihu.com/p/25249694,不過原文鏈接有些圖片顯示不清楚,不知為何?如果你能夠顯示完整圖片,建議直接看原文,轉發文章與原文有些區別,並且代碼不能直接粘貼。然后我們接着看這個:

一個簡單的例子:離散卷積 (2)

其實,對於圖像處理——離散卷積屬於常用算法,這篇文章對利用卷積對圖像濾波講得比上一篇文章更淺顯易懂,且只講了這一點內容,很短,所以建議上篇文章看不下去的時候先轉頭看看這個再接着看上一篇,會有不錯的效果。當然,對於喜歡追根究底的同學來說,僅看上面這兩篇文章是遠遠不夠的,可能你和我一樣對於什么是卷積這個概念還不是很清楚,那么請接下來移步如下鏈接,看看他們對卷積的討論和理解:

怎樣通俗易懂的解釋卷積 (3)

基本上這三篇文章就能基本了解CNN是怎么回事,能夠看懂我在下一篇博文將要貼出的訓練程序代碼了。

      首先,關於什么是卷積,文章(3)有一牛人用一句話總結得很好:卷積就是帶權的積分,看下面的一維卷積公式:

函數值與權值的乘積相加即可得到卷積值c(x),換句話說,我們對函數值的加權疊加,即可得到x處的卷積值。CNN利用的是多維卷積,但原理一樣,不多說了,同時建議不要過多糾纏這個概念,理解就好,以后若作科研再作深入了解。對於圖像處理,CNN會對輸入圖像矩陣化,然后從矩陣第一個元素開始逐一進行卷積運算。在這里進行卷積運算的矩陣元素值即為,而則被稱為卷積核或者濾波器,需求不同我們選用的濾波器會有所不同,其卷積效果會不同。比如均值濾波器(average filter)會將圖像模糊,而拉普拉斯濾波器(Laplacian filter)則會將圖像局部細節增強。但假如我們既不想將圖像模糊又不想將圖像增強,而我們有其它古怪的需求呢?比如,我們正在做的人臉識別,如果輸入的是我的臉部圖像,經過CNN卷積處理后我想得到一個固定數值0來代表我;而輸入我閨女的圖像時,得到另一個數值1來代表她,這種需求我們該怎么辦?這種情況下,我們就需要從一個隨機濾波器開始,讓CNN根據我們的需求利用某種算法調整濾波器使其逐漸接近目標,即能夠根據輸入圖像的不同准確地輸出0或者1這兩個數值。那么CNN是怎么做到的呢?

      要想弄明白這個問題,我們必須先了解一下什么是人工神經網絡(NN,Neural Network)?人工神經網絡是一種計算模型,是由多層、每層多個人工神經元組成的復雜網絡。單個人工神經元的結構見下圖(該圖來自百度圖片,稍作修改):

 

其中,x1——xm為神經元的輸入,w1-wm則是權值,b為偏置標量(可理解為線性方程的截距),我們對x1-xm逐一加權(w1-wm)求和后得到卷積值,卷積值與偏置值b相加得到c,我們再將c輸出給“激活函數f(c)”,最終我們得到人工神經元的輸出a,即:

a = f(c)

需要特別交代的是:c = wTx+b為上述計算過程的向量表達形式,這樣可以讓公式看起來比較簡潔(或者更高大上些)。其中w、x分別代表權值矩陣和輸入數據矩陣,wT為w的轉置矩陣。簡單說就是我們將矩陣w的“行列”進行了轉換,“列”變成了“行”后得到轉置矩陣wT,這樣即可實現w和x的逐個元素相乘疊加,其本質就是矩陣乘法。不懂的可以度娘查找矩陣乘法,很簡單,就不多說了。

      我們得到c值后,將其輸入到激活函數進行處理,那么激活函數是干啥的呢?我的個人理解就是將簡單的線性輸入(上述加權疊加過程再復雜也是簡單的線性組合)轉換成復雜的非線性輸出,以獲得更好的分類效果。換句話說,我們需要利用激活函數將簡單的線性分類變成復雜的非線性分類以獲得更好的分類效果。舉個例子,如下圖:

兩種顏色代表兩類數據,這兩類數據很老實地呆在直線的兩邊,我們很容易找到准確描述這條直線的線性方程式,這就是簡單的線性分類。但是,如果數據像下面這樣呢:

其實,絕大多數情況下,數據都應該是類似這樣,而且比這還復雜。因為這僅僅是二維空間一個簡單到能夠一眼就能看出數據邊界的例子,如果是三維、四維以及更高維的情況呢?一條簡單的直線顯然是辦不到的。這種情況下只能用多層神經網絡利用激活函數將簡單的線性分類變成復雜的非線性分類,讓分類邊界變成復雜的曲線並且能夠穿越多維空間,這樣才能達成我們的目標,至於激活函數經過多層作用后,它到底會長什么樣,誰也不知道,我們只是知道——It worked!常見的激活函數有sigmoid、tanh、ReLu、maxout等,以sigmoid函數為例,其函數式如下:

其具備類似階躍函數的性質,其可以在跳躍點(某個數值)從0跳躍到1。該函數的值域為(0,1),人工神經元將sigmoid函數的輸出與某個閥值進行比較,比如0.5,大於0.5,神經元輸出1,小於則輸出0。就這樣我們把當前神經元的輸出作為另一個神經元的輸入,構成一個多層,每層多個神經元的復雜網絡,如下圖:

我直接將文章(1)的圖截過來了,這個圖很形象地展示了CNN的結構,其屬於最簡單的多層全連接前向神經網絡系統,它有10個輸入連接到了網絡的第一層,每個輸入均與第一層的所有神經元連接。第一層神經元的輸出作為下一層神經元的輸入連接到下一層,以此類推,直至最后一層神經元。上圖共有三層網絡,第1、2層各有12個神經元,第3層也就是最后一層有6個神經元,也就是說這個三層網絡最后會有6個輸出,即一個6元向量。

      那么,類似這樣的網絡結構,是怎樣理解並實現我們識別人臉這樣的需求的呢?接下來就是訓練數據登場的時候了。在這里,我們將訓練數據稱為訓練集,每組訓練數據包括一個輸入、一個輸出,也就是ML經常提到的帶標注的數據,標注值為輸出,圖像等需要識別的內容為輸入,N對這樣的數據構成了訓練數據集。以我們前面准備的人臉識別數據為例,我的1000張臉部圖像作為輸入數據,每輸入一張圖像,CNN的輸出應為0,也就是說,一張圖像對應一個固定數值0,1000張圖像與1000個0組成1000對訓練集。同樣,閨女的1000張臉部圖像與1000個1組成另外1000對訓練集。我們首先將臉部圖像作為輸入數據輸入給CNN,CNN從一個隨機濾波器開始計算,其最終的輸出基本不太可能是正確的,但這不要緊,CNN會將自己的輸出Ocnn與數據集給出的輸出Oreal進行比較,見下式:

我們求得n對樣本數據的真實值與輸出值之間差的平方和的均值e,此處e被稱作均方誤差,亦即mse。顯然e越小,其越接近真實輸出,於是CNN的實際工作就變為想方設法地讓e變小,直至e值進入可接受范圍之內,此時我們就可以認為CNN訓練好了。像e這樣的函數我們統稱為代價函數(Cost Function),除了mse,我們還可以選擇其它代價函數用於調優。那么我們怎么才能調優呢?答案是使用梯度下降算法找到e的全局最小值,說白了就是求偏導。CNN會沿着的相反方向調整權值和偏置值(順着的方向e值上升最快,反之則下降最快,不了解的可參閱高等數學之偏導數及向量兩部分內容,建議先看向量了解個大概再看偏導,更弱的就先看導數),一次一個步長(步長被稱為學習效率,Learning Rate),如此反復,經過多次迭代,CNN即可得到e的最小值。於是,我們的目標達成。

      我相信你只要仔細閱讀並真正理解了上面講述的內容,那么接下來讀懂訓練代碼應該不成問題了。如果你覺得還不過癮,還想了解得更深,那么關於卷積神經網絡更詳細的內容,請詳細閱讀本文開頭給出的幾篇文章,或者看知乎上關於它的討論帖,也很不錯,唯一的小缺點是有點長。

      最后,還需要交代一點:事實上,上面給出的三層卷積神經網絡的結構圖是非常簡單的,僅僅包含三層單一的卷積層,我們接下來實際使用的CNN網絡還需要幾種特殊的網絡層才能讓CNN更加成熟,包括pooling layer、Dropout layer、flatten layer、dense layer等,下一節我將結合代碼來詳細講解它們的實際用處,這里就不多說了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM