CNN的反向傳播

CNN的反向傳播

來自專欄人工智慧圖像識別技術與計算機視覺(CV)5 人贊了文章

漫長的道路盡頭

是豁然開朗,還是危機重重

原來我的誤差

只決定了我們離別的可能

——題記

日常題(sāo)記(huà)……


再談交叉熵

我們在「基於DNN的圖像識別」這一篇中提到了交叉熵公式,在那裡我們直接給出了公式最簡形式:

E_{tot} = ln(sum_{i = 1}^{size_{layerspace O}}{e^{out_{Oi}}}) - out_{Ospace ans\_lab}

事實上,這個公式能夠解決問題,但是並不能很明顯地表徵出交叉熵的意義。

接下來我將介紹一下交叉熵的真正意義。其實如果不了解交叉熵,對學習計算機視覺方面的影響不大,所以不願意學數學的朋友可以選擇跳過「再談交叉熵」標題下的內容。

熵,就是不確定度,也是衡量一個概率分布是否接近真實分布的標準。

先說不確定度,A、B、C三名學生:

A喜歡上網,天天熬夜打遊戲,退學的概率為30%,延畢的概率為60%,順利畢業的概率為10%;

B熱愛學習,經常出沒於圖書館和自習室,退學的概率為10%,延畢的概率為10%,順利畢業的概率為80%;

C恃才放曠,成天翹課泡在機房準備ACM,退學的概率為20%,延畢的概率為40%,順利畢業的概率為40%。

那麼,如何衡量他們未來的不確定性呢?

我們引入熵的公式: H(X) = -sum_{i = 1}^{n}{(p_{i}(x) · ln(p_{i}(x)))} 。於是對於A、B、C三位同學的未來,熵值分別是:

H_{A}(X) = -sum_{i = 1}^{3}{(p_{Ai}(X) · ln(p_{Ai}(X)))} approx -(0.3 	imes (-1.203973) + 0.6 	imes (-0.510826) + 0.1 	imes (-2.302585)) approx 0.8979

H_{B}(X) = -sum_{i = 1}^{3}{(p_{Bi}(X) · ln(p_{Bi}(X)))} approx -(0.1 	imes (-2.302585) + 0.1 	imes (-2.302585) + 0.8 	imes (-0.223144)) approx 0.6390

