什么是BP神經網絡
BP(Back )神經網絡是一種按誤差反向傳播(簡稱誤差反傳)訓練的多層前饋網絡,它的基本思想是梯度下降法,利用梯度搜索技術,以期使網絡的實際輸出值和期望輸出值的誤差最小。
BP神經網絡包括信號的前向傳播和誤差的反向傳播兩個過程。即計算誤差輸出時按從輸入到輸出的方向進行,而調整權值和閾值則從輸出到輸入的方向進行。
網絡結構:BP神經網絡整個網絡結構包含了:一層輸入層,一到多層隱含層,一層的輸出層。
隱含層的選取
在BP神經網絡中,輸入層和輸出層的節點個數都是確定的,而隱含層節點個數不確定多層神經網絡bp算法權值更新過程,那么應該設置為多少才合適呢?實際上,隱含層的節點個數的多少對神經網絡的性能是有影響的,有一個經驗公式可以確定隱含層節點數目,公式如下:
h=\sqrt{m+n}+a
其中h為隱含層節點數目,m為輸入層節點數目,n為輸出層節點數目,a為1~10之間的調節常數。
單神經元梯度信號的前向傳播
為了便于理解,這里先用單個神經元梯度為例。
圖中有兩個輸入 [x_1,x_2] ,兩個權值 [w_1,w_2]多層神經網絡bp算法權值更新過程,偏置值為 w_0 ,f為激活函數。
前向傳播過程中:
z=++=\sum_{i=0}^,其中x_0=1 \\ y=f\sum_{i=0}^
用向量形式可表示為:
z=\sum_{i=0}^=w^Tx \\ y=f(w^Tx)
誤差的反向傳播
在BP神經網絡中,誤差反向傳播基于Delta學習規則。我們已知輸出層的結果為 y=y=f(w^Tx) ,對于預測值與真實值之間誤差的計算,我們使用如下公式(代價函數):
E=\frac{1}{2}(t-y)^2
其中真實值為t。
BP神經網絡的主要目的是修正權值,使得誤差數值達到最小。Delta學習規則是一種利用梯度下降的一般性的學習規則。公式如下:
\begin{} ΔW&=-?E' \\ \frac{\delta E}{\delta w}&=\frac{\delta\frac{1}{2}[t-f(w^Tx)]^2}{\delta w} \\ &=\frac{1}{2}*2[t-f(w^Tx)]*(-f'(w^Tx))\frac{\delta w^Tx}{\delta w} \\ &=-(t-y)f'(w^Tx)x \\ ΔW&=-?E'=?(t-y)f'(w^Tx)x=?\delta x,其中\delta=(t-y)f'(w^Tx) \end{}
Delta學習規則小結
全連接層梯度
正向傳播
第一層
輸入 x_1,x_2,x_3
h_{1}^1=u_{11}x_1+u_{21}x_2+u_{31}x_3=\sum_{i=1}^3u_{i1}x_i \\ h_{2}^1=u_{12}x_1+u_{22}x_2+u_{32}x_3=\sum_{i=1}^3u_{i2}x_i \\ H_{1}^1=f(h_{1}^1) \\ H_{2}^1=f(h_{2}^1) \\ h^1=[h_1^1,h_2^1]=\begin{} u_{11} & u_{21} & u_{31} \\ u_{12} & u_{22} & u_{32} \end{}^T \begin{} x_1 \\ x_2 \\ x_3 \end{} =u^Tx \\ H^1=f(u^Tx)
上圖有兩個隱含層,為了便于解釋,這里用 x_i^j 表示第j層的第i個節點,如 h_1^1 表示第一個隱含層的第一個節點。
第二層
輸入 H_1^1,H2^1
h_1^2=w_{11}H_1^1+w_{21}H_2^1 \\ h_2^2=w_{12}H_1^1+w_{22}H_2^1 \\ H_1^2=f(h_1^2) \\ h_2^2=f(h_2^2) \\ h^2=[h_1^2,h_2^2]=\begin{} w_{11} & w_{21} \\ w_{12} & w_{22} \end{}^T \begin{} H_1^1 \\ H_2^1 \end{} =w^TH^1 \\ H^2=f(w^TH^1)
輸出層
輸入 H_1^2,H_2^2
y=f(^2+^2)=f(v^TH^2)
反向傳播
輸出層
\begin{} ΔW&=-?E'=?(t-y)f'(v^TH^2)H^2=?\delta H^2 \\ \delta&=(t-y)f'(v^TH^2) \end{}
第二層
首先根據Delta學習規則可得:
\begin{} ΔW&=-?E' \\ \frac{\delta E}{\delta w}&=\frac{\delta\frac{1}{2}[t-f(v^TH^2)]^2}{\delta w} \\ &=\frac{1}{2}*2[t-f(v^TH^2)]*(-f'(v^TH^2))\frac{\delta v^TH^2}{\delta w} \\ &=-(t-y)f'(v^TH^2)\frac{\delta v^TH^2}{\delta w} \end{}
此時我們先計算 \frac{\delta v^TH^2}{\delta w} 的取值:
\begin{} \frac{\delta v^TH^2}{\delta w}&=\frac{\delta v^TH^2}{\delta H^2}*\frac{\delta H^2}{\delta w} \\ &=v^T\frac{\delta f(w^TH^1)}{\delta w} \\ &=v^Tf'(W^TH^1)H^1 \end{}
這樣我們就可以將上述結果帶入到 ΔW 中
\begin{} ΔW&=?(t-y)f'(v^TH^2)\frac{\delta v^TH^2}{\delta w} \\ &=?(t-y)f'(v^TH^2)v^Tf'(W^TH^1)H^1 \\ &=?\delta v^Tf'(W^TH^1)H^1 \\ &=?\delta^2H^1 \end{}
最后我們就得到了 \delta^2
\delta^2=\delta v^Tf'(W^TH^1)
第一層
首先根據Delta學習規則可得:
\begin{} ΔW&=-?E' \\ \frac{\delta E}{\delta u}&=\frac{\delta\frac{1}{2}[t-f(v^TH^2)]^2}{\delta u} \\ &=\frac{1}{2}*2[t-f(v^TH^2)]*(-f'(v^TH^2))\frac{\delta v^TH^2}{\delta u} \\ &=-(t-y)f'(v^TH^2)\frac{\delta v^TH^2}{\delta u} \end{}
此時我們先計算 \frac{\delta v^TH^2}{\delta u} 的取值:
\begin{} \frac{\delta v^TH^2}{\delta u}&=\frac{\delta v^TH^2}{\delta H^2}*\frac{\delta H^2}{\delta H^1}*\frac{\delta H^1}{\delta u} \\ &=v^T\frac{\delta f(w^TH^1)}{\delta H^1}*\frac{\delta f(u^Tx)}{\delta u} \\ &=v^Tf'(w^TH^1)w^T*f'(u^Tx)x \end{}
這樣我們就可以將上述結果帶入到 ΔW 中
\begin{} ΔW&=?(t-y)f'(v^TH^2)\frac{\delta v^TH^2}{\delta u} \\ &=?(t-y)f'(v^TH^2)v^Tf'(w^TH^1)w^T*f'(u^Tx)x \\ &=?\delta v^Tf'(w^TH^1)w^T*f'(u^Tx)x \\ &=?\delta^2w^Tf'(u^Tx)x \\ &=?\delta^1x \end{}
參考
\delta=(t-y)f'(v^TH^2) \\ \delta^2=\delta v^Tf'(W^TH^1)
最后我們就得到了 \delta^1
\delta^1=\delta^2w^Tf'(u^Tx)
代碼
import numpy as np
?
#輸入數據
X = np.array([[1,0,0],
[1,0,1],
[1,1,0],
[1,1,1]])
#標簽
Y = np.array([[0,1,1,0]])
#權值初始化,取值范圍-1到1
V = np.random.random((3,4))*2-1
W = np.random.random((4,1))*2-1

print(V)
print(W)
#學習率設置
lr = 0.11
?
def sigmoid(x):
return 1/(1+np.exp(-x))
?
def dsigmoid(x):
return x*(1-x)
?
def update():
global X,Y,W,V,lr
L1 = sigmoid(np.dot(X,V))#隱藏層輸出(4,4)
L2 = sigmoid(np.dot(L1,W))#輸出層輸出(4,1)
L2_delta = (Y.T - L2)*dsigmoid(L2)

L1_delta = L2_delta.dot(W.T)*dsigmoid(L1)
W_C = lr*L1.T.dot(L2_delta)
V_C = lr*X.T.dot(L1_delta)
W = W + W_C
V = V + V_C
for i in range(20000):
update()#更新權值
if i%500==0:
L1 = sigmoid(np.dot(X,V))#隱藏層輸出(4,4)
L2 = sigmoid(np.dot(L1,W))#輸出層輸出(4,1)
print('Error:',np.mean(np.abs(Y.T-L2)))
L1 = sigmoid(np.dot(X,V))#隱藏層輸出(4,4)
L2 = sigmoid(np.dot(L1,W))#輸出層輸出(4,1)
print(L2)
參考資料:
/a/29971