《Notes on Convolutional Neural Networks》中詳細講解了CNN的BP過程,下面結合Deep learn toolbox中CNN的BP源碼對此做一些解析
?卷積層:
? ? ? ?卷積層的前向傳導:
? ??? ? ? ? ? ? ? ? ?
? ? ? ?誤差反傳:
? ? ? ? 當卷基層的下一層是pooling層時,如果pooling層的誤差敏感項為時,那么卷基層的誤差敏感項為:
? ? ??
? ? ? ?其中,upsample表示對進行上采樣,表示激活函數對輸入的導數,代表點積操作
? ? ? ?upsample根據pooling時采用方法來定,大概思想為:pooling層的每個節(jié)點是由卷積層中多個節(jié)點(一般為一個矩形區(qū)域)共同計算得到,所以pooling層每個節(jié)點的誤差敏感值也是由卷積層中多個節(jié)點的誤差敏感值共同產生的,只需滿足兩層的誤差敏感值總和相等即可,下面以mean-pooling和max-pooling為例來說明。
假設卷積層的矩形大小為4×4, pooling區(qū)域大小為2×2, 很容易知道pooling后得到的矩形大小也為2*2(本文默認pooling過程是沒有重疊的,卷積過程是每次移動一個像素,即是有重疊的,后續(xù)不再聲明),如果此時pooling后的矩形誤差敏感值如下:
?
則按照mean-pooling,首先得到的卷積層應該是4×4大小,其值分布為(等值復制):
?
因為得滿足反向傳播時各層見誤差敏感總和不變,所以卷積層對應每個值需要平攤(除以pooling區(qū)域大小即可,這里pooling層大小為2×2=4)),最后的卷積層值
分布為:
?
如果是max-pooling,則需要記錄前向傳播過程中pooling區(qū)域中最大值的位置,這里假設pooling層值1,3,2,4對應的pooling區(qū)域位置分別為右下、右上、左上、左下。則此時對應卷積層誤差敏感值分布為:
?
求得后,我們就要求卷積層的導數了,論文中給出的公式為:
? ? ??
? ? 上式中表示的(u,v)項的值,表示與進行卷積的結果的(u,v)項所對應的的patch。
? ? ?上述公式和下面的公式是等價的:
? ? 損失函數對b的導數為:
? ? ? ? ?
?deep learn toolbox就是按照上述2個公式計算的。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
?pooling層
? ? ??pooling層的前向傳導:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ??down(.)表示一個下采樣函數。典型的操作一般是對輸入圖像的不同nxn的塊的所有像素進行求和。這樣輸出圖像在兩個維度上都縮小了n倍。每個輸出map都對應一個屬于自己的乘性偏置β和一個加性偏置b。
? ? 已知卷積層的誤差敏感項時,那么pooling層的誤差敏感項為:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? 得到誤差敏感項后,由于pooling只有兩個參數,分別求導:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ?但在deep learn toolbox中,只是簡單地進行subsampling,并沒有加sigmoid激活函數,因而pooling層沒有參數,不需要對pooling層求導,也不
需要對其參數進行更新。
? ?
? ?下面是deep learn toolbox 中CNN BP算法的代碼:
? ?
[cpp]?view plaincopy
function?net?=?cnnbp(net,?y)???? ????n?=?numel(net.layers);???? ?????? ????net.e?=?net.o?-?y;???? ?????? ????net.L?=?1/2*?sum(net.e(:)?.^?2)?/?size(net.e,?2);???? ?????? ?????? ?????? ????net.od?=?net.e?.*?(net.o?.*?(1?-?net.o));????? ????net.fvd?=?(net.ffW'?*?net.od);???????????????? ????if?strcmp(net.layers{n}.type,?'c')??????????? ????????net.fvd?=?net.fvd?.*?(net.fv?.*?(1?-?net.fv));???? ????end???? ?????? ???? ?????? ????sa?=?size(net.layers{n}.a{1});???? ????fvnum?=?sa(1)?*?sa(2);???? ????for?j?=?1?:?numel(net.layers{n}.a)???? ????????net.layers{n}.d{j}?=?reshape(net.fvd(((j?-?1)?*?fvnum?+?1)?:?j?*?fvnum,?:),?sa(1),?sa(2),?sa(3));???? ????end???? ?????? ?????? ?????? ?????? ?????? ????for?l?=?(n?-?1)?:?-1?:?1???? ????????if?strcmp(net.layers{l}.type,?'c')???? ????????????for?j?=?1?:?numel(net.layers{l}.a)???? ????????????????net.layers{l}.d{j}?=?net.layers{l}.a{j}?.*?(1?-?net.layers{l}.a{j})?.*?(expand(net.layers{l?+?1}.d{j},?[net.layers{l?+?1}.scale?net.layers{l?+?1}.scale?1])?/?net.layers{l?+?1}.scale?^?2);???? ????????????end???? ????????elseif?strcmp(net.layers{l}.type,?'s')???? ????????????for?i?=?1?:?numel(net.layers{l}.a)???? ????????????????z?=?zeros(size(net.layers{l}.a{1}));???? ????????????????for?j?=?1?:?numel(net.layers{l?+?1}.a)???? ?????????????????????z?=?z?+?convn(net.layers{l?+?1}.d{j},?rot180(net.layers{l?+?1}.k{i}{j}),?'full');???? ????????????????end???? ????????????????net.layers{l}.d{i}?=?z;???? ????????????end???? ????????end???? ????end???? ?????? ?????? ????for?l?=?2?:?n???? ????????if?strcmp(net.layers{l}.type,?'c')???? ????????????for?j?=?1?:?numel(net.layers{l}.a)???? ????????????????for?i?=?1?:?numel(net.layers{l?-?1}.a)???? ????????????????????net.layers{l}.dk{i}{j}?=?convn(flipall(net.layers{l?-?1}.a{i}),?net.layers{l}.d{j},?'valid')?/?size(net.layers{l}.d{j},?3);???? ????????????????end???? ????????????????net.layers{l}.db{j}?=?sum(net.layers{l}.d{j}(:))?/?size(net.layers{l}.d{j},?3);???? ????????????end???? ????????end???? ????end???? ?????? ????net.dffW?=?net.od?*?(net.fv)'?/?size(net.od,?2);???? ????net.dffb?=?mean(net.od,?2);???? ???? ????function?X?=?rot180(X)???? ????????X?=?flipdim(flipdim(X,?1),?2);???? ????end???? end????
總結
以上是生活随笔為你收集整理的Deep learn toolbox:CNN BP求导解析的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。