深度学习——反向传播(BP)算法
1、BP算法引入
1.1 网络基本结构
在之前的文章深度学习——神经网络前向传播与反向求导过程中,我们简单的构建了一个简单的神经网络,描述了其前向传播过程和反向求导的过程。之前的描述的网络结构十分简单,仅仅包含一层的输入层,一层的隐藏层和一层的输出层,并且输出层是一个标量的输出。通常情况下,一个完整的神经网络是要包含多层隐藏层的。下面,我们就具体来展示一下。
上图是具有两层隐藏层的神经网络结构。
提示:在神经网络中,一般情况下,隐藏层的节点数量是不固定的,下面给出一个经验公式来确定隐藏层节点的数量:
h
=
m
+
n
+
a
h = \sqrt{m+n}+a
h=m+n+a
其中h是隐藏层节点的数量,m是输入节点的数量,n是输出节点的数量,a是一个1~10之间的一个常数。
1.2 网络参数
训练样本集合:
D
=
{
(
X
1
,
Y
1
)
,
(
X
2
,
Y
2
)
,
.
.
.
.
.
.
(
X
N
,
Y
N
)
}
D=\{(X_1,Y_1),(X_2,Y_2),......(X_N,Y_N)\}
D={(X1,Y1),(X2,Y2),......(XN,YN)}
其中每一个样本
X
i
X_i
Xi包含两个属性,表示为
X
i
=
x
1
x
2
X_i= \begin{matrix} x_1\\ x_2 \end{matrix}
Xi=x1x2
其中每一个样本的标签
Y
i
Y_i
Yi包含两个属性,表示为
Y
i
=
y
1
y
2
Y_i= \begin{matrix} y_1\\ y_2 \end{matrix}
Yi=y1y2
权重矩阵包括三个,第一个是输入层向第一层隐藏层输入的权重矩阵W,第二个是第一层隐藏层向第二层隐藏层输入的权重矩阵V,第三个是第二层隐藏层向输出层的权重矩阵U。分别表示为:
W
=
w
11
w
12
w
13
w
21
w
22
w
23
W= \begin{matrix} w_{11} & w_{12} & w_{13} \\ w_{21} & w_{22} & w_{23} \end{matrix}
W=w11w21w12w22w13w23
V
=
v
11
v
12
v
13
v
21
v
22
v
23
v
31
v
32
v
33
V= \begin{matrix} v_{11} & v_{12} & v_{13} \\ v_{21} & v_{22} & v_{23} \\ v_{31} & v_{32} & v_{33} \end{matrix}
V=v11v21v31v12v22v32v13v23v33
U
=
u
11
u
12
u
21
u
22
u
31
u
32
U= \begin{matrix} u_{11} & u_{12}\\ u_{21} & u_{22} \\ u_{31} & u_{32} \end{matrix}
U=u11u21u31u12u22u32
1.3 前向传播过程
具体的传播过程,我们已经在之前的文章中提到过,所以,我们在这里仅仅出代码的实现过程。
#encoding=utf-8
import numpy as np
def sigmoid(x):
return 1/(1+np.exp(-x))
class NetWork:
def __init__(self,input_dim,hidden1_dim,hidden2_dim,output_dim):
self.input_dim = input_dim
self.hidden1_dim = hidden1_dim
self.hidden2_dim = hidden2_dim
self.output_dim = output_dim
self.W = np.random.rand(input_dim,hidden1_dim)
self.B1 = np.random.rand(hidden1_dim,1)
self.V = np.random.rand(hidden1_dim,hidden2_dim)
self.B2 = np.random.rand(hidden2_dim,1)
self.U = np.random.rand(hidden2_dim,output_dim)
self.B3 = np.random.rand(output_dim,1)
def forward(self,X):
'''注意,这里我们先采用的逐个样本的计算方式,激活方式采用的是sigmoid激活函数'''
net1 = np.dot(self.W.T,X) + self.B1
H1 = sigmoid(net1)
net2 = np.dot(self.V.T,H1) + self.B2
H2 = sigmoid(net2)
Y = np.dot(self.U.T,H2) + self.B3
return net1,net2,H1,H2,Y
其计算的基本公式为:
n
e
t
1
=
W
T
X
+
B
1
net_1 = W^TX+B1
net1=WTX+B1
h
1
=
s
i
g
m
o
i
d
(
n
e
t
1
)
h_1 = sigmoid(net_1)
h1=sigmoid(net1)
n
e
t
2
=
V
T
h
1
+
B
2
net_2 = V^Th_1+B2
net2=VTh1+B2
h
2
=
s
i
g
m
o
i
d
(
n
e
t
2
)
h_2 = sigmoid(net_2)
h2=sigmoid(net2)
Y
=
U
T
h
2
+
B
3
Y=U^Th2+B3
Y=UTh2+B3
2 反向传播(BP)算法
2.1 反向传播算法概述
对于一般的前馈神经网络而言,其训练的过程及时不断的调节网络中的权重和偏置项两类参数,前馈型神经网络。前馈神经网络的训练方法主要是反向传播算法,反向传播算法包括正向的输出过程和反向的误差传播过程。正向过程就是我们上面的描述的从输入到输出的前向传播过程。反向误差传播过程则是根据输出值反向逐层调整网络的权重和偏置项。
2.2反向传播算法的过程计算
2.2.1 误差函数的选择
这里我们依然采用的是MSE的误差计算函数,其基本公式为:
J
=
1
2
∗
∑
i
=
1
b
(
y
r
i
−
y
i
)
2
J=\frac{1}{2}*∑_{i=1}^{b}(y_{ri}-y_i)^2
J=21∗i=1∑b(yri−yi)2
其中labelY共有b个属性,
y
r
i
y_{ri}
yri表示y的第i个属性的真实值。
y
i
y_i
yi表示第i个属性的预测值。
2.2.2 对于net求导
为了方便展示,我们再次将网络结构图进行展示。
上面,我们提到了反向传播是一个逐层进行的过程。我首先计算出输出层的误差为:
J
=
1
2
∗
∑
i
=
1
2
(
y
r
i
−
y
i
)
2
J =\frac{1}{2}*∑_{i=1}^{2}(y_{ri}-y_i)^2
J=21∗i=1∑2(yri−yi)2
-
我们先对输出层求导。计算过程为:
∂ J ∂ y 1 ∂ J ∂ y 2 = ∂ 1 2 ( y r 1 − y 1 ) + ( y r 2 − y 2 ) δ y 1 δ 1 2 ( y r 1 − y 1 ) + ( y r 2 − y 2 ) δ y 2 = y 1 − y r 1 y 2 − y r 2 \begin{matrix} \frac{∂J}{∂y_{1}}\\ \\ \frac{∂J}{∂y_{2}} \end{matrix}= \begin{matrix} \frac{∂\frac{1}{2}(y_{r1}-y_1)+(y_{r2}-y_2)}{δy_{1}}\\ \\ \frac{δ\frac{1}{2}(y_{r1}-y_1)+(y_{r2}-y_2)}{δy_{2}} \end{matrix}= \begin{matrix} y_1-y_{r1}\\ \\ y_2-y_{r2} \end{matrix} ∂y1∂J∂y2∂J=δy1∂21(yr1−y1)+(yr2−y2)δy2δ21(yr1−y1)+(yr2−y2)=y1−yr1y2−yr2
我们将J关于Y的偏导数记为:
δ y = Y − Y r δ_y=Y-Y_r δy=Y−Yr -
下面我们要计算的是对于 n e t 2 net_2 net2的偏导数, n e t 2 net_2 net2表示的是对于输入到第二隐藏的各个神经单元未激活时的数据。一共包含三个单元, n e t 21 , n e t 22 , n e t 23 net_{21},net_{22},net_{23} net21,net22,net23
首先计算对于 n e t 21 net_{21} net21的导数值。
∂ J ∂ n e t 21 = ∂ J ∂ y 1 ∂ y 1 ∂ h 21 ∂ h 21 ∂ n e t 21 + ∂ J ∂ y 2 ∂ y 2 ∂ h 21 ∂ h 21 ∂ n e t 21 = ∑ i = 1 L ∂ J ∂ y i ∗ U 1 i ∗ h 21 ∗ ( 1 − h 21 ) \frac{∂J}{∂net_{21}}=\frac{∂J}{∂y_{1}}\frac{∂y_1}{∂h_{21}}\frac{∂h_{21}}{∂net_{21}}+\frac{∂J}{∂y_{2}}\frac{∂y_2}{∂h_{21}}\frac{∂h_{21}}{∂net_{21}}=∑_{i=1}^L\frac{∂J}{∂y_{i}}*U_{1i}*h_{21}*(1-h_{21}) ∂net21∂J=∂y1∂J∂h21∂y1∂net21∂h21+∂y2∂J∂h21∂y2∂net21∂h21=i=1∑L∂yi∂J∗U1i∗h21∗(1−h21)
同理可以计算另外两个神经单元:
∂ J ∂ n e t 22 = ∂ J ∂ y 1 ∂ y 1 ∂ h 22 ∂ h 22 ∂ n e t 22 + ∂ J ∂ y 2 ∂ y 2 ∂ h 22 ∂ h 22 ∂ n e t 22 = ∑ i = 1 L ∂ J ∂ y i ∗ U 2 i ∗ h 22 ∗ ( 1 − h 22 ) \frac{∂J}{∂net_{22}}=\frac{∂J}{∂y_{1}}\frac{∂y_1}∂{h_{22}}\frac{∂h_{22}}{∂net_{22}}+\frac{∂J}{∂y_{2}}\frac{∂y_2}{∂h_{22}}\frac{∂h_{22}}{∂net_{22}}=∑_{i=1}^L\frac{∂J}{∂y_{i}}*U_{2i}*h_{22}*(1-h_{22}) ∂net22∂J=∂y1∂J∂∂y1h22∂net22∂h22+∂y2∂J∂h22∂y2∂net22∂h22=i=1∑L∂yi∂J∗U2i∗h22∗(1−h22)
∂ J ∂ n e t 23 = ∂ J ∂ y 1 ∂ y 1 ∂ h 23 ∂ h 21 ∂ n e t 23 + ∂ J ∂ y 2 ∂ y 2 ∂ h 23 ∂ h 23 ∂ n e t 23 = ∑ i = 1 L ∂ J ∂ y i ∗ U 3 i ∗ h 23 ∗ ( 1 − h 23 ) \frac{∂J}{∂net_{23}}=\frac{∂J}{∂y_{1}}\frac{∂y_1}{∂h_{23}}\frac{∂h_{21}}{∂net_{23}}+\frac{∂J}{∂y_{2}}\frac{∂y_2}{∂h_{23}}\frac{∂h_{23}}{∂net_{23}}=∑_{i=1}^L\frac{∂J}{∂y_{i}}*U_{3i}*h_{23}*(1-h_{23}) ∂net23∂J=∂y1∂J∂h23∂y1∂net23∂h21+∂y2∂J∂h23∂y2∂net23∂h23=i=1∑L∂yi∂J∗U3i∗h23∗(1−h23)
整理成向量的形式为:
δ
n
e
t
2
=
δ
J
δ
n
e
t
2
=
δ
J
δ
n
e
t
21
δ
J
δ
n
e
t
22
δ
J
δ
n
e
t
23
=
U
T
δ
Y
∗
h
2
∗
(
1
−
h
2
)
δ_{net_2}=\frac{δJ}{δnet_2}= \begin{matrix} \frac{δJ}{δnet_{21}}\\ \\ \frac{δJ}{δnet_{22}}\\ \\ \frac{δJ}{δnet_{23}}\\ \\ \end{matrix}= U^Tδ_Y*h_2*(1-h_2)
δnet2=δnet2δJ=δnet21δJδnet22δJδnet23δJ=UTδY∗h2∗(1−h2)
3. 最后我们要计算的是关于
n
e
t
1
net_1
net1的偏导数。
首先计算对于
n
e
t
11
net_{11}
net11的导数值。
我首先对
n
e
t
11
net_{11}
net11向上的传递过程进行分析。
n
e
t
11
net_{11}
net11通过激活函数生成
h
11
h_{11}
h11,然后
h
11
h_{11}
h11j将值分别传递给了
h
21
,
h
22
,
h
23
h_{21},h_{22},h_{23}
h21,h22,h23,最后
h
21
,
h
22
,
h
23
h_{21},h_{22},h_{23}
h21,h22,h23又分别将信息传递给了
y
1
,
y
2
y_1,y_2
y1,y2。则通过链式法则,我们不难发现有以下几个步骤:
a). 总误差J对
y
1
,
y
2
y_1,y_2
y1,y2求导形成误差δY。
b).
h
2
h_2
h2层的每个单元分别从
y
1
,
y
2
y_1,y_2
y1,y2处获得误差和,求导之后形成
n
e
t
2
net_2
net2的误差
c}.
h
11
h_{11}
h11分别从
h
2
h_2
h2层的每一个单元获得误差,求和,计算出总的误差值。
d). 根据
h
11
h_{11}
h11获得的误差值,求导,确定了
n
e
t
11
net_{11}
net11的误差值。
我们采用数学方式进行表示:
a) 总误差J对Y求导表示为:
δ
y
=
δ
y
1
δ
y
2
δy= \begin{matrix} δy_1\\ δy_2 \end{matrix}
δy=δy1δy2
b) 形成
Y
到
n
e
t
2
Y到net_2
Y到net2的误差
δ
n
e
t
2
=
δ
Y
δ
n
e
t
2
δ_{net_2}=\frac{δY}{δnet_2}
δnet2=δnet2δY
c) 形成从
n
e
t
2
net_2
net2到
h
11
h_{11}
h11的误差:
∑
i
=
1
3
n
e
t
2
i
h
11
=
V
11
+
V
12
+
V
13
∑_{i=1}^3\frac{net_{2i}}{h_{11}}=V_{11}+V_{12}+V_{13}
i=1∑3h11net2i=V11+V12+V13
d). 形成从
h
11
h_{11}
h11的到
n
e
t
11
net_{11}
net11的误差:
∂
h
11
∂
n
e
t
11
=
h
11
∗
(
1
−
h
11
)
\frac{∂h_{11}}{∂net_{11}}=h_{11}*(1-h_{11})
∂net11∂h11=h11∗(1−h11)
n e t 12 , n e t 13 net_{12},net_{13} net12,net13的误差传递过程与 n e t 11 net_{11} net11类似,只不过是从 h 12 , h 13 h_{12},h_{13} h12,h13处获取误差值。
我们利用链式法则对于上述的误差传递过程进行总结得到:
δ
n
e
t
1
=
∂
J
∂
n
e
t
1
=
V
T
δ
2
∗
h
1
∗
(
1
−
h
1
)
=
∂
J
∂
n
e
t
11
∂
J
∂
n
e
t
12
∂
J
∂
n
e
t
13
δ_{net_1}=\frac{∂J}{∂net_{1}}=V^Tδ_2*h_1*(1-h_1)= \begin{matrix} \frac{∂J}{∂net_{11}}\\ \\ \frac{∂J}{∂net_{12}}\\ \\ \frac{∂J}{∂net_{13}}\\ \end{matrix}
δnet1=∂net1∂J=VTδ2∗h1∗(1−h1)=∂net11∂J∂net12∂J∂net13∂J
其中”*“表示对位相乘,其他表示矩阵相乘。
2.3 总结
我们发现了,对于BP算法的核心,就是对于各个net进行求导计算误差,在这过程中,我们可以发现,对于底层的net的导数,根据链式法则,可以复用高层次的net的导数。那么,为什么要对net求导呢?
我们根据前向传播的公式可以看出,参数W,V,U是和net直接相关的,也就是说,我们在确定了net的导数之后,可以直接确定参数权重的导数。
3、反向传播的权重更新
3.1 计算相关权重的最终梯度
3.1.1 关于U的梯度
[
∂
J
∂
u
11
,
∂
J
∂
u
12
]
=
[
∂
J
∂
y
1
∗
∂
y
1
∂
u
11
,
∂
J
∂
y
2
∗
∂
y
2
∂
u
12
]
[\frac{∂J}{∂u_{11}},\frac{∂J}{∂u_{12}}]=[\frac{∂J}{∂y_{1}}*\frac{∂y_1}{∂u_{11}},\frac{∂J}{∂y_{2}}*\frac{∂y_2}{∂u_{12}}]
[∂u11∂J,∂u12∂J]=[∂y1∂J∗∂u11∂y1,∂y2∂J∗∂u12∂y2]
[
∂
J
∂
u
21
,
∂
J
∂
u
22
]
=
[
∂
J
∂
y
1
∗
∂
y
1
∂
u
21
,
∂
J
∂
y
2
∗
∂
y
2
∂
u
22
]
[\frac{∂J}{∂u_{21}},\frac{∂J}{∂u_{22}}]=[\frac{∂J}{∂y_{1}}*\frac{∂y_1}{∂u_{21}},\frac{∂J}{∂y_{2}}*\frac{∂y_2}{∂u_{22}}]
[∂u21∂J,∂u22∂J]=[∂y1∂J∗∂u21∂y1,∂y2∂J∗∂u22∂y2]
[
∂
J
∂
u
31
,
∂
J
∂
u
32
]
=
[
∂
J
∂
y
1
∗
∂
y
1
∂
u
31
,
∂
J
∂
y
2
∗
∂
y
2
∂
u
32
]
[\frac{∂J}{∂u_{31}},\frac{∂J}{∂u_{32}}]=[\frac{∂J}{∂y_{1}}*\frac{∂y_1}{∂u_{31}},\frac{∂J}{∂y_{2}}*\frac{∂y_2}{∂u_{32}}]
[∂u31∂J,∂u32∂J]=[∂y1∂J∗∂u31∂y1,∂y2∂J∗∂u32∂y2]
整理一下,误差对于权重U的梯度为
∂
J
∂
U
=
∂
J
∂
u
11
∂
J
∂
u
12
∂
J
∂
u
11
∂
J
∂
u
12
∂
J
∂
u
11
∂
J
∂
u
12
=
∂
J
∂
Y
∗
[
h
2
∣
∣
h
2
]
=
δ
Y
∗
[
h
2
∣
∣
h
2
]
\frac{∂J}{∂U}= \begin{matrix} \frac{∂J}{∂u_{11}} & \frac{∂J}{∂u_{12}} \\ \frac{}{} & \frac{}{}\\ \frac{∂J}{∂u_{11}} & \frac{∂J}{∂u_{12}}\\ \frac{}{} & \frac{}{}\\ \frac{∂J}{∂u_{11}} & \frac{∂J}{∂u_{12}} \end{matrix}= \frac{∂J}{∂Y} * [h_2||h_2]=δ_Y*[h2||h2]
∂U∂J=∂u11∂J∂u11∂J∂u11∂J∂u12∂J∂u12∂J∂u12∂J=∂Y∂J∗[h2∣∣h2]=δY∗[h2∣∣h2]
其中
h
2
h_2
h2表示第二个隐藏层的神经单元,具体为:
h
21
h
22
h
23
\begin{matrix} h_{21} \\ h_{22} \\ h_{23} \end{matrix}
h21h22h23
下面的
h
1
,
X
h1,X
h1,X类似。
3.1.2 关于V的梯度
根据输入
n
e
t
2
=
V
T
h
1
+
B
2
net_2 = V^Th_1+B2
net2=VTh1+B2
有
∂
n
e
t
2
∂
V
11
=
∂
n
e
t
21
∂
V
11
=
h
11
∂
n
e
t
2
∂
V
12
=
∂
n
e
t
22
∂
V
12
=
h
11
∂
n
e
t
2
∂
V
13
=
∂
n
e
t
23
∂
V
12
=
h
11
\frac{∂net_2}{∂V_{11}}=\frac{∂net_{21}}{∂V_{11}}=h_{11}\\ \frac{}{}\\ \frac{∂net_2}{∂V_{12}}=\frac{∂net_{22}}{∂V_{12}}=h_{11}\\ \frac{}{}\\ \frac{∂net_2}{∂V_{13}}=\frac{∂net_{23}}{∂V_{12}}=h_{11}
∂V11∂net2=∂V11∂net21=h11∂V12∂net2=∂V12∂net22=h11∂V13∂net2=∂V12∂net23=h11
同理可以计算
n
e
t
2
net_2
net2关于V中其他单元的导数。则总误差J对于V的各个元素的偏导数为
∂
J
∂
V
=
δ
n
e
t
2
∗
[
h
1
∣
h
1
∣
h
1
]
\frac{∂J}{∂V}=δ_{net_2}*[h1|h1|h1]
∂V∂J=δnet2∗[h1∣h1∣h1]
3.1.3 关于W的梯度
根据输入:
n
e
t
1
=
W
T
X
+
B
1
net_1 = W^TX+B1
net1=WTX+B1
有:
∂
n
e
t
1
∂
W
11
=
∂
n
e
t
11
∂
W
11
=
X
1
∂
n
e
t
1
∂
W
12
=
∂
n
e
t
12
∂
W
12
=
X
1
∂
n
e
t
1
∂
W
13
=
∂
n
e
t
13
∂
W
13
=
X
1
\frac{∂net_1}{∂W_{11}}=\frac{∂net_{11}}{∂W_{11}}=X_{1}\\ \frac{}{}\\ \frac{∂net_1}{∂W_{12}}=\frac{∂net_{12}}{∂W_{12}}=X_{1}\\ \frac{}{}\\ \frac{∂net_1}{∂W_{13}}=\frac{∂net_{13}}{∂W_{13}}=X_{1}\\
∂W11∂net1=∂W11∂net11=X1∂W12∂net1=∂W12∂net12=X1∂W13∂net1=∂W13∂net13=X1
同理,可以计算其他W元素的偏导数,则总的误差对于整个W的偏导数为:
∂
J
∂
W
=
δ
n
e
t
1
T
∗
[
X
∣
X
∣
X
]
T
\frac{∂J}{∂W}=δ_{net_1}^T*[X|X|X]^T
∂W∂J=δnet1T∗[X∣X∣X]T
3.1.4 关于B1,B2,B3的梯度
根据输入
Y
=
U
T
h
2
+
B
3
Y=U^Th2+B3
Y=UTh2+B3
可以确定:
∂
y
1
∂
B
31
=
1
∂
y
2
∂
B
32
=
1
\begin{matrix} \frac{∂y_1}{∂B_{31}}=1\\ \frac{}{} \\ \frac{∂y_2}{∂B_{32}}=1\\ \end{matrix}
∂B31∂y1=1∂B32∂y2=1
则有:
∂
J
B
3
=
δ
Y
\frac{∂J}{B_3}=δ_Y
B3∂J=δY
同理可以计算出关于B2,B1的梯度为
δ
n
e
t
2
,
δ
n
e
t
1
δ_{net_2},δ_{net_1}
δnet2,δnet1。
3.2 梯度更新
W
n
e
w
=
W
−
α
∂
J
∂
W
,
B
1
n
e
w
=
B
1
−
α
∂
J
∂
B
1
W_{new}=W-α\frac{∂J}{∂W},B1_{new}=B1-α\frac{∂J}{∂B1}
Wnew=W−α∂W∂J,B1new=B1−α∂B1∂J
V
n
e
w
=
V
−
α
∂
J
∂
V
,
B
2
n
e
w
=
B
2
−
α
∂
J
∂
B
2
V_{new}=V-α\frac{∂J}{∂V},B2_{new}=B2-α\frac{∂J}{∂B2}
Vnew=V−α∂V∂J,B2new=B2−α∂B2∂J
U
n
e
w
=
U
−
α
∂
J
∂
U
,
B
3
n
e
w
=
B
3
−
α
∂
J
∂
B
3
U_{new}=U-α\frac{∂J}{∂U},B3_{new}=B3-α\frac{∂J}{∂B3}
Unew=U−α∂U∂J,B3new=B3−α∂B3∂J
其中α是学习率。