讀懂反向傳播算法(bp算法)

bp算法

介紹

反向傳播算法可以說是神經(jīng)網(wǎng)絡最基礎也是最重要的知識點?;旧纤缘膬?yōu)化算法都是在反向傳播算出梯度之后進行改進的。同時,也因為反向傳播算法是一個遞歸的形式,一層一層的向后傳播誤差即可,很容易實現(xiàn)(這部分聽不懂沒關系,下面介紹)。不要被反向傳播嚇到,掌握其核心思想就很容易自己手推出來。

思想

我們知道神經(jīng)網(wǎng)絡都是有一個loss函數(shù)的。這個函數(shù)根據(jù)不同的任務有不同的定義方式,但是這個loss函數(shù)的目的就是計算出當前神經(jīng)網(wǎng)絡建模出來輸出的數(shù)據(jù)和理想數(shù)據(jù)之間的距離。計算出loss之后,根據(jù)反向傳播算法就可以更新網(wǎng)絡中的各種參數(shù)以此使loss不斷下降,即可使輸出的數(shù)據(jù)更加理想。
所以,現(xiàn)在的任務是,已知一個網(wǎng)絡的loss之后,如何根據(jù)loss來更新參數(shù)呢?具體點即如何更新網(wǎng)絡節(jié)點中的權重w和偏差b的值呢?

定義元素

這里我們采用的是全連接神經(jīng)網(wǎng)絡進行說明。
要想把這個過程說清楚,首先需要將神經(jīng)網(wǎng)絡中各個參數(shù)用文字表達清楚。定義的就是w和b在網(wǎng)絡中的準確位置。


w標記說明

對于w _{jk} ^l表示的是神經(jīng)網(wǎng)絡中第l-1層第k個節(jié)點到神經(jīng)網(wǎng)絡中第l層第j個節(jié)點之間的權重。注意w的下標是首位表示的是節(jié)點后層節(jié)點的位置,末尾表示是前層節(jié)點的位置。理解這樣的表達方式在后面的計算中會很好理解。
同理,對于b的表示:

b,a符號說明

b的表示相比于w要簡單一些,符號b _j ^l表示第l層網(wǎng)絡在第j個節(jié)點的偏置。無論w還是b的表示,上標都是表示層數(shù)。并且w _{jk} ^lb _j ^l表示都是第l層網(wǎng)絡第j個節(jié)點的參數(shù)。所以該節(jié)點的輸出可以表示為:
z_{j}^{l}=\sum_{k} w_{j k}^{l} a_{k}^{l-1}+b_{j}^{l}
神經(jīng)網(wǎng)絡輸出之后會經(jīng)過一個激活函數(shù),這用激活函數(shù)用\sigma表示,則經(jīng)過激活函數(shù)輸出為:
a_{j}^{l}=\sigma(z_{j}^{l})=\sigma\left(\sum_{k} w_{j k}^{l} a_{k}^{l-1}+b_{j}^{l}\right)
至此,根據(jù)上面符號w _{jk} ^lb _j ^l、z_{j}^{l}a_{j}^{l}。我們可以對于神經(jīng)網(wǎng)絡里面每一個數(shù)據(jù)準確的表示了。

損失函數(shù)對參數(shù)的偏導

給定一個損失函數(shù)之后,用C表示,說白了反向傳播就是求?C/?w和?C/?b,然后將這個值乘以和對應的w,b進行相減就可以實現(xiàn)一次的參數(shù)更新了。為什么這樣的操作就可以優(yōu)化網(wǎng)絡,減小loss值呢?

來源于導數(shù)的概念和速度相關。?C/?w和?C/?b相當于loss值C相對于w和v變化的速度。如果?C/?w是正的,則增大w,C也會增大,如果希望C減小的話,應該減小w;并且?C/?w的絕對值越大,表示w對C的值影響越大,w稍微有一點變化,C就會有大幅變化。如果要優(yōu)化C變小,w應該對應的減少多少呢?也沒有一個確定的答案。這里通過變化的速度和學習率相乘作為一個減小的值。通過多輪迭代。最終是希望c達到最小點。而當函數(shù)落入最小值的時候,無論是局部最小還是全局最小,其周圍一定是平滑的。所以此時?C/?w和?C/?b將會變得很小甚至為0,即參數(shù)不在更新了。當函數(shù)在局部最小點處參數(shù)不在更新出現(xiàn)梯度消失的問題時,目前也有各種trick進行解決。不是這里的重點。

為了好說明,這里定義一個很簡單的損失函數(shù)C:

損失函數(shù)


即:網(wǎng)絡輸出的值和label之間的均方差。

求導

