本文相關代碼可以從Backpropagation下載
在上一篇文章小白也能看懂的BP反向傳播算法之Into-Backpropagation
,我們研究了一個嵌套神經(jīng)元的反向傳播的計算,了解到反向傳播本質就是利用鏈式法則,求取所需要更新的變量的偏導數(shù)!但我們前文所研究的神經(jīng)元是比較簡單的,沒有復雜的函數(shù),也沒有復雜的結構,而真實的神經(jīng)網(wǎng)絡中,往往神經(jīng)元的函數(shù)和結構都比較復雜!
為了更好的過渡到復雜的神經(jīng)網(wǎng)絡中的反向傳播,本文先引入復雜函數(shù),也就是神經(jīng)網(wǎng)絡中最基本的激活函數(shù),并聯(lián)系如何計算反向傳播,為后續(xù)進入神經(jīng)網(wǎng)絡的反向傳播計算打下堅實的基礎!
Lets get started!!!
我們將引入神經(jīng)網(wǎng)絡最常見的激活函數(shù)sigmoid函數(shù)!


實現(xiàn)這個單一神經(jīng)元很簡單
import numpy as np
def sigmoid(x):
return 1/(1+np.exp(-x))
a=-2
f=sigmoid(a)
print(f) #outputs 0.1192
Aim
接下來依舊是老套路,我們是=試著使輸出值增加。首先我們 就要計算Sigmoid的函數(shù)的導數(shù),根據(jù)微分的法則,我們可以求出

然后,就可以得到更新變量的方程:

我們用python實現(xiàn):
import numpy as np
def sigmoid(x):
return 1./(1+np.exp(-x))
def derivative_sigmoid(x):
return sigmoid(x) * (1 - sigmoid(x))
a = -2
h = 0.1
a = a + h * derivative_sigmoid(a)
f = sigmoid(a)
print(f) #outputs 0.1203
觀察輸出結果,0.1203比0.1192大.所以我們的算法成功將輸出值增加!
現(xiàn)在我們已經(jīng)知道如何對一個復雜的函數(shù)的神經(jīng)元進行反向傳播,從而改變輸出值!那么,接下來我們就將復雜函數(shù)放到一個嵌套的神經(jīng)網(wǎng)絡結構中,看看如何進行反向傳播的計算:

這個神經(jīng)網(wǎng)絡的結構就是在前文的基礎上增加了一個sigmoid函數(shù)!我們先用python實現(xiàn)它的正向傳播
import numpy as np
def addition(x,y):
return x+y
def product(x, y):
return x * y
def sigmoid(x):
return 1 / (1 + np.exp( -x ))
a=1
b=-2
c=-3
d=addition(a,b)
e=product(c,d)
f=sigmoid(e)
print(f) #outputs 0.952574
現(xiàn)在我們開始計算反向傳播,首先很明確的是,要進行反向傳播,就得求得所要更新變量的微分:

所以我們需要的計算就是a,b,c三個變量的偏導數(shù)!具體的求解規(guī)則和前文一樣就是倒著從輸出往回推,看看經(jīng)過了哪些神經(jīng)元的計算,然后利用鏈式法則:

希望讀者能獨立推導出上述的公式!
得到上述微分的計算公式,我們就要開始實際計算這些微分值,不難求出

如果讀者對此推導過程依舊有疑問,請重新閱讀前兩篇文章即能理解!
最后,就是編寫程序來實現(xiàn)反向傳播了!
import numpy as np
def addition(x, y):
return x + y
def product(x, y):
return x * y
def sigmoid(x):
return 1 / (1 + np.exp(-x))
def derivative_sigmoid(x):
return sigmoid(x) * (1 - sigmoid(x))
# initialization
a = 1
b = -2
c = -3
# forward-propogation
d = addition(a, b)
e = product(c, d)
# step size
h = 0.1
# derivatives
derivative_f_e = derivative_sigmoid(e)
derivative_e_d = c
derivative_e_c = d
derivative_d_a = 1
derivative_d_b = 1
# backward-propogation (Chain rule)
derivative_f_a = derivative_f_e * derivative_e_d * derivative_d_a
derivative_f_b = derivative_f_e * derivative_e_d * derivative_d_b
derivative_f_c = derivative_f_e * derivative_e_c
# update-parameters
a = a + h * derivative_f_a
b = b + h * derivative_f_b
c = c + h * derivative_f_c
d = addition(a, b)
e = product(c, d)
f = sigmoid(e)
print(f) # prints 0.9563
輸出結果是0.9563比0.9525大,可以看到,經(jīng)過一次反向傳播,我們的輸出值成功增加!
經(jīng)過練習,我們可以發(fā)現(xiàn),不管網(wǎng)絡多復雜,無非是鏈式法則求導是復雜一些,只要我們能求出微分,就能進行反向傳播!
待續(xù)
我們目前練習的都還是比較簡單的網(wǎng)絡,但恭喜你已經(jīng)了解到反向傳播的最核心的思想!下一篇文章小白也能看懂的BP反向傳播算法之Further into Backpropagation,我們會正式引入一個真實的神經(jīng)網(wǎng)絡結構,然后進行反向傳播的計算!并且利用矩陣來簡化計算過程!
本文相關代碼可以從Backpropagation下載