1. 程式人生 > >卷積神經網路CNN理論到實踐(1)

卷積神經網路CNN理論到實踐(1)

作者:相國大人

寫這篇博文用了很多時間和精力,如果這篇博文對你有幫助,希望您可以打賞給博主相國大人。哪怕只捐1毛錢,也是一種心意。通過這樣的方式,也可以培養整個行業的智慧財產權意識。我可以和您建立更多的聯絡,並且在相關領域提供給您更多的資料和技術支援。

賞金將用於拉薩兒童圖書公益募捐

手機掃一掃,即可:

1. 導讀

卷積神經網路CNN常用於處理具有柵格拓撲特徵的資料。時間序列資料可以看做是在固定時間間隔取樣的一維網格資料;影象可以看做是由畫素組成的一個二維網格。在實際應用中,具有很好的效果。也是進入深度學習領域需要掌握的最基本的網路模型。卷積網路使用卷積來代替一般的矩陣乘法。將一層卷積結果作為一個輸出層。
本文是一之後系列博文的第一篇。在本系列博文中,我們會全方位,足夠深入的為你講解CNN的知識。包括很多你之前在網上找了很多資料也沒搞清楚的東西,例如:
1. 我們會全面深入的介紹卷積的概念,讓你不僅僅知道卷積的運算,還能夠從理性和感性的雙重角度,理解卷積的意義。我們還會探討為什麼要使用卷積網路,卷積網路究竟有什麼特性。
2. 我們會詳細介紹池化的概念,並且告訴你為什麼要做池化操作,池化操作究竟有什麼特別的好處。
3. 我們會全面介紹CNN的各種形式。如:standard convolution,valid convolution, same convolution,full convolution,unshared convolution,tiled convolution等等。尤其是tiled convolution我們會用最能夠讓人理解的方式,讓你透徹明白其中的原理。這一點,我們的工作要比網上其他博文做得更好。
4. 我們還將詳細探討卷積與矩陣乘法的關係。這一點,我們的工作也要比網上其他博文作的好。
5. 除此之外,我們還會探討更多,更深入的知識,例如:CNN中的其他操作(如反捲積等),如何在資料集上使用不同維度的卷積,使得卷積操作更高效的方式 ,使用tensorflow進行CNN的實現,討論並實現如何使用CNN做中文文字分類。

所有這些精彩的內容,都會在我接下來的博文中一一介紹。
因此,與網上其他博文相比,我們的工作更好,主要體現在:
1.對理論的介紹足夠深入易懂
2. 我們會利用CNN做文字分類的實踐。
3. 我們會繪製大量精美的示意圖。保證博文的高質量和美觀。

接下來,我們為大家介紹卷積的概念

2. 卷積

假如我們現在要追蹤一艘船的位置,這艘船會給我們返回當前時刻t的它的位置座標x(t),這裡的xt都是實數。如果這個函式返回的值有些噪聲干擾,那麼我們能夠想到的一個策略,就是取鄰域求均值。如下圖所示,我們用最近觀測到的結果做一個加權求和。只不過,這個權重顯然應該是離當前時刻越近越大才合理一些。這樣,我們不妨假設權重函式為ω

(Δt),那麼對於一個特定時刻α,而言,加權求和中,關於它的一項,應該寫為:x(α)ω(tα).如果對所有時刻進行求和,我們就可以得到一個新的函式s(t),表示對x(t)的一個平滑的估計:

s(t)=x(α)ω(tα)dα(2.1)
我們把上面這個操作,叫做卷積(convolution).常常簡寫為:
s(t)=(xw)(t)(2.2)
2.1
圖片2.1 卷積示意圖

在我們這個場景(追蹤船位置)中,我們的函式ω是權重函式,因此,它在全域上的積分和應該為1,並且是非負函式。因此這個ω函式,實質上就是一個概率密度函式。並且ω(t)=0,if:t<0,否則這意味著我們可以看到未來的資料,這不符合此場景下的邏輯。
但事實上,剛才說到的這兩個限制,僅僅是在我們這個場景中是成立的。對於一般的卷積定義來說,不管ω

是什麼樣的函式,只要可以寫成公式(2.1,2.2)的形式,我們都稱之為卷積操作。
特別的,在深度學習領域中,我們把公式(2.1,2.2)中的x叫做輸入(input),把ω叫做核(kernel),而輸出s叫做特徵對映(feature map).本文接下來的所有論述中,將直接使用英文術語。

在剛才的場景中,我們預設x是連續的函式。事實上,在很多實際情況中,尤其是在深度學習中,這是不可能的。通常情況下,當我們處理計算機上的資料時,時間是離散化的。因此,我們接下來不妨假設,在剛才的場景中,函式x(t)中,引數t只能取得整數值,這樣,一個離散化的卷積定義就出現了:

s[n]=(xω)(n)=m=x[m]ω[nm](2.3)

在機器學習領域中,我們的input往往是多維陣列,kernel也是由學習引數構成的多維陣列。這樣以來,我們可以把這些多維陣列看做是張量。從公式(2.3)中可以看到,我們需要對無窮多資料進行求和,但實際上,如果我們假定,除了我們儲存的觀測值之外,其他沒有觀測到的值,統統記為0,那麼就可以通過有限次的求和來得到式(2.3)的結果。
由上面的論述,我們知道,我們需要同時在多個維度上進行卷積操作。例如,如果我們使用二維影象I作為輸入,那麼我們也希望使用二維的kernel K進行卷積操作(類比之前的場景,這個時候,你可以把K理解為,在二維網格中,距離當前節點越近的格點,應該擁有更大的權值):

s[i,j]=(IK)[i,j]=mnI[m,n]K[im,jn](2.4)
對於卷積操作而言,交換IK的引數,其值不變(關於這一點,其實你看下圖片2.1,相信不會難以理解),即:
s[i,j]=(IK)[i,j]=mnI[im,jn]K[m,n](2.5)
在CNN中,K的尺寸一般要比I的尺寸小很多。這意味著,如果我們採用公式(2.4)的話,那麼我們需要對大尺寸的I的每一個畫素點遍歷,得到I[m,n],然後再去尋找K[im,jn],沒有其值的就以0填充。因此這種操作順序,浪費計算。但是,如果我們採用公式(2.5),那麼我們需要對小尺寸的K的每一個畫素點遍歷,得到K[m,n],然後再去尋找I[im,jn],這個在大尺寸的I中是可以找到的(沒有其值的就以0填充)。因此這種操作順序,比較節約計算資源。所以我們在CNN中使用的是後者。
有趣的是,在很多機器學習庫中,它們往往把上面公式的kernel進行“翻轉”,得到下面的樣子:
s[i,j]=(IK)[i,j]=mnI[i+m<