接下來就是有意思的階段了。這里還是利用上一節(jié)中?C/?w和?C/?b的解釋。如果我們想要求出?C/?w和?C/?b的值,即具體的w _{jk} ^l、b _j ^l對C影響速率的值,我們找一個中間變量?C/?z_{j}^{l}。因為我們知道:
z _{j}^{l}=\sum _{k} w _{j k} ^{l} a _{k} ^{l-1}+b _{j} ^{l}
我們定義:
\delta_{j}^{l} \equiv \frac{\partial C}{\partial z_{j}^{l}}
當我們知道了\delta_{j}^{l}值之后,我們根據(jù)z _{j}^{l}=\sum _{k} w _{j k} ^{l} a _{k} ^{l-1}+b _{j} ^{l}式子可以很容易求出\frac{\partial C}{\partial c_{jk}^{l}}
利用導數(shù)的鏈式法則:
\frac{\partial C}{\partial w_{jk}^{l}} =\frac{\partial C}{\partial z_{j}^{l}} \frac{\partial z_{j}^{l}}{\partial w_{jk}^{l}}= \delta_{j}^{l} a _{k} ^{l-1}
很容易推出來不是?同理可以求出:
\frac{\partial C}{\partial b_{j}^{l}} =\frac{\partial C}{\partial z_{j}^{l}} \frac{\partial z_{j}^{l}}{\partial b_{j}^{l}}= \delta_{j}^{l}
可以看出通過媒介 \delta_{j}^{l}很容易求出?C/?w和?C/?b。那么我們現(xiàn)在來理解一下 \delta_{j}^{l}到底是什么意思,以及如何求出來每一個l層j節(jié)點的\delta_{j}^{l}值。

根據(jù)定義:
\delta_{j}^{l} \equiv \frac{\partial C}{\partial z_{j}^{l}}
可以看出來\delta_{j}^{l}就是{ z_{j}^{l}}對于C的影響大小(聯(lián)系之前說的導數(shù)和速率的關系)。而z_{j}^{l}是第l層第j個神經(jīng)元未進過激活函數(shù)之前的輸出。所以我們可以理解\delta_{j}^{l}為網(wǎng)絡中第l層第j個神經(jīng)元對loss的影響。所以很直觀的看法就是我們先求出單個神經(jīng)元對loss值得影響,然后再計算該神經(jīng)元內(nèi)部參數(shù)對于loss的影響。

ok,如果我們已經(jīng)理解了為什么要引入\delta_{j}^{l}變量以及如何利用該變量計算具體參數(shù)的梯度后,接下來我們就可以看看如何獲得\delta_{j}^{l}值。反向傳播的名字我想也就是通過計算\delta_{j}^{l}的方式而來的。是一層一層遞歸而來的。

既然說是遞歸的方式,我們來思考一下\delta_{j}^{l}\delta_{k}^{l+1}之間有什么關系,如果找到這個關系之后,我們就可以默認我們?nèi)绻雷詈笠粚泳W(wǎng)絡節(jié)點的\delta_{j}^{l}值,我們就可以獲得倒數(shù)第二層網(wǎng)絡節(jié)點的\delta_{j}^{l}值,倒數(shù)第三層,倒數(shù)第四層,……以此推類即可獲得整個網(wǎng)絡的每個節(jié)點的\delta_{j}^{l}值。至此我們的反向傳播也基本完成了。
所以最重要的有兩點:

  1. \delta_{j}^{l}\delta_{k}^{l+1}之間有什么關系
  2. 假設最后一層網(wǎng)絡是L,最后一層\delta_{j}^{L}如何計算得出

先看問題1,直接根據(jù)求導的鏈式法則就可以找出兩個的關系,具體公式如下,可以多看看手寫一下,思路上也很簡單。
\delta_{j}^{l}=\frac{\partial C}{\partial z_{j}^{l}}=\sum_{k} \frac{\partial C}{\partial z_{k}^{l+1}} \frac{\partial z_{k}^{l+1}}{\partial z_{j}^{l}}=\sum_{k} \frac{\partial z_{k}^{l+1}}{\partial z_{j}^{l}} \delta_{k}^{l+1}
覺得這樣的鏈式公式還是很直觀的,如果不好理解,可以自己畫一個神經(jīng)網(wǎng)絡圖,連上節(jié)點與節(jié)點之間的線,標上參數(shù),然后推一下應該就能理解了。
這里的z都表示的未經(jīng)過激活函數(shù)的神經(jīng)元的輸出。\sigma表示激活函數(shù)。因為:
z_{k}^{l+1}=\sum_{j} w_{k j}^{l+1} a_{j}^{l}+b_{k}^{l+1}=\sum_{j} w_{k j}^{l+1} \sigma\left(z_{j}^{l}\right)+b_{k}^{l+1}
所以:
\frac{\partial z_{k}^{l+1}}{\partial z_{j}^{l}}=w_{k j}^{l+1} \sigma\left(z_{j}^{l}\right)
帶入上式就可以得出:
\delta_{j}^{l}=\sum_{k} w_{k j}^{l+1} \delta_{k}^{l+1} \sigma\left(z_{j}^{l}\right)
至此就找出了\delta_{j}^{l}\delta_{k}^{l+1}之間的關系了。
(還能簡化,根據(jù)最開始我們定義的a_{j}^{l}=\sigma(z_{j}^{l}))。
\delta_{j}^{l}=\sum_{k} w_{k j}^{l+1} \delta_{k}^{l+1} a_{j}^{l}
理解起來就是網(wǎng)絡中前面一層某一個神經(jīng)元對于loss的影響與該層的后一層所有的神經(jīng)元對loss的影響、該神經(jīng)元的輸出大小、該神經(jīng)元與后一層神經(jīng)元連接的權重有關系的,并且是一個累加的效應。這樣的理解也是非常直觀合乎常理的。

