BP神经网络公式推导(含代码实现)

本文详细介绍了BP神经网络的基本概念,包括其前向传播和反向传播过程,单神经元梯度,以及如何通过误差反传调整权重。重点讲解了隐含层节点选择的公式,并通过实例演示了多层神经网络的学习过程。

什么是BP神经网络

BP(Back Propagation)神经网络是一种按误差反向传播(简称误差反传)训练的多层前馈网络,它的基本思想是梯度下降法,利用梯度搜索技术,以期使网络的实际输出值期望输出值误差最小

BP神经网络包括信号的前向传播误差的反向传播两个过程。即计算误差输出时按从输入到输出的方向进行,而调整权值和阈值则从输出到输入的方向进行。

网络结构:BP神经网络整个网络结构包含了:一层输入层,一到多层隐含层,一层的输出层。

img

隐含层的选取

在BP神经网络中,输入层和输出层的节点个数都是确定的,而隐含层节点个数不确定,那么应该设置为多少才合适呢?实际上,隐含层的节点个数的多少对神经网络的性能是有影响的,有一个经验公式可以确定隐含层节点数目,公式如下:
h=m+n+a h=\sqrt{m+n}+a h=m+n+a
其中h为隐含层节点数目,m为输入层节点数目,n为输出层节点数目,a为1~10之间的调节常数。

单神经元梯度

信号的前向传播

为了便于理解,这里先用单个神经元梯度为例。

在这里插入图片描述

图中有两个输入[x1,x2][x_1,x_2][x1,x2],两个权值[w1,w2][w_1,w_2][w1,w2],偏置值为w0w_0w0,f为激活函数。

前向传播过程中:
z=w0x0+w1x1+w2x2=∑i=02wixi,其中x0=1y=f∑i=02wixi z=w_0x_0+w_1x_1+w_2x_2=\sum_{i=0}^2w_ix_i,其中x_0=1 \\ y=f\sum_{i=0}^2w_ix_i z=w0x0+w1x1+w2x2=i=02wixi,x0=1y=fi=02wixi
用向量形式可表示为:
z=∑i=02wixi=wTxy=f(wTx) z=\sum_{i=0}^2w_ix_i=w^Tx \\ y=f(w^Tx) z=i=02wixi=wTxy=f(wTx)

误差的反向传播

在BP神经网络中,误差反向传播基于Delta学习规则。我们已知输出层的结果为y=y=f(wTx)y=y=f(w^Tx)y=y=f(wTx),对于预测值与真实值之间误差的计算,我们使用如下公式(代价函数):
E=12(t−y)2 E=\frac{1}{2}(t-y)^2 E=21(ty)2
其中真实值为t。

BP神经网络的主要目的是修正权值,使得误差数值达到最小。Delta学习规则是一种利用梯度下降的一般性的学习规则。公式如下:
ΔW=−ŋE′δEδw=δ12[t−f(wTx)]2δw=12∗2[t−f(wTx)]∗(−f′(wTx))δwTxδw=−(t−y)f′(wTx)xΔW=−ŋE′=ŋ(t−y)f′(wTx)x=ŋδx,其中δ=(t−y)f′(wTx) \begin{aligned} Δ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{aligned} ΔWδwδEΔW=ŋE=δwδ21[tf(wTx)]2=212[tf(wTx)](f(wTx))δwδwTx=(ty)f(wTx)x=ŋE=ŋ(ty)f(wTx)x=ŋδx,δ=(ty)f(wTx)

Delta学习规则小结

在这里插入图片描述

全连接层梯度

img

正向传播

第一层

输入x1,x2,x3x_1,x_2,x_3x1,x2,x3

h11=u11x1+u21x2+u31x3=∑i=13ui1xih21=u12x1+u22x2+u32x3=∑i=13ui2xiH11=f(h11)H21=f(h21)h1=[h11,h21]=[u11u21u31u12u22u32]T[x1x2x3]=uTxH1=f(uTx) 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{bmatrix} u_{11} & u_{21} & u_{31} \\ u_{12} & u_{22} & u_{32} \end{bmatrix}^T \begin{bmatrix} x_1 \\ x_2 \\ x_3 \end{bmatrix} =u^Tx \\ H^1=f(u^Tx) h11=u11x1+u21x2+u31x3=i=13ui1xih21=u12x1+u22x2+u32x3=i=13ui2xiH11=f(h11)H21=f(h21)h1=[h11,h21]=[u11u12u21u22u31u32]Tx1x2x3=uTxH1=f(uTx)
上图有两个隐含层,为了便于解释,这里用xijx_i^jxij表示第j层的第i个节点,如h11h_1^1h11表示第一个隐含层的第一个节点。

第二层

