用BP网络算法实现对含噪声0到9数字的识别

类别:VC语言 点击:0 评论:0 推荐:

http://210.77.192.38/bugzhao/_ALL_OTHERs/MyWork/Articles/BPnet/bpnet.pdf

我已经做成一个pdf文件了

完整的原文可以下载这个pdf阅读

摘要如下:

摘要:

     反向传播网络(Back propagation Network,简称BP网络)是对非线形可微分函数进行权值训练的多层前向网络。BP网络可以看作是对多层感知器网络的扩展,即信息的正向传播及误差数据的反向传递。BP网络主要可以应用于模式分类、函数逼近以及数据压缩等等。本文介绍了一种较为简单的三层BP网络模型,并将其应用于一个实例:数字0到9的识别。文中将给出BP网络的原理、设计该BP网络的过程以及具体的实现、方案的改进。同时附有大量的实验数据。程序采用VC++6.0编写,具备友好的GUI界面。

 

关键字:

       人工神经网络,BP网络,反向传播算法,数字识别

 

 

Abstract:

          Back propagation Network(short for BP net) is an classical ANN that convey information forwardly and just accept errors backwordly to ajust weight of the network so as to meet the LMS .BP net is based on the multiplayer perceptron network. It could be mainly used in the field of  pattern classification ,function approximation and data compression.This paper primarily introduce the priciple of a classical 3-layer BP net,and give an practical example ,that is: noised digital number(0 to 9) recognition.The designing process is well described and also ,I give an implication program of it ,developed using Visual C++ 6.0. Plenty of tables and graphs are also included in this article  when necessary.

 

Keywords:

   ANN, Back propagation network, BP, digital number recognition

 

1. 导论:  神经网络及BP网络概述

 

         在这里,我简要的对人工神经网络的大体发展脉络,尤其是BP网络的原理做一简单的概述。

        人工神经网络,即从生物学神经系统的信号传递而抽象发展而成的一门学科。在神经网络中,最基本的单元就是神经元。神经元由三部分组成:树突、细胞体和轴突。树突是树状的神经纤维接受网络,它将电信号传递给细胞体,细胞体对这些输入信号进行整合并进行阀值处理。轴突是单根长纤维,它把细胞体的输出信号导向其他的神经元。神经元的排列拓扑结构和突触的连接强度确立了神经网络的功能。

一些神经结构是与生俱来的,而其他部分则是在学习过程中形成的。在学习的过程中,可能会产生一些新的连接,也可能一些连接要消失,但主要的改变是加强或减弱突触的链接。

上图是将生物神经元模型抽象成一个信号传递、反馈的数学模型。

         神经元的输入是信号P,经过一个累加器累加后的信号送入一个激活函数f,从而得到这个神经元的输出a。这个神经元的输出a同时又可以作为下一个或多个神经元的输入,从而将神经信号成网络分散状的传递出去。一个神经元可以接受多个输入,所以把神经元表示成为矢量、矩阵形式更容易去处理分析实际问题。

这里,P表示一R维的输入向量,B为偏置向量,W为网络的权值矩阵,f为激活传输函数,a为网络的输出向量。

            以上是对一个单层神经网络的描述。一般就实际情况而言,多层网络用处要广的多。后面用到的BP网络也是多层的。

            在多层网络中,一般至少有3个层:一个输入层、一个输出层、一个或多个隐层。多层网络可以解决很多单层网络无法解决的问题,比如多层网络可以用来进行非线性分类,可以用来做精度极高的函数逼近,只要有足够多的层和足够多的神经元,这些都可以办到。

            一个多层网络的输入和输出层的神经元个数是由外部描述定义的。例如如果有4个外部变量作为输入,那网络就要有4个输入。关于隐层神经元的确定,将在BP网络的设计中详细讨论。

            文中曾多次提到过,感知器是神经网络的基础,也是BP网络的基础。所谓感知器(perceptron),也即给定一个或多个已知类别的输入,通过对网络的训练以实现所有输入数据的正确分类的数学模型。注意,感知器是单层网络。这里,训练的意思就是通过感知器的输出来反复调整网络的权值,以使其满足所有分类都正确的要求。不过一般来说,感知器的分类能力较差。

         下面来概述一下一种用途最广的神经网络:BP网络

          Frank Rosenblatt的感知器学习模型和Widrow的LMS算法是用来设计训练单层网络的。在实际应用中,单层网络远远不能满足需求,所以多层网络应运而生。但多层网络面临一个问题:应用LMS算法的时,我们如何来求用来确定调整权值系数的偏导数?

