Convolutional Neural Net 筆記
更改版本:
2016/11/16 初版
2016/12/16 感謝rxliu同學提供的資料,讓我更清楚CNN的完整架構
本文公式推導來自於 [1] Notes on Convolutional Neural Networks,以及眾多參考資料 [6] [7] ,小編將他們統整起來,並給出一個範例code實作,將公式與程式對照起來,希望能給剛接觸CNN的人一點參考,code是摘自網路上的 [8] Matlab Deep Learning Toolbox,如果看不懂的話也已經有人對code做了精闢的解說 [9],相信仔細閱讀的話能有不少收穫。
概念介紹:
CNN網路是近年才發展起來的,早在1980年,Fukushima就做出了第一代CNN網路[2] Neocognitron,但當時效果還不是很好,經過後人不斷的研究改進後才慢慢演變成為今日的CNN網路,CNN網路最初的構想是來自於Hubel, Wiesel在1962年發表的 [3] 論文,他們把探針放到貓腦中特定的神經元細胞上,發現該神經元細胞對特定角度的直線有反應,不管是粗的或是細的。例如某顆神經元對傾斜45度的直線會激發,不管他們選擇粗的線或是細的線又或是在螢幕上的不同位置,他們發現只要將直線傾斜45度就會激發,當然他們也發現到其他角度的神經元。
而在後來的研究中發現不只存在這種偵測特定角度神經元存在,連高階特徵神經元也存在,例如偵測人臉神經元,且他們位於大腦的不同區域,低階神經元位於大腦視覺處理的V1區,相關資料可參考 [4] [5]。
CNN正是模仿人腦的這種架構產生出來的,由底層一層一層的學習低階特徵,再慢慢地由低階特徵組合出高階特徵去學,如下圖。
已知類神經數學推導:
上面為已知的類神經數學公式
第一行:表示 Error 是等於樣本t與輸出y的方均跟差
第二行:表示類神經的組合公式,後一層的輸出x(L)等於前一層的輸出乘以Weight+bias,然後再挑選一個適當的激活函數當f()
第三行:表示Error對 bias的微分直接等於 Error對u的微分,因為u對bias的微分為1
第四、五行:是類神經網路中最重要的精神,即這一層的敏感度(L)是後面那層的敏感度(L+1) 傳過來然後乘以W(L+1)最後再乘以輸出對輸入的微分
第六行:表示 Error 對 W的微分等於 敏感度 乘以前一層的輸出
Forward mapping:
第一層卷積層:
關於卷積過程大家可以看 Stanford 推出的 [10] UFIDL(Unsupervised Feature Learning and Deep Learning),裡面有動畫介紹。
第一層sub層:
全連接層:
全連接層和以前的類神經一樣,差別就只在於把前面的捲積層神經元攤開,假如前面的size是 20*20 ,那麼到全連階層就是 400顆神經元排列在前方。
Backward mapping:
接下來的推導過程我都會放一個實際的例子,下面擺公式以及matlab實現的代碼,方便大家對照,matlab代碼是參考github上大牛寫的 [8] Deeplearning Toolbox,真心推薦想理解DL的人可以從詳讀這個代碼開始,小編也是從這份代碼開始學起的,如果看不懂的話也有人整理出 [9] 筆記出來可以參考看看。其實小編也還不完全了解CNN,裡面有的數學甚是繁雜,小編也是從網路上拼拼湊湊才整理出這份資料,如果有大師看到什麼錯誤的地方,還望您不吝惜指教。
從最後一層傳到sub層(S2):
這邊解釋一下為什麼實現f微分的方式為o*(1-o),假如你的激發函數選擇sigmoid函數也就是1/(1+e-x),假設y=1/(1+e-x),
所以我們如果要求F的微分的話,我們只要把輸出*(1-輸出)就代表F的微分,現在我們假設已知網路最後面的誤差,根據公式,要算出前一層的敏感度就是算出當層的敏感度,然後乘上weight係數再乘以函數對輸入的微分,最後一層的敏感度就直接是樣本誤差,而如果我們選的f()為 sigmoid函數的話,那麼 f’(u)可以表示為輸出 o*(1-o),至此,前面一層的敏感度就出來了。
這裡我們假設後面三科神經元的輸出都是0.5方便計算,而誤差分別為0.4,0.8,0.16,因此得到我們的綠色底線:
再繼續乘以weight值就可以求出前一層的敏感度,所以這裡weight的維度為W(4*3),綠色底線的維度為net.od(3*1),因此根據矩陣乘法可以得知前一層的敏感度維度為net.fvd(4*1)
第一個元素的算法為 w11*net.od(1)+w12*net.od(1)+w13*net.od(1)
第二個元素的算法為 w21*net.od(2)+w22*net.od(2)+w23*net.od(2)
後面以此類推
最後將維度的形狀從(4,1)轉成(2,2)就可以算出到sub層的敏感度了,還記得剛剛的全聯階層嗎?這裡就是把它還原回去而已,這樣等等才可以繼續算下去,所以sub層的敏感度為
從sub層傳到conv層(C2):
這裡也是把剛剛的動作做還原而已,剛剛如果選擇的2*2值為1/4的捲積核,那麼還原的結果為如下
繼續算出到conv層的敏感度,也就是圖中紅色的部分,這裡繼續假設輸出為0.5方便計算
所以conv層的敏感度為
到這裡完整結構如下,下面表示該層的敏感度:
從conv層傳到sub層(S1):
因此我們繼續推算S1層的敏感度,求S1的層的敏感度非常簡單,只要將前一層的敏感度與旋轉180度的kernel做卷積即可得知,基本上還是計算下列公式,只是採取矩陣的小技巧罷了,這裡要感謝 rxliu 同學提供的資料 [12] ,裏面非常詳細的用圖解描述為什麼kernel要轉180度計算:
原MLP公式:
CNN:
如果都有各層的敏感度了,那就開始求weight偏導:
根據公式,想要知道W怎麼改變就必須知道前一層的輸出 x(l-1) 再乘以那一層的敏感度:
Error對w的微分:
這裡以求導conv(b)的weight為例,似乎是與kernel轉180度同樣的技巧,執行上面那個式子就是把前一層的輸出a轉個180度然後再 和 d 互相卷積就可以求出了,假設前一層的輸出X(l-1)輸出a如下,因此求出Error對weight的微分如下:
注意看程式碼只有當層是卷積層時才需要做梯度運算,因為只有conv層要學weight而已,sub層並不用,所以如果要求conv(b)的weight的話必須要先求得C2的敏感度以及S1層的輸出。
Error對b的微分:
根據公式 Error 對 b 的微分公式如下:
因此會把所有的敏感度都加總,然後再除以batch size
然後帶入學習率算出學習之後的W:
求出Error對W的微分之後,接下來只要帶入學習率就可以知道Weight的改變方向了,這裡注意bias的 Error對b微分是要全部相加的,因此:
參考資料:
-
[1].J. Bouvrie, “Notes on convolutional neural networks”, MIT CBCL Tech Report, pp. 38- 44, 2006
-
[2].K. Fukushima, “Neocognitron: A Self-Organizing Neural Network Model for a Mechanism of Pattern Recognition Unaffected by Shift in Position”, Biological Cybernetics, vol. 36, pp. 193-202, 1980.
-
[3].D. H. Hubel and T. N. Wiesel, “Receptive fields of single neurones in the cat’s striate cortex,”J. Physiol. (London) 148, 574–591 (1959).
-
[4].https://smallcollation.blogspot.tw/2013/06/visual-cortex.html#gsc.tab=0
-
[6].一文讀懂CNN卷積神經網路
-
[7].数据挖掘系列(10)——卷积神经网络算法的一个实现
-
[10].http://deeplearning.stanford.edu/wiki/index.php/Feature_extraction_using_convolution
http://www.slideshare.net/kuwajima/cnnbp
關於CNN的backprop這裡有簡單的圖解推導
第10頁也有提到conv層到sub層的kernel反轉
希望對小編有幫助
http://cs231n.stanford.edu/
李飛飛在Stanford開課的教材也很實用
版主回覆:(11/27/2016 11:44:08 AM)
謝謝您提供的資料^.^,那請問我的理解有錯的地方嗎?如果有,請一定要告訴我喔~
那請問他有影片可以看嗎?我點影片都沒反應
課程網站中的影片連結好像沒了,不過Youtube還有哦!
https://www.youtube.com/playlist?list=PL16j5WbGpaM0_Tj8CRmurZ8Kk1gEBc7fg
課程網站內的連結似乎無效了,不過在Youtube搜尋cs231n就有囉!
(我沒辦法附網址上來,會被痞客的系統吃掉…哈哈)
版主回覆:(11/28/2016 01:34:27 AM)
找到了~~這對我真的很有用~~謝謝~
不要因為方便計算就誤導讀者~!!!!
版主回覆:(03/06/2017 10:44:07 PM)
您好~感謝您的批評
小編也是在學習中
本文只是小編彙整所有看過的資料寫出的
或許還有不對的地方
可以請您指證出小編的錯誤嗎?
好讓小編釐清 更改錯誤
謝謝 ^.^
很用心~讚!!! 樓上腦? 不爽你來做啊!
版主回覆:(03/06/2017 10:45:50 PM)
謝謝您~~
有了你們的加油打氣
小編會更努力寫東西教大家的~~
^.^
我10年前碩士班是念電腦視覺的,但畢業後一直都沒有學以致用。今天不小心翻到小編的文章,又讓我熱血起來了,感激
版主回覆:(07/21/2017 05:54:42 PM)
哈哈~ 小編不是念電腦視覺的
可是現在卻在電腦視覺產業
剛好跟您相反XD
哪部分讓您熱血呢?
這個產業現在也快要變血汗產業了..施暴的是客戶!不是企業主…我真是不懂.為什麼這些業主都自認為瞭解了個皮毛就全部都通了.e04勒…我又不是氣功師傅專門打通人家的任督二脈的.我們也只是個賣藝的商人.這樣的環境真的能升級能進步嗎?我也在想…
版主回覆:(08/19/2017 10:14:08 PM)
是在對工作發牢騷嗎 哈哈