機器學習:一步步教你理解反向傳播方法

在閱讀反向傳播方法的時候,看到了這篇通過示例給出反向傳播的博文A Step by Step Backpropagation Example,在這篇博文中,作者通過一個簡單的示例,給出了反向傳播的過程的過程,非常的清晰,遂結合自己的理解翻譯之,希望對反向傳播方法有所理解的朋友有些許幫助。

背景

反向傳播在神經網絡的訓練過程中雖然用得如此之多,但是在網上還很少有通過具體的實例來解釋反向傳播怎麼工作的博文。所以在這篇文章中,我會嘗試用一個具體的例子來解釋反向傳播過程,這樣有需要的朋友就可以通過自己的計算過程來判斷自己對於反向理解的過程是否到位。

你可以在我的Gihub上找個我寫的反向傳播的Python實現代碼。

概覽

在這篇博文中,我們會使用有2個輸入單元的神經網絡,2個隱層神經元以及2個輸出神經元。此外,隱層和輸出神經元會包含一個偏置,下面是基本的網絡結構:

爲了便於後面說明的說明,我們對該網絡設置一些初始的權重、偏置以及輸入和輸出:

反向傳播的目標是對權重進行優化,使得神經網絡能夠學習到從任意的輸入到輸出的準確映射。

在這篇博文中,我們僅使用一個簡單的訓練集,即輸入爲0.05和0.10,我們希望網絡的輸出爲0.01和0.99(即輸入的樣本是兩個: (0.05, 0.99), (0.10, 0.99))。

前向傳播

首先來看看對於給定的初始化權重和偏置,網絡對於輸入0.05和0.10的輸出是啥。我們將輸入輸進網絡中。

我們先計算從全部網絡的輸入到隱層的每一個神經元,**函數採用logistic函數,對於從隱層到輸出層,我們重複這一過程。

全部的網絡輸入也被稱爲網絡的輸入Derivation of Backpropagation

下面是對於 h1 全部網絡輸入的輸入計算過程:

neth1=w1i1+w2i2+b11neth1=0.150.05+0.20.1+0.351=0.3775

(譯者注:類比到CNN網絡裏,這個過程就是卷積過程,得到特徵響應圖)

然後我們將其輸入到**函數中,得到輸出 h1 :

outh1=11+eneth1=11+e0.3775=0.593269992

(譯者注:類比到CNN網絡裏,這個過程特徵響應圖經過**函數運算的過程)

對於 h2 通過上面相同的過程,我們可以得到:

outh2=0.596884378

對於輸入層神經元,將隱層的輸出作爲輸入(譯者注:在CNN中,還需要經過池化後才能作爲下一層的輸入,至於爲啥需要池化,這裏譯者不就解釋了),重複上面相同的過程,我們可以得到:

neto1=w5outh1+w6outh2+b21neto1=0.40.593269992+0.450.596884378+0.61=1.105905967outo1=11+eneto1=11+e1.105905967=0.75136507

同樣的,重複上面相同的過程,可以得到 O2 :

outO2=0.772928465

計算總誤差

現在對於輸出的每一個神經元,使用平方誤差函數求和來計算總的誤差:

Etotal=12(targetoutput)2

output就是我們的預測label,而target就是groundtruth。 12 使得我們在求騙到的時候可以消去2,不影響模型參數的結果求解。

對於第一個神經元的輸出 O1 真實值是0.01,而網絡的輸出是0.75136507, 因而第一個神經元的輸出誤差爲:

EO1=12(targetoutput)2=12(0.010.75136507)2=0.274811083

重複上面過程,可以得到第二個神經元的輸出 O2 爲:

EO2=0.023560026

所以整個神經網絡的誤差求和爲:

Etotal=EO1+EO2=0.274811083+0.023560026=0.298371109

反向傳播

反向傳播的目標是:通過更新網絡中的每一個權重,使得最終的輸出接近於groundtruth,這樣就得到整個網絡的誤差作爲一個整體進行了最小化。

輸出層

先來考察 w5 ,我們想知道對於 w5 的改變可以多大程度上影響總的誤差,也就是 Etotalw5

通過使用鏈式法則,可以得到:

Etotalw5=Etotalouto1outO1netO1netO1w5

爲了更直觀的表述上面鏈式法則的過程,對其進行可視化:

我們對上面使用鏈式法則得到的每一項分別進行計算。首先,整體誤差關於各個神經元的輸出改變了?

Etotal=12(targetoutput)2=12(targetO1outputO1)2+12(targetO2outputO2)2EtotaloutO1=212(targetO1outputO1)211+0=(targetO1outputO1)=(0.010.75136507)=0.74136507

logistic函數的偏導數爲輸出乘以1減去輸出,即:

