摘要:
关于BP算法(误差反向传播)网上的学习、参考资料已经有很多了。每篇文章都差不多,都是在阐述BP的数学原理或者实践。本篇文章其实也和网上大部分文章一样,但从一个初学者的角度来分享学习这个算法的过程的一些体会。
预先定义:
网上许多资料都是以单层的神经网络为例推导BP算法,本文用一个两个隐藏层的神经网络为例推导BP算法。(其实结果是一样的)。网络结构如下图:
接着,我们定义一下一些参数。(请不要跳过这个环节)
假设输入层的每一个输入表示为 xm x m , m=1,2...Ninput m = 1 , 2... N i n p u t
假设输入层第 m m 个输入与第一个隐藏层的第
个神经元的连接权重为 uim u i m 。
那么,第一层隐藏层的第 i i 神经元输入为
, neti=∑Ninputm=1uimxm n e t i = ∑ m = 1 N i n p u t u i m x m 。
因此,经过激活函数 f(x) f ( x ) 后,第 i i 个神经元的输出为
y(1)i=f(neti) y i ( 1 ) = f ( n e t i )
同理可以得到第二个隐藏层:
第二层隐藏层的第j个神经元输入为 netj n e t j , netj=∑N(1)m=1vjmy(1)m n e t j = ∑ m = 1 N ( 1 ) v j m y m ( 1 ) ,其中 N(1) N ( 1 ) 是第二层的神经元个数。 vjm v j m 是权重。经过激活函数后其值为 y(2)j y j ( 2 ) , y(2)j=f(netj) y j ( 2 ) = f ( n e t j )
最后,可以得到输出层:
netk=∑N(2)m=1wkmy(2)m n e t k = ∑ m = 1 N ( 2 ) w k m y m ( 2 ) ,经过激活函数后其值为 ok o k , ok=f(netk) o k = f ( n e t k ) 。
另外,假设目前的损失函数为 E=12∑N(o)m=1(ok−tk)2 E = 1 2 ∑ m = 1 N ( o ) ( o k − t k ) 2 。(这里的0.5系数是为了方便计算)
这里需要提一下的是,很多文章都是把损失函数定义成均方误差,这个主要是为是好解释BP算法。在后面推导完后就可以发现,其实任意的可导损失函数都可以,本文也会简单的说明。
另外,一些读者可能发现上面在求 net n e t 的值时没有写明计算偏置项,其实这不影响我们的公式推导,后面也会做说明(当然,你也可以把公式理解成已经把偏置项包含进去了,此时输入总是1)
推导
BP算法解决的是什么问题?解决的是如何更新网络中的权重值。
一般来说,对于任意一个权重我们都有:
wafter:=wbefore+Δw w a f t e r : = w b e f o r e + Δ w ,第二项其实就是我们熟知的学习率和梯度的乘积。
在这个多层的网络中,需要学习的参数有 wkm w k m , vjm v j m , uim u i m 。
其于目标函数 E E 的梯度值分别为:
, ∂E∂vjm ∂ E ∂ v j m , ∂E∂uim ∂ E ∂ u i m 。只要能够求出上面这3个式子,我们就完成了更新权重的任务。所以下面,一个一个求解。
1.先求 ∂E∂wkm ∂ E ∂ w k m :
由链式法则,我们可以得到下式:
∂E∂wkm=∂E∂netk∗∂netk∂wkm ∂ E ∂ w k m = ∂ E ∂ n e t k ∗ ∂ n e t k ∂ w k m 。
(这里简单解释一下为什么会想到这一步。回头看我们的一些参数定义,我们可以看到, wkm w k m 和 netk n e t k 是最直接的函数关系,所以我们选择引入中间变量 netk n e t k ,另一方面,我们如果把神经元输入作为中间变量引入到链式法则中后面推导得到式子会很整齐,很有规律性)
接着,我们定义一个误差信号:
所谓误差信号即: δ(o)k=∂E∂netk δ k ( o ) = ∂ E ∂ n e t k ,那么上式就可以写成:
∂E∂wkm=∂E∂netk∗∂netk∂wkm=δ(o)k∗∂netk∂wkm ∂ E ∂ w k m = ∂ E ∂ n e t k ∗ ∂ n e t k ∂ w k m = δ k ( o ) ∗ ∂ n e t k ∂ w k m 。
对于 ∂netk∂wkm