在这里我就不介绍神经网络的起源发展和基本概念了,让我们专注于BP神经网络的算法。为了方便说明,我们做出如下如下神经网路用于解决分类问题,其中输入层有3个单元(含1个偏置项),第1个隐藏层有3个单元(含1个偏置项),第2个隐藏层有3个单元(含1个偏置项),输出层有2个单元。
符号 |
意义 |
x
|
样本输入向量 |
xi
|
样本输入向量第
i
个分量 |
y
|
样本输出向量 |
z(k)j
|
第
k
层第
j
个单元的值(用激励函数之前) |
a(k)j
|
第
k
层第
j
个单元的值(用激励函数之后) |
θ(k)i,j
|
第
k
层的第
j
个单元与第
k+1
层的第
i
个单元之间的权值,其中
θ(k)i0
的值恒为1 |
Θ(k)
|
由
θ(k)ij
组成的矩阵 |
δ(k)j
|
第
k
层第
j
个单元的误差 |
一、前向传播
方便起见,针对一个训练样本用于训练网络,首先进行前向传播。第一层(输入层)如下,其中矩阵中的1为偏置项。
a(1)=[1x1x2]T(1)
第二层(隐藏层1)经过权值的作用得到如下。
z(2)=Θ(1)a(1)(2)
其中
Θ(1)
的维度是
2×3
,
a(1)
的维度是
3×1
,因此
z(2)
的维度是
2×1
,不包括第2层的偏置项。具体来讲,
z(2)2=θ(1)20×a(1)0+θ(1)21×a(1)1+θ(1)22×a(1)2(2.2)
接下来我们需要用一个激励函数使得神经网络的计算非线性化,在这里我们用sigmoid函数作用如下。
a(2)=g(z(2))(3)
具体来讲,
a(2)1=11+e−z(2)1(3.1)
a(2)2=11+e−z(2)2(3.2)
为了与输入层的
a(1)
保持一致,在这里我们对
a(2)
增加一个偏置项,即
a(2)=[1a(2)1a(2)2]T(4)
第二层的计算完毕,针对第三层的计算(隐藏层2),我们把第二层视为输入层,同理可得如下。
z(3)=Θ(2)a(2)(5)
其中
Θ(2)
的维度是
2×3
,
a(2)
的维度是
3×1
,因此
z(3)
的维度是
2×1
,不包括第3层的偏置项。接下来用sigmoid函数作用
a(3)=g(z(3))(6)
对
a(3)
增加一个偏置项,即
a(3)=[1a(3)1a(3)2]T(7)
第三层的计算完毕,针对第四层的计算(输出层),我们把第三层视为输入层,同理可得如下。
z(4)=Θ(3)a(3)(8)
其中
Θ(3)
的维度是
2×3
,
a(3)
的维度是
3×1
,因此
z(4)
的维度是
2×1
。接下来用sigmoid函数作用
a(4)=g(z(4))(9)
由于第四层是输出层因此不再增加一个偏置项。至此神经网络的前向传播已经结束。
二、反向传播
下面我们要进行反向传播,并用梯度下降法更新
θ
的权值。对于分类问题,我们知道代价函数为
J(θ)=−1m∑i=1m[y(i)log(hθ(x(i)))+(1−y(i))log(1−hθ(x(i)))]+λ2m∑j=1nθ2j(10)
由于神经网络的输出层为向量,不是一个像逻辑回归是一个数,因此我们重新定义输出量
y
为向量,输出量的维度与所分类别数一致,每一个维度代表一种类别。例如我们要分四类,那么对应神经网络的理想输出如下,且当训练集中
y=3
时,经过调整变为
y3
,为方便说明,我们令
y=y3
。
y1=⎡⎣⎢⎢⎢1000⎤⎦⎥⎥⎥,y2=⎡⎣⎢⎢⎢0100⎤⎦⎥⎥⎥,y3=⎡⎣⎢⎢⎢0010⎤⎦⎥⎥⎥,y4=⎡⎣⎢⎢⎢0001⎤⎦⎥⎥⎥
这样,神经网络的代价函数就更改为
J(θ)=−1m[∑i=1m∑k=1Ky(i)klog(hθ(x(i))k)+(1−y(i)k)log(1−hθ(x(i))k)]+λ2m∑l=1L−1∑i=1sl∑j=1sl+1(θ(l)j,i)2(11)
其中L为神经网络的总层数,
sl
为第
l
层的单元数(不包括偏置项),K为输出层的单元数,
hθ(x)
与
a(l)
一致。
由于梯度下降法更新
θ
的权值需要计算
∂∂θ(l)i,jJ(θ)
,而对于这种形式的神经网络直接计算偏导数有些困难,因此我们用间接的方式求得偏导数。数学证明比较麻烦,在这里只提供算法。
既然是反向传播,当然就应该从输出层向输入层进行计算。首先我们要计算每一层的“误差”
δ(k)j
。对于输出层,“误差”为神经网络的输出结果与给定输出结果之差,即
δ(4)=a(4)−y(12)
上式为向量形式,其中
δ(4)
为
2×1
向量。
接下来求第三层的“误差”,即
δ(3)=(Θ(3))Tδ(4).∗g′(z(3))(13)
其中
δ(3)
为
3×1
向量,
g(⋅)
为sigmoid函数,
Θ(3)
为
2×3
向量,
z(3)
为
3×1
向量,
A.∗B
指的是
A
、
B
向量对应的数相乘,例如
[123].∗[456]=[41018]
经过简单的数学推导我们可以得知
g′(z(3))=a(3).∗(1−a(3))(14)
因此
δ(3)=(Θ(3))Tδ(4).∗a(3).∗(1−a(3))(15)
由于每一层的第一个单元为偏置项,因此我们默认它的值恒为1,不进行修改。所以对于
δ(k)
我们去掉第一项偏置项,得到
2×1
向量。
接下来求第二层的“误差”,即
δ(2)=(Θ(2))Tδ(3).∗a(2).∗(1−a(2))(16)
由于第一层为输入层,我们不想修改它的值,因此我们只做到第二层就结束。
当我们求完输入层以外的所有层的“误差”
δ
后,我们只需一步就可以求得偏导数,即
∂∂θ(k)i,jJ(θ)=a(k)jδ(k+1)i(17)
向量表示如下,可知
Δ(k)
均为
2×3
矩阵,与
Θ(k)
维数相符。
Δ(k)=δ(k+1)(a(k))T(18)
以上只举了一个例子,当训练集为
m
时,由代价函数的定义可知
Δ(k)=∑i=1mΔ(k)i(19)
因此偏导数如下,不要忘记考虑正则项
⎧⎩⎨⎪⎪⎪⎪∂∂Θ(k)ijJ(Θ)=1m(Δ(k)i,j+λΘ(k)i,j)∂∂Θ(k)ijJ(Θ)=1mΔ(k)i,jif j≠0if j=0(20)
让我们来整体看一下这个算法
有了代价函数和偏导数,接下来就可以利用熟知的梯度下降法或者其他算法来求得最优值。
注:
- 虽然这样的神经网络是非凸型的,即有局部最优值,但是实践证明梯度下降法也可以得到比较满意的解,虽然不是最优解。
- 初始化
Θ
时,我们应该随机化初始化,若每一层的
Θi,j
一样时,神经网络将每一层的单元数将退化成一个单元。
- 用梯度下降法时有时虽然可以看到每一轮的代价函数所得值逐步降低,但是这不代表梯度没有求错,因此可以用手工计算梯度来校验,但是代价比较高,当发现梯度算对后应结束手工计算梯度这一步骤。
∂z∂x=f(x+ϵ,y)−f(x−ϵ,y)2ϵ