outO1=11+enetO1outO1netO1=outO1(1outO1)=0.75136507(10.75136507)=0.186815602

最後,整個網絡的輸入 O1 關於 w5 改變了多少呢?

netO1=w5outh1+w6outh2+b21Etotalw5=Etotalouto1outO1netO1netO1w5Etotalw5=0.741365070.1868156020.593269992=0.082167041

你也會看到用delta規則表示的形式:

Etotalw5=(targetO1outO1)outO1(1outo1)outh1

我們可以將 EtotaloutO1 outO1netO1 寫爲 EtotalnetO1 ,並用 δO1 表示它,從而可以將上面的式子表示爲:

δO1=Etotalouto1outO1netO1δO1=(targetO1outO1)outO1(1outo1)

因此有:

Etotalw5=δO1outh1

有一些論文中通過將負號從 δ 中提出來將其也可以寫爲下面這種形式:

Etotalw5=δO1outh1

爲了減小誤差,我們將 w5 原來的值減去目前的權重(通常會乘上一個學習率 η ,這裏我們將其設置爲0.5):

w+5=w5ηEtotalw5

學習率在不同的文章中可以記法不一樣,有用 α 的,有用 η 的,有用 ϵ 的。

重複上面的過程,我們可以得到更新後的 w6 w7 w8

w+6=0.408666186w+7=0.511301270w+8=0.561370121

注意,在我們繼續向前推進反向傳播的時候,在要使用到 w5 w6 w7 w8 的地方,我們仍然使用的是原來的權重,而不是更新後的權重。

隱層

我們繼續推進反向傳播來計算 w1 w2 w3 w4 更新的權重:

同樣使用鏈式法則,我們可以得到:

Etotalw1=Etotalouth1outh1neth1neth1w1

可視化上面的鏈式法則:

對於這一層(隱層)的更新我們採用上面輸出層相似的處理方式,不過會稍有不同,這種不同主要是因爲每一個隱層神經元的輸出對於最終的輸出都是有貢獻的。我們知道 outh1 既影響 outO1 也影響 outO2 ,因此 Etotalouth1 需要同時考慮到這兩個輸出神經元影響:

Etotalouth1=EO1outh1+EO2outh1

又由於:

EO1outh1=EO1netO1netO1outh1

我們可以用前面計算的值來計算 EO1netO1 :

EO1netO1=EO1outO1outO1netO1=0.741365070.186815602=0.138498562

又因爲 netO1outh1 等於 w5 :

netO1=w5outh1+w6outh2+b21netO1outh1=w5=0.40

將上面每步分開算的結果合起來得:

EO1outh1=EO1netO1netO1outh1=0.1384985620.40=0.055399425

與上面的步驟一樣,我們可以得到:

EO2outh1=w5=0.019049119

因此:

Etotalouth1=EO1outh1+EO2outh1=0.055399425+(0.019049119)=0.036350306

現在我們已經有了 Etotalouth1 ,我們還需要爲每一個需要更新的權重計算 outh1neth1 neth1w

outh1=11+e(neth1)outh1neth1=outh1(1outh1)=0.59326999(10.59326999)=0.241300709

如我們前面對於輸出神經元所做的一樣,我們計算 h1 的全部輸入關於 w1 求偏導:

neth1=w1i1+w2i2+b11neth1w1=i1=0.05

將上面計算的各個部分合起來:

Etotalw1=Etotalouth1outh1neth1neth1w1Etotalw1=0.0363503060.2413007090.05=0.000438568

你可以可能會看到下面的這種寫法:

Etotalw1=(OEtotaloutOoutOnetOnetOouth1)outh1neth1neth1w1Etotalw1=(OδOwhO)outh1(1outh1)iEtotalw1=δh1i1

現在我們可以更新 w1 :

w+1=w1ηEtotalw1=0.150.50.000438568=0.149780716

根據上面相同的計算過程,我們可以得到 w2 w3 w4

w+2=0.19956143w+3=0.24975114w+4=0.29950229

現在,我們已經更新了所有的權重,在最初,在我們的輸入爲0.05和0.1的時候,網絡的誤差爲0.298371109, 經過第一次方向傳播後,網絡的誤差降低到了0.291027924。雖然看起來下降得不是很多,但是在重複這個過程10000次以後,網絡的誤差就下降到了0.000035085。這個時候,當我們把0.05和0.1再輸入進去,兩個神經元的輸出爲0.015912196(vs 0.01)和0.984065734(vs 0.99)。

如果你在讀上面的博文的時候發現有任何錯誤,不要猶豫告訴我。如果你有更清楚的想讀者講解的方式,不要猶豫給我留言。謝謝!