讲解BP人工神经网络。

上一次我们讲了M-P模型,它实际上就是对单个神经元的一种建模,还不足以模拟人脑神经系统的功能。由这些人工神经元构建出来的网络,才能够具有学习、联想、记忆和模式识别的能力。BP网络就是一种简单的人工神经网络。我们的第二话就从BP神经网络开始漫谈吧。

BP的来源

“时势造英雄”,一个伟大的人物的登场总是建立在历史的需求之下,所以我们剖析一个人,得先看看他的出身时代。同样的道理,在讲BP网络的特性和用途之前,我们需要先了解一下它的来源和诞生原因,以便理解它的重要性。

1.1 最简单的神经网络结构——感知器

在1958年,美国心理学家Frank Rosenblatt提出一种具有单层计算单元的神经网络,称为感知器(Perceptron)。它其实就是基于M-P模型的结构。我们可以看看它的拓扑结构图。

这个结构非常简单,如果你还记得前面所讲的M-P神经元的结构的话,这个图其实就是输入输出两层神经元之间的简单连接(如果忘了可以看看第一话的模型示意图)。

由第一话的(2)中我们知道输入层各节点的输入加权和

\[net'_j = \sum_{i=1}^n\omega_{ij}x_i\]

我们一般采用符号函数来当作单层感知器的传递函数,即输出

\[o_j=sgn(net'_j-T_{j})=sgn(\sum_{i=0}^n\omega_{ij}x_i)=sgn(W_j^TX)\]

公式(2)可以进一步表达为:

\[o_j=\left \{ \begin{aligned} 1 & , &W_{j}^{T}X>0 \\ -1 & ,& W_{j}^{T}X<0 \end{aligned} \right.\]

1.2 风中之烛——单层感知器的局限性

虽然单层感知器简单而优雅,但它显然不够聪明——它仅对线性问题具有分类能力。什么是线性问题呢?简单来讲,就是用一条直线可分的图形。比如,逻辑“与”和逻辑“或”就是线性问题,我们可以用一条直线来分隔0和1。

1)逻辑“与”的真值表和二维样本图如图2:

2)逻辑“或”的真值表如图3:

为什么感知器就可以解决线性问题呢?这是由它的传递函数决定的。这里以两个输入分量 \(x_1\) 和 \(x_2\) 组成的二维空间为例,此时节点 \(j\) 的输出为 \[ o_j=\left \{ \begin{aligned} 1 &, & ~~~\omega_{1j}x_1+\omega_{2j}x_2-T_j>0 \\ -1 & , & ~~~\omega_{1j}x_1+\omega _{2j}x_2-T_j<0 \end{aligned} \right. \]

所以,方程 \[\omega_{1j}x_1+\omega_{2j}x_2-T_j=0\]

确定的直线就是二维输入样本空间上的一条分界线。对于三维及更高维数的推导过程可以参考其他的Tutorials。

如果要让它来处理非线性的问题,单层感知器网就无能为力了。例如下面的“异或”,就无法用一条直线来分割开来,因此单层感知器网就没办法实现“异或”的功能。

仅对线性可分问题具有分类能力,这就是单层感知器的局限所在。显然它能够解决的实际问题是很有限的。也正因为这样,单层感知器在解决实际问题时很少被采用。

1.3 心有余而力不足——多层感知器的瓶颈

既然一条直线无法解决分类问题,当然就会有人想到用弯曲的折线来进行样本分类。我们常常听到一句批评人笨的话“你这人脑袋就是不会转弯!”大意就是如此,脑袋会转弯的人才善于解决问题。所以,人们请来了单层感知器他哥——多层感知器来帮忙。所谓多层感知器,就是在输入层和输出层之间加入隐层,,以形成能够将样本正确分类的凸域。多层感知器的拓扑结构如图5所示。

我们可以比较一下单层感知器和多层感知器的分类能力:

由上图可以看出,随着隐层层数的增多,凸域将可以形成任意的形状,因此可以解决任何复杂的分类问题。实际上,Kolmogorov理论指出:双隐层感知器就足以解决任何复杂的分类问题

多层感知器确实是非常理想的分类器,但问题也随之而来:隐层的权值怎么训练?对于各隐层的节点来说,它们并不存在期望输出,所以也无法通过感知器的学习规则来训练多层感知器。因此,多层感知器心有余而力不足,虽然武功高强,但却无力可施。

1.4 山重水复疑无路——ANN的低潮期

1966年,Minisky和Papert在他们的《感知器》一书中提出了上述的感知器的研究瓶颈,指出理论上还不能证明将感知器模型扩展到多层网络是有意义的。这在人工神经网络的历史上书写了极其灰暗的一章。对ANN的研究,始于1890年开始于美国著名心理学家W.James对于人脑结构与功能的研究,半个世纪后W.S.McCulloch和W.A.Pitts提出了M-P模型,之后的1958年Frank Rosenblatt在这个基础上又提出了感知器,此时对ANN的研究正处在升温阶段,《感知器》这本书的出现就刚好为这刚刚燃起的人工神经网络之火泼了一大盆冷水。一时间人们仿佛感觉对以感知器为基础的ANN的研究突然间走到尽头,看不到出路了。于是,几乎所有为ANN提供的研究基金都枯竭了,很多领域的专家纷纷放弃了这方面课题的研究。

1.5 柳暗花明又一村——ANN研究的复苏和BP神经网络的诞生

所以说真理的果实总是垂青于能够忍受寂寞的科学家。尽管ANN的研究陷入了前所未有的低谷, 但仍有为数不多的学者忍受住寂寞,坚持致力于ANN的研究。在长达10年的低潮时期之间,相 继有一些开创性的研究成果被提出来,但还不足以激起人们对于ANN研究的热情。一直到上世 纪80年代,两个璀璨的成果诞生了:1982年美国加州理工学院的物理学家John J.Hopfield博 士的Hopfield网络和David E.Rumelhart以及James L.McCelland研究小组发表的《并行分布 式处理》。这两个成果重新激起了人们对ANN的研究兴趣,使人们对模仿脑信息处理的智能计 算机的研究重新充满了希望。

前者暂不讨论,后者对具有非线性连续变换函数的多层感知器的误差反向传播(Error Back Propagation)算法进行了详尽的分析,实现了 Minsky 关于多层网络的设想。Error Back Propagation算法的简称就是BP算法,以BP算法实现的多层感知器网络就是BP网络。

所以,BP网络本质上并不是一个新的网络,而是使用BP学习算法的多层感知器网络。

BP算法的基本思想

前面我们说到,多层感知器在如何获取隐层的权值的问题上遇到了瓶颈。既然我们无法直接得到隐层的权值,能否先通过输出层得到输出结果和期望输出的误差来间接调整隐层的权值呢?BP算法就是采用这样的思想设计出来的算法,它的基本思想是,学习过程由信号的正向传播误差的反向传播两个过程组成。

  • 正向传播时,输入样本从输入层传入,经各隐层逐层处理后,传向输出层。若输出层的实际输出与期望的输出(教师信号)不符,则转入误差的反向传播阶段。
  • 反向传播时,将输出以某种形式通过隐层向输入层逐层反传,并将误差分摊给各层的所有单元,从而获得各层单元的误差信号,此误差信号即作为修正各单元权值的依据。

图8就是BP算法的信号流向图。

BP网络特性分析——BP三要素

我们分析一个ANN时,通常都是从它的三要素入手,即1)网络拓扑结构;2)传递函数;3)学习算法。如图9所示。