BP算法的提出很好的解决了这个问题。

            在BP算法模型中,首先是信息的正向传播。这一点和以前所提到的神经网络是一样的。BP算法的成功之处,就是它提供了一种快速计算各层误差的实现方法,以用来调整各层的权值和偏置,从而可以将LMS算法很好的应用于多层网络。

在上图所描述的网络中,算法的输入是一系列正确的、已知的样本和输出对:

            {P1,T1} , {P2, T2} ,{P3,T3}….

            网络输出误差为:

            F(x)=E( e)

            BP网络通过微积分中的链法则来计算偏导数。这里我给出训练BP网络的公式,详细的推导过程请见参考文献。

 

首先是信息的正向传播:

然后是反向计算误差并调整权值:

2. 问题描述与网络的设计

 

          下面就开始用BP网络的思想来设计实现一个真正的实际的神经网络。

            BP网络的一个重要的用途就是用于模式识别。

            我们的任务是要设计并训练出一个可行、高效的BP网络,以实现对0到9共10个加噪声后的数字和识别。

            这里,数字采用了8×8共64点阵的形式,使用美观的数码管字体。

首先,要选择一种编码方式。在这里可以采用行编码和列编码,但经过大量的实验表明,这两种编码方式的抗干扰性能不佳。我最终选择的还是点阵直接0-1编码的方式。比如,对于数字0,可以编码为:

 

                0   0   1   1   1   1   1   0

0   0   1   0   0   0   1   0

0   0   1   0   0   0   1   0

0   0   1   0   0   0   1   0

0   0   1   0   0   0   1   0

0   0   1   0   0   0   1   0

0   0   1   0   0   0   1   0

0   0   1   1   1   1   1   0

 

            这样,很容易确定该BP网络的输入为64维。

          当数字数据混入噪声时,可以看作是对0、1数据进行简单的随机反转。比如说,要加入7%的噪声,那就可以对4个0或者1进行反转。反转哪一个,这里是随机的。

如上图,经噪声干扰后的0编码为:

 

                                                    0   0   1   1   1   1   1   0

0   0   1   0   0   0   1   0

0   0   1   0   0   0   1   0

0   0   1   0   0   1   1   0

0   0   1   0   0   0   1   0

0   0   1   0   0   0   1   0

0   0   1   1   1   0   1   1

0   0   1   1   1   1   1   0

 

图中,加下划线的斜体部分就是噪声。

 

接下来来确定输出层的神经元个数。在输出层,我将0~9数字用8421码进行编码,这样10个数字就需要4位二进制的码。这样也就确定下来输出层有4个神经元。

下面,来确定最关键的隐层的神经元个数。一般来说,在做类似于函数逼近的课题时,隐层的神经元越多,则逼近就越精确。但对于当前的这个模式分类的题目,隐层神经元的数目必须要适当的选取,即不能过多,也不能太少。如果隐层的神经元过多,一来会大大的加大训练时间,二来,虽然神经元的增多可以更加精确的描述分类判别的空间的界限,但同时,也造成网络的容错能力下降。这对于我们当前的这个0~9数字识别是极为不利的。当然,神经元的数目过少的时候,又无法满足分类的要求。

经过反复的实验测定、对比,我认为隐层的神经元的数目为8到15为最佳。小于8个神经元的时候,网络输出误差就太大了;大于15个神经元的时候,识别率又过低。

由于这只是一个简单的10类区分问题,所以使用一个隐层足已。