現(xiàn)在萬事具備,只差問題2了。即假設最后一層網(wǎng)絡是L,最后一層\delta_{j}^{L}如何計算得出。最后一層的\delta_{j}^{L}值就像一個導火索,一旦有了開始,就可以利用我們之前推出來的:\delta_{j}^{l}=\sum_{k} w_{k j}^{l+1} \delta_{k}^{l+1} \sigma\left(z_{j}^{l}\right)公式進行反向傳播了(反向傳播還是很形象的不是?)。現(xiàn)在解決這個問題。這個問題就是和損失函數(shù)具體怎么定義有關系了。不過我們先不考慮C的具體形式,根據(jù)通用的鏈式法則我們可以得到:
\delta_{j}^{L}=\sum_{k} \frac{\partial C}{\partial a_{k}^{L}} \frac{\partial a_{k}^{L}}{\partial z_{j}^{L}}
這里需要注意的是最后一層激活函數(shù)使用的是哪種。最后一層激活函數(shù)在計算某一個神經(jīng)元的輸出時可能會結(jié)合其他節(jié)點的輸出來計算。比如softmax激活函數(shù),其輸出的是一個概率值【0,1】。輸出大小就是結(jié)合輸出所有的值。

現(xiàn)在我們來考慮兩個具體的損失函數(shù),并且采用之前定義的均方誤差損失函數(shù)C=\frac{1}{2}\left\|y-a^{L}\right\|^{2}=\frac{1}{2}\sum_{j}\left(y_{j}-a_{j}^{L}\right)^{2}

  • sigmoid損失函數(shù)
    形式:S(x)=\frac{1}{1+e^{-x}}
    函數(shù)曲線:
    sigmoid function

求導為:S^{\prime}(x)=\frac{e^{-x}}{\left(1+e^{-x}\right)^{2}}=S(x)(1-S(x))
因為sigmoid輸出的值僅僅和輸入的x值有關 。所以\frac{\partial a_{k}^{L}}{\partial z_{j}^{L}}k \neq j時值為0.所以:
\delta_{j}^{L}=\sum_{k} \frac{\partial C}{\partial a_{k}^{L}} \frac{\partial a_{k}^{L}}{\partial z_{j}^{L}}=\frac{\partial C}{\partial a_{j}^{L}} \frac{\partial a_{j}^{L}}{\partial z_{j}^{L}}=(a_{j}^{L}-y _j)*a_{j}^{L}(1-a_{j}^{L})

  • softmax損失函數(shù)
    形式:S(z _{j})=\frac{e^{z_{j}}}{\sum_{k=1}^{K} e^{z_{k}}}, j=1, \ldots, K
    函數(shù)形式:輸出也是【0,1】的值,不過需要依賴最后一層所有的數(shù)來計算分母
    求導:

    • \frac {\delta S(z _{j})} {\delta z _{j}} = S(z _{j})(1-S(z _{j}))
    • \frac {\delta S(z _{j})} {\delta z _{k}} = -S(z _{j})S(z _k) ,k \neq j

    所以
    \delta_{j}^{L}=\sum_{k} \frac{\partial C}{\partial a_{k}^{L}} \frac{\partial a_{k}^{L}}{\partial z_{j}^{L}}=\frac{\partial C}{\partial a_{j}^{L}} \frac{\partial a_{j}^{L}}{\partial z_{j}^{L}}-\sum_{k \neq j} \frac{\partial C}{\partial a_{k}^{L}} \frac{\partial a_{k}^{L}}{\partial z_{j}^{L}}=(a_{j}^{L}-y _j)*a_{j}^{L}(1-a_{j}^{L}) -\sum_{k \neq j} (a_{j}^{L}-y _j)*a_{j}^L a_{k}^L

總結(jié)

根據(jù)上面,BP推導有三部曲,先求出\delta_{j}^{l},再根據(jù)\delta_{j}^{l}分別求出w _{jk} ^l、b _j ^l??偨Y(jié)公式如下:
\delta_{j}^{l}=\sum_{k} w_{k j}^{l+1} \delta_{k}^{l+1} a_{j}^{l}
\frac{\partial C}{\partial w_{jk}^{l}} =\frac{\partial C}{\partial z_{j}^{l}} \frac{\partial z_{j}^{l}}{\partial w_{jk}^{l}}= \delta_{j}^{l} a _{k} ^{l-1}
\frac{\partial C}{\partial b_{j}^{l}} =\frac{\partial C}{\partial z_{j}^{l}} \frac{\partial z_{j}^{l}}{\partial b_{j}^{l}}= \delta_{j}^{l}
啟動上面反傳的導火索是最后一層的\delta_{j}^{L}值,計算公式為:
\delta_{j}^{L}=\sum_{k} \frac{\partial C}{\partial a_{k}^{L}} \frac{\partial a_{k}^{L}}{\partial z_{j}^{L}}
根據(jù)最后一層不同類型的激活函數(shù)不同對待。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容