输入H11,H21H_1^1,H2^1H11,H21
h12=w11H11+w21H21h22=w12H11+w22H21H12=f(h12)h22=f(h22)h2=[h12,h22]=[w11w21w12w22]T[H11H21]=wTH1H2=f(wTH1) 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{bmatrix} w_{11} & w_{21} \\ w_{12} & w_{22} \end{bmatrix}^T \begin{bmatrix} H_1^1 \\ H_2^1 \end{bmatrix} =w^TH^1 \\ H^2=f(w^TH^1) h12=w11H11+w21H21h22=w12H11+w22H21H12=f(h12)h22=f(h22)h2=[h12,h22]=[w11w12w21w22]T[H11H21]=wTH1H2=f(wTH1)
输出层

输入H12,h22H_1^2,h_2^2H12,h22
y=f(v1H12+v2H22)=f(vTH2) y=f(v_1H_1^2+v_2H_2^2)=f(v^TH^2) y=f(v1H12+v2H22)=f(vTH2)

反向传播

输出层
ΔW=−ŋE′=ŋ(t−y)f′(vTH2)H2=ŋδH2δ=(t−y)f′(vTH2) \begin{aligned} ΔW&=-ŋE'=ŋ(t-y)f'(v^TH^2)H^2=ŋ\delta H^2 \\ \delta&=(t-y)f'(v^TH^2) \end{aligned} ΔWδ=ŋE=ŋ(ty)f(vTH2)H2=ŋδH2=(ty)f(vTH2)
第二层

首先根据Delta学习规则可得:
ΔW=−ŋE′δEδw=δ12[t−f(vTH2)]2δw=12∗2[t−f(vTH2)]∗(−f′(vTH2))δvTH2δw=−(t−y)f′(vTH2)δvTH2δw \begin{aligned} Δ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{aligned} ΔWδwδE=ŋE=δwδ21[tf(vTH2)]2=212[tf(vTH2)](f(vTH2))δwδvTH2=(ty)f(vTH2)δwδvTH2
此时我们先计算δvTH2δw\frac{\delta v^TH^2}{\delta w}δwδvTH2的取值:
δvTH2δw=δvTH2δH2∗δH2δw=vTδf(wTH1)δw=vTf′(WTH1)H1 \begin{aligned} \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{aligned} δwδvTH2=δH2δvTH2δwδH2=vTδwδf(wTH1)=vTf(WTH1)H1
这样我们就可以将上述结果带入到ΔWΔWΔW
ΔW=ŋ(t−y)f′(vTH2)δvTH2δw=ŋ(t−y)f′(vTH2)vTf′(WTH1)H1=ŋδvTf′(WTH1)H1=ŋδ2H1 \begin{aligned} Δ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{aligned} ΔW=ŋ(ty)f(vTH2)δwδvTH2=ŋ(ty)f(vTH2)vTf(WTH1)H1=ŋδvTf(WTH1)H1=ŋδ2H1
最后我们就得到了δ2\delta^2δ2
δ2=δvTf′(WTH1) \delta^2=\delta v^Tf'(W^TH^1) δ2=δvTf(WTH1)
第一层

首先根据Delta学习规则可得:
ΔW=−ŋE′δEδu=δ12[t−f(vTH2)]2δu=12∗2[t−f(vTH2)]∗(−f′(vTH2))δvTH2δu=−(t−y)f′(vTH2)δvTH2δu \begin{aligned} Δ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{aligned} ΔWδuδE=ŋE=δuδ21[tf(vTH2)]2=212[tf(vTH2)](f(vTH2))δuδvTH2=(ty)f(vTH2)δuδvTH2

此时我们先计算δvTH2δu\frac{\delta v^TH^2}{\delta u}δuδvTH2的取值:
δvTH2δu=δvTH2δH2∗δH2δH1∗δH1δu=vTδf(wTH1)δH1∗δf(uTx)δu=vTf′(wTH1)wT∗f′(uTx)x \begin{aligned} \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{aligned} δuδvTH2=δH2δvTH2δH1δH2δuδH1=vTδH1δf(wTH1)δuδf(uTx)=vTf(wTH1)wTf(uTx)x
这样我们就可以将上述结果带入到ΔWΔWΔW
ΔW=ŋ(t−y)f′(vTH2)δvTH2δu=ŋ(t−y)f′(vTH2)vTf′(wTH1)wT∗f′(uTx)x=ŋδvTf′(wTH1)wT∗f′(uTx)x=ŋδ2wTf′(uTx)x=ŋδ1x \begin{aligned} Δ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{aligned} ΔW=ŋ(ty)f(vTH2)δuδvTH2=ŋ(ty)f(vTH2)vTf(wTH1)wTf(uTx)x=ŋδvTf(wTH1)wTf(uTx)x=ŋδ2wTf(uTx)x=ŋδ1x
参考
δ=(t−y)f′(vTH2)δ2=δvTf′(WTH1) \delta=(t-y)f'(v^TH^2) \\ \delta^2=\delta v^Tf'(W^TH^1) δ=(ty)f(vTH2)δ2=δvTf(WTH1)
最后我们就得到了δ1\delta^1δ1
δ1=δ2wTf′(uTx) \delta^1=\delta^2w^Tf'(u^Tx) δ1=δ2wTf(uTx)

代码

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)

参考资料:

https://segmentfault.com/a/1190000021529971

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NicKernel

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值