最后,来确定隐层和输出层的激活函数。遵循一般的,我在隐层中使用了处处可微分的Log-sigmoid函数,

f1(n)=

 

在输出层使用了线性函数,这里,不妨简单的取:

f2(n)= n

 

至此,BP网络的大体雏形已经设计出来了。下面,我结合着编程,具体的说一下BP网络的实现部分,包括训练样本的设计、允许误差的设定和步长的设定,并给出改进识别率或训练时间的方案及实现。

 

 

 

3. BP网络的编程实现

 

这里,我所使用的编程开发环境为:

windows 2000 with sp4  + visual c++ 6.0 with sp5

面对琳琅满目的各种开发环境和仿真软件,我放弃了简单的matlab,也没有使用自己熟悉的C++Builder和Visual Basic, 最主要的原因就是,VC对内存的掌控很好。这对运算量极大的BP算法有着关键的作用。要知道,设计一个BP网络不难,难的是设计出一个高效、高速、稳定的BP网络,这就需要我们来对内存进行优化,对算法进行最大程度的挖掘。否则,设计出来的BP算法将是不健壮或者说不够稳定、实用的。一定要注意在设计程序时要尽可能多的释放掉不再使用的内存。

为了让提高编程的效率和便于查错,我使用了BP算法的矩阵形式,也就是公式1、2、3。 这样一来,对于正向信息的传播和反向误差的传播,很容易表示成矩阵(包括向量)相加减、相乘除的形式。

在运行BP网络进行识别之前,首先我们要有足够的数据来训练这个网络。这里,我们仅仅用10组“纯净”未含噪声的数据0、1…9是绝对不够的。如果只用10组输入,虽然可以很快的收敛也可以达到很小的误差,但对于我们的识别对象-加入噪声的数据,就几乎完全失去了分辨能力。

所以,这里,经过我多次比较、测试,我选定了60组数据作为训练样本。这60组数据包括:

①    其中有10组是纯净的0~9数字

②    外的50组,是对这10组纯净数据进行随机加噪产生的,分别随机的加入5%~15%的噪声。这样以来训练样本就有了足够的健壮性和容错能力。

 

下面来确定隐层的神经元个数、允许误差及学习步长。

     如前所述,隐层的神经元数目的选择,是BP算法设计的关键。隐层的神经元数目过多,那即将造成训练时间的加长,也将降低抗噪声能力。编程证明,当隐层神经元数目超过25的时候,网络的训练时间将无法忍受,同时抗噪声能力大大降低;当神经元数目低于7的时候,系统误差无法收敛到满意的值,又造成识别率过低。经过多次的比较分析,我最终选定了隐层为9个神经元。事实证明(从后面的训练时间和识别率可以看出),这是个不错的选择。

允许误差是系统进行训练的目标。当系统的输出误差小于这个允许的误差的时候即停止训练。误差选择过大,将造成系统识别率过低;误差选择太小,会大大延长训练时间,是一种浪费。这里,也要通过多次的对比分析来得到最佳的允许误差。我最终确定下来的允许误差在0.02~0.2之间。

学习步长的选择也是BP网络设计的关键所在。学习步长过长,则有可能造成算法无法收敛;步长过短,一来加大了训练时间,二来则很容易陷入所谓的局部极小值。这里我初步把学习步长设定在0.02~0.3之间。

最后,我们来看看初始权值和偏置的设定。

设计初始权值和偏置有两点注意,一,W和B不要太大,否则很可能处于误差平面的平坦之处,导致网络训练停滞; 二,各项权值不能设为一样的值。

我的实现方法是:利用(-1,1)之间的随机数来设定权值和偏置。

     

至此,网络的设计已经完成。下面我来介绍一下我开发的这个程序,简要说明一下。

 

下图就是这个程序的主界面:

菜单界面:

 

训练误差曲线:

 

识别结果:

 

注:目前程序增加了输出文件记录的功能,如下所示:

本文地址:http://com.8s8s.com/it/it1095.htm