H_{C}(X) = -sum_{i = 1}^{3}{(p_{Ci}(X) · ln(p_{Ci}(X)))} approx -(0.2 	imes (-1.609438) + 0.4 	imes (-0.916291) + 0.4 	imes (-0.916291) approx 1.0549

我們發現,C同學的未來不確定性是最高的,其次是A,B的不確定性最低。

所以,好好學習,天天向上,珍愛生命,遠離ACM。

啊不,並不是這樣,ACM該打還是要打一打的,萬一拼上保研了呢……這不是關鍵。

關鍵在於,對於B同學這樣品學兼優的好學生,A和C誰更接近一點呢?當然,誰都知道肯定不是A,那就只能是C了,但是如何度量呢?

於是我們引入交叉熵的公式:C_{(M, N)}(X) = -sum_{i = 1}^{n}{(p_{Mi}(X) · ln(p_{Ni}(X)))} ,其中M為原概率分布,N為待估計概率分布。於是,B同學與A、C的接近程度為:

H_{(B, A)}(X) = -sum_{i = 1}^{3}{(p_{Bi}(X) · ln(p_{Ai}(X)))} approx -(0.1 	imes (-1.203973) + 0.1 	imes (-0.510826) + 0.8 	imes (-2.302585)) approx 2.0135

H_{(B, C)}(X) = -sum_{i = 1}^{3}{(p_{Bi}(X) · ln(p_{Ci}(X)))} approx -(0.1 	imes (-1.609438) + 0.1 	imes (-0.916291) + 0.8 	imes (-0.916291)) approx 0.9856

所以,差生A與優生B的差距就比較大了,而競賽狂魔C與優生B的差距就小了一點。但是,這個差距的最小值,就是 H_{B}(X) ,因為原概率是最接近正確概率的,有興趣的朋友可以證明一下。

但是,這只是交叉熵在概率方面的應用,如何應用在CNN求誤差中呢?

Softmax層——將輸出轉化為概率

由於我們的輸出,往往是n個實數 a_{1}, a_{2}, a_{3}, ..., a_{n} ,我們期望這些實數都是[0, 1]區間內的實數,並且它們的和為1,這樣就能將輸出轉化為概率。但是我們應該如何轉化呢?

於是我們引入Softmax層:對於n個輸出 out_{O1}, out_{O2}, out_{O3}, ..., out_{On} ,標籤為i的概率值為 frac{e^{out_{Oi}}}{sum_{j = 1}^{size_{layerspace O}}{e^{out_{Oj}}}} 。這樣,對於每一次訓練,前向傳播之後,我們用Softmax層求出概率,下一步就是最大化正確標籤的概率、最小化所以錯誤標籤概率就行了。

如何最小化呢?這裡就用到了交叉熵。我們期望的Softmax的輸出值,除了 ans_{Softmax ans\_lab} = 1 之外, ans_{Softmax i} = 0 (其中 i 
e ans\_lab ),所以誤差就是E_{tot} = -sum_{i = 1}^{n}{(ans_{Softmax i} · lnfrac{e^{out_{Oi}}}{sum_{j = 1}^{size_{layerspace O}}{e^{out_{Oj}}}})} = lnfrac{sum_{j = 1}^{size_{layerspace O}}{e^{out_{Oj}}}}{e^{out_{Ospace ans\_lab}}} = ln(sum_{i = 1}^{size_{layerspace O}}{e^{out_{Oi}}}) - out_{Ospace ans\_lab}

於是我們求出每一個輸出層神經元分攤的誤差:

i 
e ans\_lab 時, delta_{Oi} = frac{partial E_{tot}}{partial net_{O i}} = frac{partial E_{tot}}{partial out_{O i}} 	imes frac{partial out_{O i}}{partial net_{O i}} = (frac{e^{out_{Oi}}}{sum_{j = 1}^{size_{layerspace O}}{e^{out_{Oj}}}})·A_{Oi}(net_{Oi})

i = ans\_lab 時, delta_{Oi} = frac{partial E_{tot}}{partial net_{O i}} = frac{partial E_{tot}}{partial out_{O i}} 	imes frac{partial out_{O i}}{partial net_{O i}} = (frac{e^{out_{Oi}}}{sum_{j = 1}^{size_{layerspace O}}{e^{out_{Oj}}}} - 1)·A_{Oi}(net_{Oi})

我是不會告訴你這個公式是我從「基於DNN的圖像識別」那一篇複製過來的……

當然,往往輸出層不激活的效果要好於激活,即輸出層的激活函數往往採用 A_{Oi}(x) = x ,而導函數就是 A_{Oi}(x) = 1 了。

這樣,通過Softmax和交叉熵,我們得到了網路的誤差。我們發現,網路的訓練就是提高正確標籤對應的輸出層神經元對圖像的敏感程度,抑制其它標籤對應的輸出層神經元對圖像的敏感程度。下面,我們將進行反向傳播。

一個卷積神經網路的結構

全連接層的反向傳播——當作DNN處理

全連接層之所以叫做全連接層,是因為它相鄰兩層的神經元之間是全連接的,而每層的神經元之間沒有連接。即相鄰兩層的神經元之間呈二分圖的拓撲結構,這就有點像RBM——受限玻爾茲曼機。於是,全連接層的反向傳播可以當作DNN處理,傳遞到第一層全連接層。

全連接層 - 卷積層的反向傳播——DNN穿上了馬甲

末層卷積層-全連接層其實和DNN的結構也差不多,就是多了共用的權值。其實權值的共用並不影響偏微分的求解。對於下左圖卷積層-全連接層的結構,我們可以拆分成右圖(注意連邊的顏色):

全連接層-卷積層的反向傳播

因為全連接層每一個神經元的接收值都是通過如下公式求得:

net_{F1space (p)} = sum_{i = 0}^{width_{S2}}{sum_{j = 0}^{height_{S2}}{out_{Ispace (p / num_{kernelspace global}, i, j)}}	imes weight_{global (pspace modspace num_{kernelspace global})space (i, j)}}

根據偏微分的性質,誤差傳遞到末層卷積層時:

delta_{S2 (p, i, j)} = frac{partial E_{tot}}{partial net_{S2 (p, i, j)}} = frac{partial E_{tot}}{partial out_{S2 (p, i, j)}} 	imes frac{partial out_{S2 (p, i, j)}}{partial net_{S2 (i, j)}} = (sum_{k = 0}^{num_{kernel global} - 1}({frac{partial E_{tot}}{partial net_{F1 (num_{kernel global} 	imes p + k)}} · weight_{global (k) (i, j)})}) · A_{S2}(net_{S2 (p, i, j)})

由於我們已經求過 delta_{F1 (num_{kernel global} 	imes p + k)} = frac{partial E_{tot}}{partial net_{F1 (num_{kernel global} 	imes p + k)}} ,所以原公式可以寫成:

delta_{S2 (p, i, j)} = frac{partial E_{tot}}{partial net_{S2 (p, i, j)}} = (sum_{k = 0}^{num_{kernel global} - 1}({delta_{F1 (num_{kernel global} 	imes p + k)} · weight_{global (k) (i, j)})}) · A_{S2}(net_{S2 (p, i, j)})

卷積層 - 匯合層的反向傳播——騷操作

現在我們已經成功地將誤差傳到了末層卷積層,下一步就是傳遞到它前面的匯合層了。但是,由於匯合層的池化方式有兩種,我們需要分情況討論。

如果我們使用max_pooling(最大池化),那麼就在前一層找到每一個池化區域中最大值的位置 (p, i, j) ,該處的誤差就是:

delta_{C1 (p, i, j)} = delta_{S2 (p, i / width_{pooling C1}, j / height_{pooling C1})}

而如果我們使用average_pooling(均值池化),那麼上一層匯合層每一個池化區域內所有神經元都要分攤下一層卷積層該位置神經元的誤差,即:

delta_{C1 (p, i, j)} = frac{delta_{S2 (p, i / width_{pooling C1}, j / height_{pooling C1})}}{width_{pooling C1} · height_{pooling C1}}

匯合層/卷積層 - 卷積層的反向傳播——DNN穿上了皮衣

此時誤差傳到了匯合層。當然,卷積神經網路不一定是卷積層、匯合層交替連接,有時也會捨棄幾層匯合層,來保留更多的信息。當然我們也可以假想存在一個匯合層,其池化區域大小為 1	imes 1

下面就是將匯合層的誤差繼續傳遞到上一層卷積層。由於權值共用,我們似乎不能非常明顯地看出哪些卷積層神經元的誤差和卷積核權值之積對匯合層某一神經元的誤差產生了貢獻。

沒關係。對於前向傳播是捨棄不存在元素的卷積,我們可以參考下面這張圖:

上圖是正向傳播過程中的卷積操作,下圖是反向傳播過程中偏微分的求解結果

於是我們發現,對於前向傳播是捨棄不存在元素的卷積,當誤差反向傳播到卷積層時,我們的操作方法依然是一個卷積,只不過要把卷積核翻過來(旋轉180°),然後在周圍補0,如圖所示:

匯合層/卷積層 - 卷積層的反向傳播,對下一層的誤差求補零的卷積

顯然,如果前向傳播是補零的卷積,那麼反向傳播就是捨棄不存在元素的卷積,不過依舊要將卷積核翻過來。

這樣,整個網路分攤的誤差我們就已經求出了,下面我們將求出各個待學習參數的梯度。

卷積層求權值與偏置量的梯度

由於匯合層沒有需要學習的參數,所有待學習的參數都在卷積層和全連接層。

對於末層卷積層,偏置量的梯度比較容易求出,只要找到對應神經元的誤差,求和就行了:

frac{partial E_{tot}}{partial b_{Sk (p)}} = sum_{k = 0}^{num_{kernel global} - 1}{delta_{F1 (num_{kernel global} 	imes p + k)}}

對於其它卷積層,偏置量的梯度則等於下一層對應單位厚度神經元的誤差之和:

frac{partial E_{tot}}{partial b_{Sk (p)}} = sum_{q = 0}^{num_{kernel Sk}- 1}{sum_{i = 0}^{width_{kernel S1} - 1}{sum_{j = 0}^{height_{kernel S1} - 1}{delta_{(Sk)^{+} (p 	imes num_{kernel Sk} + q, i, j)}}}}

而權值的梯度,對於末層全連接層,只需要求出對應神經元的誤差與末層卷積層輸出值的乘積即可:

frac{partial E_{tot}}{partial weight_{global (k) (i, j)}} = sum_{k = 0}^{num_{kernel global} - 1}({delta_{F1 (num_{kernel global} 	imes p + k)} · out_{S2 (k, i, j)})}

對於其它卷積層,則是另一個卷積:將卷積層的輸出值翻過來(旋轉180°),然後求下一層的誤差與翻過來的輸出值的卷積,得到的就是這些卷積層的權值的梯度。同時需要注意的就是,前向傳播的卷積如果是補零的,反向傳播的這個卷積則是捨棄不存在元素的;前向傳播的卷積如果是捨棄不存在元素的,反向傳播的這個卷積則是補零的。

全連接層求權值與偏置量的梯度

當成DNN處理就可以了,再此不贅述了。忘記的朋友可以回頭看一下我原來的文章:

北極鵝:深度神經網路(DNN)的訓練過程?

zhuanlan.zhihu.com圖標

網路參數的更新量與降低學習率

這些過程就和DNN完全一樣了,在此也不贅述了。


關於CNN的訓練過程已經完全講完了,配合原來講過的正則化,讀者們可以自己編寫CNN,訓練圖像識別了。下一篇我將介紹一些常用的濾波器及其作用。

感謝您的閱讀。由於筆者學業繁忙,文章托更太久。限於筆者水平,文章定有疏漏。如有不足,敬請斧正!

推薦閱讀:

TAG:神經網路 | 卷積神經網路CNN | BP演算法 |