每一个要素的特性加起来就决定了这个ANN的功能特性。所以,我们也从这三要素入手对BP网络的研究。

3.1 BP网络的拓扑结构

前面已经说了,BP网络实际上就是多层感知器,因此它的拓扑结构和多层感知器的拓扑结构(图5)相同。由于单隐层(三层)感知器已经能够解决简单的非线性问题,因此应用最为普遍。三层感知器的拓扑结构如图10所示。

3.2 BP网络的传递函数

BP网络采用的传递函数是非线性变换函数——Sigmoid函数(又称S函数)。其特点是函数本身及其导数都是连续的,因而在处理上十分方便。为什么要选择这个函数,等下在介绍BP网络的学习算法的时候会进行进一步的介绍。S函数有单极性S型函数和双极性S型函数两种,单极性S型函数定义如下:\[f(x)=\frac {1}{1+e^{-x}}\]

其函数曲线如图11所示。

双极性S型函数定义如下: \[f(x)=\frac {1-e^{-x}}{1+e^{-x}}\]

其函数曲线如图12所示。

3.3 BP网络的学习算法

BP网络的学习算法就是BP算法,又叫 \(\delta\) 算法(在ANN的学习过程中我们会发现不少具有多个名称的术语), 以三层感知器为例,当网络输出与期望输出不等时,存在输出误差 \(E\) ,定义如下

\[ \begin{aligned} E &=\frac{1}{2}(d-O)^2 \\ &=\frac{1}{2}\sum_{\kappa=1}^\ell(d_k-o_k)^2 \end{aligned} \]

将以上误差定义式展开至隐层,有 \[\begin{aligned}E & =\frac{1}{2}\sum_{\kappa=1}^\ell[d_{\kappa}-f(net_\kappa)]^2 \\ &=\frac{1}{2}\sum_{\kappa=1}^\ell[d_{\kappa}-f(\sum_{j=0}^m\omega_{j\kappa}y_j)]^2 \end{aligned}\]

进一步展开至输入层,有 \[ \begin{aligned} E & =\frac{1}{2}\sum_{\kappa=1}^\ell\{d_{\kappa}-f[\sum_{j=0}^m\omega_{j\kappa}f(net_j)]\}^2 \\ &=\frac{1}{2}\sum_{\kappa=1}^\ell\{d_{\kappa}-f[\sum_{j=0}^m\omega_{j\kappa}f(\sum_{j=0}^n\upsilon_{ij}\chi_i)]\}^2 \end{aligned} \]

由上式可以看出,网络输入误差是各层权值\(\omega_{j\kappa}\)、\(\upsilon_{ij}\)的函数,因此调整权值可改变误差 \(E\)。 显然,调整权值的原则是使误差不断减小,因此应使权值与误差的梯度下降成正比,即 \[ \begin{aligned}\Delta \omega_{j\kappa}=-\eta \frac{\partial E}{\partial \omega_{j\kappa}} & j=0,1,2,\ldots,m; & \kappa=1,2,\ldots,\ell \end{aligned} \]

\[\begin{aligned}\Delta \upsilon_{ij}=-\eta \frac{\partial E}{\partial \upsilon_{ij}} & i=0,1,2,\ldots,n; & j=1,2,\ldots,m \end{aligned}\]

对于一般多层感知器,设共有 \(h\) 个隐层,按前向顺序各隐层节点数分别记为 \(m_1,m_2,\ldots,m_h\),各隐层输出分别记为 \(y^1,y^2,\ldots,y^h\),各层权值矩阵分别记为 \(W^1,W^2,\ldots,W^h,W^{h+1}\),则各层权值调整公式为

输出层

\[ \begin{aligned} \scriptstyle\Delta \omega_{j\kappa}^{h+1}=\eta \delta_{\kappa}^{h+1}y_j^h=\eta(d_\kappa-o_\kappa)o_\kappa(1-o_\kappa)y_j^\kappa & \scriptstyle j=0,1,2,\ldots,m_h; & \scriptstyle \kappa=1,2,\ldots,\ell \end{aligned} \]

第 \(h\) 隐层

\[\begin{aligned}\scriptstyle\Delta \omega_{ij}^{h}=\eta \delta_j^hy_i^h-1=\eta(\sum _{\kappa=1}^l \delta_\kappa^o\omega_{j\kappa}^{h+1}y_j^\kappa(1-y_j^kappa)y_i^h-1 & \scriptstyle i=0,1,2,\ldots,m_(h-1); & \scriptstyle j=1,2,\ldots,m_h \end{aligned}\]

按以上规律逐层类推,则第一隐层权值调整公式

\[\begin{aligned} \scriptstyle \Delta \omega_{pq}^1=\eta \delta_q^1\chi_p=\eta(\sum_{r=1}^{m_{2}}\delta_r^2\omega_{qr}^2)y_q^1(1-y_q^1)\chi_p & \scriptstyle p=0,1,2,\ldots,n; & \scriptstyle j=1,2,\ldots,m_1 \end{aligned}\]

容易看出,BP学习算法中,各层权值调整公式形式上都是一样的,均由3个因素决定,即:

  • 学习率 \(\eta\)
  • 本层输出的误差信号 \(\delta\)
  • 本层输入信号 \(Y\)(或\(X\))

其中输入层误差信号与网络的期望输出与实际输出之差有关,直接反应了输出误差,而各隐层的误差信号与前面各层的误差信号有关,是从输出层开始逐层反传过来的

可以看出BP算法属于\(\delta\)学习规则类,这类算法常被称为误差的梯度下降算法。\(\delta\)学习规则可以看成是Widrow-Hoff(LMS)学习规则的一般化(generalize)情况。LMS学习规则与神经元采用的变换函数无关,因而不需要对变换函数求导,\(\delta\)学习规则则没有这个性质,要求变换函数可导。这就是为什么我们前面采用Sigmoid函数的原因

综上所述,BP三要素如图13所示。

BP网实例

由于BP网络具有出色的非线性映射能力、泛化能力和容错能力,因此BP网络成了至今为止应用最广泛的人工神经网络。图14是Matlab下用BP网络做线性拟合的结果,效果很好。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
% BP网络函数逼近实例

% 1.首先定义正弦函数,采样率为20Hz,频率为1Hz

k = 1; % 设定正弦信号频率
p = [0:0.05:4];
t = cos(k*pi*p) + 3*sin(pi*p);
plot(p, t, '-'), xlabel('时间'); ylabel('输入信号');

% 2.生成BP网络。用newff函数生成前向型BP网络,设定隐层中神经元数目为10
% 分别选择隐层的传递函数为 tansig,输出层的传递函数为 purelin,
% 学习算法为trainlm。

net =
newff(minmax(p),[10,10,1],{'tansig','tansig','purelin'},'trainlm');

% 3.对生成的网络进行仿真并做图显示。
y1 = sim(net,p); plot(p, t, '-', p, y1, '--')

% 4.训练。对网络进行训练,设定训练误差目标为 1e-5,最大迭代次数为300
% 学习速率为0.05
net.trainParam.lr=0.05;
net.trainParam.epochs=1000;
net.trainParam.goal=1e-5;
[net,tr]=train(net,p,t);

%5.再次对生成的网络进行仿真并做图显示。
y2 = sim(net,p);
plot(p, t, '-', p, y2, '--')

Comments