- 外文名
- Back Propagation Neural Network
- 提出时间
- 1986年
- 中文名
- BP神经网络
-
详解BP神经网络
2018-05-06 11:30:41BP神经网络学习算法可以说是目前最成功的神经网络学习算法。显示任务中使用神经网络时,大多数是使用BP算法进行训练. 在我看来BP神经网络就是一个”万能的模型+误差修正函数“,每次根据训练得到的结果与...#BackPropagation Neuron NetWok
BP神经网络学习算法可以说是目前最成功的神经网络学习算法。显示任务中使用神经网络时,大多数是使用BP算法进行训练.
在我看来BP神经网络就是一个”万能的模型+误差修正函数“,每次根据训练得到的结果与预想结果进行误差分析,进而修改权值和阈值,一步一步得到能输出和预想结果一致的模型。举一个例子:比如某厂商生产一种产品,投放到市场之后得到了消费者的反馈,根据消费者的反馈,厂商对产品进一步升级,优化,从而生产出让消费者更满意的产品。这就是BP神经网络的核心。
下面就让我们来看看BP算法到底是什么东西。BP网络由输入层、隐藏层、输出层组成。给定训练集***D***={(x1,y1),(x2,y2…(xn,yn)},其中xnϵRd,ynϵRl,表示输入示例由d个属性组成,输出l维实值变量。现在,我们看看如何求得输出值,以及怎么由输出值调整权值和阈值。
神经元是以生物研究及大脑的响应机制而建立的拓扑结构网络,模拟神经冲突的过程,多个树突的末端接受外部信号,并传输给神经元处理融合,最后通过轴突将神经传给其它神经元或者效应器。神经元的拓扑结构如图:
对于第i个神经元,X1、X2、…、Xj为神经元的输入,输入常为对系统模型关键影响的自变量,W1、W2、…、Wj为连接权值调节各个输入量的占重比。将信号结合输入到神经元有多种方式,选取最便捷的线性加权求和可得neti神经元净输入:
i表示该神经元的阈值,根据生物学中的知识,只有当神经元接收到的信息达到阈值是才会被激活。因此,我们将和进行比较,然后通过激活函数处理以产生神经元的输出。
激活函数:激活函数这里我们不多重述。如果输出值有一定的范围约束,比如用来分类,一般我们用的最多的是Sigmod函数,它可以把输入从负无穷大到正无穷大的信号变换成0到1之间输出。如果没有约束的话,我们可以使用线性激活函数(即权值相乘之和)。这样我们得到的输出为:
我们可以将公式化简一下,设第一个输入永远值为,权值为-1,则我们可以得到公式:
其中w0=-1,x0=j,其中f为选择的激活函数。
已经知道在BP神经网络模型中,我们有三层结构,输入层、隐藏层、输出层,因此输入层到隐藏层的权值,设为,隐藏层第h个神经元的阈值我们设为。隐藏层到输出层的权值,设为,输出层第j个神经元的阈值我们用表示。在下面这张图里,有d输入神经元,q个隐藏神经元,隐藏有q个隐藏神经元阈值,个输出神经元,因此有个输出神经元阈值。
其中中的。隐藏层和输出层的激活函数,在这里我们暂时全部用函数。
在某个训练示例中,假设神经网络的训练输出为,输出为维向量,其中
那么这次预测结果的误差我们可以用最小二乘法表示:
而我们现在要做的就是根据这个误差去调整个参数的值,一步一步缩小。那么从现在开始,我们就要进入数学的世界了。这里我们使用最常用的算法:梯度下降法来更新参数。函数永远是沿着梯度的方向变化最快,那么我们对每一个需要调整的参数求偏导数,如果偏导数>0,则要按照偏导数相反的方向变化;如果偏导数<0,则按照此方向变化即可。于是我们使用-1*偏导数则可以得到参数需要变化的值。同时我们设定一个学习速率,这个学习速率不能太快,也不能太慢。太快可能会导致越过最优解;太慢可能会降低算法的效率。(具体设多少就属于玄学调参的领域了)。因此我们可以得到一个参数调整公式:
首先我们看看隐藏层到输出层的权值调整值:
好,我们从上到下缕一缕这个偏导该怎么求,我们把每一个公式都罗列出来:
##### 1.输入层到隐藏层:
##### 2.经过隐藏层的激活函数:
##### 3.隐藏层到输出层:
##### 用矩阵表示
##### 4.经过输出层的激活函数:
##### 5.误差:
综上我们可以得知先影响,再影响,最后影响,(一个权值只会影响一个)所以我们可得:
其中,前面提到过,是第h个隐藏神经元的输出。
而我们选择的激活函数是函数,该函数具有一个很好的性质
所以我们有:
综合我们可得:
#### 同理:
我们再看看的值怎么求,还是由推导,一个权值会影响所有的
其中
#### 至此,我们所有得公式都推导完毕了,剩下做的就是设定一个迭代终止条件,可以是误差小于一定值时终止递归,也可以是设定迭代次数。这样一个BP神经网络模型就算是设计结束。
java实现代码和实验数据在我的github上面 -
BP神经网络
2018-04-07 19:29:51BP神经网络的python实现BP神经网络的python实现BP神经网络的python实现BP神经网络的python实现BP神经网络的python实现BP神经网络的python实现BP神经网络的python实现BP神经网络的python实现BP神经网络的python实现BP... -
神经网络学习 之 BP神经网络
2015-11-30 21:17:56上一次我们讲了M-P模型,...BP网络就是一种简单的人工神经网络。 本文具体来介绍一下一种非常常见的神经网络模型——反向传播(Back Propagation)神经网络。概述BP(Back Propagation)神经网络是1986年由Rumelhart和Mc上一次我们讲了M-P模型,它实际上就是对单个神经元的一种建模,还不足以模拟人脑神经系统的功能。由这些人工神经元构建出来的网络,才能够具有学习、联想、记忆和模式识别的能力。BP网络就是一种简单的人工神经网络。
本文具体来介绍一下一种非常常见的神经网络模型——反向传播(Back Propagation)神经网络。概述
BP(Back Propagation)神经网络是1986年由Rumelhart和McCelland为首的科研小组提出,参见他们发表在Nature上的论文 Learning representations by back-propagating errors 。
BP神经网络是一种按误差逆传播算法训练的多层前馈网络,是目前应用最广泛的神经网络模型之一。BP网络能学习和存贮大量的 输入-输出模式映射关系,而无需事前揭示描述这种映射关系的数学方程。它的学习规则是使用最速下降法,通过反向传播来不断 调整网络的权值和阈值,使网络的误差平方和最小。
BP算法的基本思想
上一次我们说到,多层感知器在如何获取隐层的权值的问题上遇到了瓶颈。既然我们无法直接得到隐层的权值,能否先通过输出层得到输出结果和期望输出的误差来间接调整隐层的权值呢?BP算法就是采用这样的思想设计出来的算法,它的基本思想是,学习过程由信号的正向传播与误差的反向传播两个过程组成。
- 正向传播时,输入样本从输入层传入,经各隐层逐层处理后,传向输出层。若输出层的实际输出与期望的输出(教师信号)不符,则转入误差的反向传播阶段。
- 反向传播时,将输出以某种形式通过隐层向输入层逐层反传,并将误差分摊给各层的所有单元,从而获得各层单元的误差信号,此误差信号即作为修正各单元权值的依据。
这两个过程的具体流程会在后文介绍。
BP算法的信号流向图如下图所示
BP网络特性分析——BP三要素我们分析一个ANN时,通常都是从它的三要素入手,即
1)网络拓扑结构;
2)传递函数;
3)学习算法。每一个要素的特性加起来就决定了这个ANN的功能特性。所以,我们也从这三要素入手对BP网络的研究。
3.1 BP网络的拓扑结构
上一次已经说了,BP网络实际上就是多层感知器,因此它的拓扑结构和多层感知器的拓扑结构相同。由于单隐层(三层)感知器已经能够解决简单的非线性问题,因此应用最为普遍。三层感知器的拓扑结构如下图所示。
一个最简单的三层BP:
###3.2 BP网络的传递函数
BP网络采用的传递函数是非线性变换函数——Sigmoid函数(又称S函数)。其特点是函数本身及其导数都是连续的,因而在处理上十分方便。为什么要选择这个函数,等下在介绍BP网络的学习算法的时候会进行进一步的介绍。
单极性S型函数曲线如下图所示。
双极性S型函数曲线如下图所示。
3.3 BP网络的学习算法
BP网络的学习算法就是BP算法,又叫 δ 算法(在ANN的学习过程中我们会发现不少具有多个名称的术语), 以三层感知器为例,当网络输出与期望输出不等时,存在输出误差 E ,定义如下
将以上误差定义式展开至隐层,有
进一步展开至输入层,有
由上式可以看出,网络输入误差是各层权值、的函数,因此调整权值可改变误差 。 显然,调整权值的原则是使误差不断减小,因此应使权值与误差的梯度下降成正比,即
对于一般多层感知器,设共有 个隐层,按前向顺序各隐层节点数分别记为 ,各隐层输出分别记为 ,各层权值矩阵分别记为 ,则各层权值调整公式为
输出层
第 隐层
按以上规律逐层类推,则第一隐层权值调整公式
容易看出,BP学习算法中,各层权值调整公式形式上都是一样的,均由3个因素决定,即:
- 学习率
- 本层输出的误差信号$ δ$
- 本层输入信号 (或)
其中输入层误差信号与网络的期望输出与实际输出之差有关,直接反应了输出误差,而各隐层的误差信号与前面各层的误差信号有关,是从输出层开始逐层反传过来的。
可以看出BP算法属于δ学习规则类,这类算法常被称为误差的梯度下降算法。δ学习规则可以看成是Widrow-Hoff(LMS)学习规则的一般化(generalize)情况。LMS学习规则与神经元采用的变换函数无关,因而不需要对变换函数求导,δ学习规则则没有这个性质,要求变换函数可导。这就是为什么我们前面采用Sigmoid函数的原因。
综上所述,BP三要素如下图所示。
下面我们会介绍BP网络的学习训练的具体过程。
BP网络的训练分解
训练一个BP神经网络,实际上就是调整网络的权重和偏置这两个参数,BP神经网络的训练过程分两部分:
- 前向传输,逐层波浪式的传递输出值;
- 逆向反馈,反向逐层调整权重和偏置;
我们先来看前向传输。
前向传输(Feed-Forward前向反馈)
在训练网络之前,我们需要随机初始化权重和偏置,对每一个权重取的一个随机实数,每一个偏置取的一个随机实数,之后就开始进行前向传输。
神经网络的训练是由多趟迭代完成的,每一趟迭代都使用训练集的所有记录,而每一次训练网络只使用一条记录,抽象的描述如下:
while 终止条件未满足: for record:dataset: trainModel(record)
首先设置输入层的输出值,假设属性的个数为100,那我们就设置输入层的神经单元个数为100,输入层的结点为记录第维上的属性值。对输入层的操作就这么简单,之后的每层就要复杂一些了,除输入层外,其他各层的输入值是上一层输入值按权重累加的结果值加上偏置,每个结点的输出值等该结点的输入值作变换
前向传输的输出层的计算过程公式如下:
对隐藏层和输出层的每一个结点都按照如上图的方式计算输出值,就完成前向传播的过程,紧接着是进行逆向反馈。逆向反馈(Backpropagation)
逆向反馈从最后一层即输出层开始,我们训练神经网络作分类的目的往往是希望最后一层的输出能够描述数据记录的类别,比如对于一个二分类的问题,我们常常用两个神经单元作为输出层,如果输出层的第一个神经单元的输出值比第二个神经单元大,我们认为这个数据记录属于第一类,否则属于第二类。
还记得我们第一次前向反馈时,整个网络的权重和偏置都是我们随机取,因此网络的输出肯定还不能描述记录的类别,因此需要调整网络的参数,即权重值和偏置值,而调整的依据就是网络的输出层的输出值与类别之间的差异,通过调整参数来缩小这个差异,这就是神经网络的优化目标。对于输出层:
其中表示第个结点的误差值,表示第个结点的输出值,记录输出值,比如对于2分类问题,我们用01表示类标1,10表示类别2,如果一个记录属于类别1,那么其,。中间的隐藏层并不直接与数据记录的类别打交道,而是通过下一层的所有结点误差按权重累加,计算公式如下:
其中表示当前层的结点到下一层的结点的权重值,下一层的结点的误差率。计算完误差率后,就可以利用误差率对权重和偏置进行更新,首先看权重的更新:
其中表示表示学习速率,取值为0到1,学习速率设置得大,训练收敛更快,但容易陷入局部最优解,学习速率设置得比较小的话,收敛速度较慢,但能一步步逼近全局最优解。更新完权重后,还有最后一项参数需要更新,即偏置:
至此,我们完成了一次神经网络的训练过程,通过不断的使用所有数据记录进行训练,从而得到一个分类模型。不断地迭代,不可能无休止的下去,总归有个终止条件。
训练终止条件
每一轮训练都使用数据集的所有记录,但什么时候停止,停止条件有下面两种:
- 设置最大迭代次数,比如使用数据集迭代100次后停止训练
- 计算训练集在网络上的预测准确率,达到一定门限值后停止训练
BP网络运行的具体流程
网络结构
输入层有个神经元,隐含层有个神经元,输出层有个神经元。
变量定义
输入变量:
隐含层输入变量:
隐含层输出变量:
输出层输入变量:
输出层输出变量:
期望输出向量:
输入层与中间层的连接权值:
隐含层与输出层的连接权值:
隐含层各神经元的阈值:
输出层各神经元的阈值:
样本数据个数:
激活函数:
误差函数:
###第一步:网络初始化
给各连接权值分别赋一个区间内的随机数,设定误差函数,给定计算精度值和最大学习次数。
###第二步:随机选取
随机选取第个输入样本以及对应的期望输出
###第三部:隐含层计算
计算隐含层各神经元的输入和输出
第四步:求偏导数
利用网络期望输出和实际输出,计算误差函数对输出层的各神经元的偏导数
第六步:修正权值
利用输出层各神经元的和隐含层各神经元的输出来修正连接权值。
第七部:修正权值
利用隐含层各神经元的和输入层各神经元的输入修正连接权值。
第八步:计算全局误差
第九步:判断模型合理性
判断网络误差是否满足要求。
当误差达到预设精度或者学习次数大于设计的最大次数,则结束算法。
否则,选取下一个学习样本以及对应的输出期望,返回第三部,进入下一轮学习。BP网络的设计
在进行BP网络的设计是,一般应从网络的层数、每层中的神经元个数和激活函数、初始值以及学习速率等几个方面来进行考虑,下面是一些选取的原则。
1.网络的层数
理论已经证明,具有偏差和至少一个S型隐层加上一个线性输出层的网络,能够逼近任何有理函数,增加层数可以进一步降低误差,提高精度,但同时也是网络 复杂化。另外不能用仅具有非线性激活函数的单层网络来解决问题,因为能用单层网络解决的问题,用自适应线性网络也一定能解决,而且自适应线性网络的 运算速度更快,而对于只能用非线性函数解决的问题,单层精度又不够高,也只有增加层数才能达到期望的结果。
2.隐层神经元的个数
网络训练精度的提高,可以通过采用一个隐含层,而增加其神经元个数的方法来获得,这在结构实现上要比增加网络层数简单得多。一般而言,我们用精度和 训练网络的时间来恒量一个神经网络设计的好坏:
(1)神经元数太少时,网络不能很好的学习,训练迭代的次数也比较多,训练精度也不高。
(2)神经元数太多时,网络的功能越强大,精确度也更高,训练迭代的次数也大,可能会出现过拟合(over fitting)现象。
由此,我们得到神经网络隐层神经元个数的选取原则是:在能够解决问题的前提下,再加上一两个神经元,以加快误差下降速度即可。3.初始权值的选取
一般初始权值是取值在(−1,1)之间的随机数。另外威得罗等人在分析了两层网络是如何对一个函数进行训练后,提出选择初始权值量级为s√r的策略, 其中r为输入个数,s为第一层神经元个数。
4.学习速率
学习速率一般选取为0.01−0.8,大的学习速率可能导致系统的不稳定,但小的学习速率导致收敛太慢,需要较长的训练时间。对于较复杂的网络, 在误差曲面的不同位置可能需要不同的学习速率,为了减少寻找学习速率的训练次数及时间,比较合适的方法是采用变化的自适应学习速率,使网络在 不同的阶段设置不同大小的学习速率。
5.期望误差的选取
在设计网络的过程中,期望误差值也应当通过对比训练后确定一个合适的值,这个合适的值是相对于所需要的隐层节点数来确定的。一般情况下,可以同时对两个不同 的期望误差值的网络进行训练,最后通过综合因素来确定其中一个网络。
BP网络的局限性
BP网络具有以下的几个问题:
- (1)需要较长的训练时间:这主要是由于学习速率太小所造成的,可采用变化的或自适应的学习速率来加以改进。
- (2)完全不能训练:这主要表现在网络的麻痹上,通常为了避免这种情况的产生,一是选取较小的初始权值,而是采用较小的学习速率。
- (3)局部最小值:这里采用的梯度下降法可能收敛到局部最小值,采用多层网络或较多的神经元,有可能得到更好的结果。
BP网络的改进
P算法改进的主要目标是加快训练速度,避免陷入局部极小值等,常见的改进方法有带动量因子算法、自适应学习速率、变化的学习速率以及作用函数后缩法等。 动量因子法的基本思想是在反向传播的基础上,在每一个权值的变化上加上一项正比于前次权值变化的值,并根据反向传播法来产生新的权值变化。而自适应学习 速率的方法则是针对一些特定的问题的。改变学习速率的方法的原则是,若连续几次迭代中,若目标函数对某个权倒数的符号相同,则这个权的学习速率增加, 反之若符号相反则减小它的学习速率。而作用函数后缩法则是将作用函数进行平移,即加上一个常数。
BP网络实现
由于BP网络具有出色的非线性映射能力、泛化能力和容错能力,因此BP网络成了至今为止应用最广泛的人工神经网络。下图是Matlab下用BP网络做线性拟合的结果,效果很好。
% 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, '--')
这是用C语言写的:用BP神经网络拟合函数:
#include "math.h" #include "time.h" #include "stdio.h" #include "stdlib.h" #include "ctype.h" #define Ni 1 #define Nm 4 #define No 1 #define L 100 #define Enom 0.02 #define loopmax 100000 #define e 2.71828 double E; double a,u,n; double W1[Ni][Nm],D1[Ni][Nm],W2[Nm][No],D2[Nm][No]; double D22[Nm][No],D11[Ni][No]; double a1[Ni][Nm],a2[Nm][No]; double Pi[L][Ni],Pm[L][Nm],Po[L][No],T[L][No]; double Xm[L][Nm],Xo[L][No]; double Qm[L][Nm],Qo[L][No]; void proceed(); void proceedR(); void forQ(); void amend(); void initiate(); double newa(double a,double D); double cal(double d); double vcal(double d); main() { long int i; int flag; char choice; for(;;) { flag=0; initiate(); for(i=0;;i++) { proceed(); if( E < Enom ) { flag=1; break; } if( i >= loopmax) { flag = -1; break; } if(i%2500==0) printf("第%10d轮误差:%20f,学习速率:%10f\n",i,E,a1[0][0]); forQ(); amend(); } if(flag>0)proceedR(); else printf("训练失败!\n"); for(;;) { choice=getchar(); printf("是否继续?(Y/N)\n"); choice=getchar(); choice=toupper(choice); if(choice=='Y')break; if(choice=='N')exit(0); } } } void initiate() { int i,j; int random; double x; double step; int stime; long ltime; ltime=time(NULL); stime=(unsigned)ltime/2; srand(stime); a=0.02; u=1; n=1; printf("本程序将用BP神经网络拟合函数:Y=sin(X)\n\n"); for( i=0; i<Nm; i++) { for( j=0; j<Ni; j++) { random=rand()%100-50; x=random; x=x/100; W1[j][i]=x; D11[j][i]=0; D1[j][i]=0; a1[j][i]=0.01; } for( j=0; j<No; j++) { random=rand()%100-50; x=random; x=x/100; W2[i][j]=x; D22[i][j]=0; D2[i][j]=0; a2[i][j]=0.01; } } step=1.0/L; for(i=0;i<L;i++) { x=i; Pi[i][0]=x*step; T[i][0]=sin(Pi[i][0]); } printf("初始化成功!\n\n下面将对神经网络进行训练请稍候。\n"); } void proceed() { int i, j, k; E=0 ; for( i=0; i<L; i++ ) { for( j=0; j<Nm; j++ ) { Pm[i][j] = 0; for( k=0; k<Ni; k++ ) { Pm[i][j] = Pi[i][k] * W1[k][j] + Pm[i][j]; } Xm[i][j] = cal( Pm[i][j] ); } for( j=0; j<No; j++) { Po[i][j] = 0; for( k=0; k<Nm; k++) { Po[i][j] = Xm[i][k] * W2[k][j] + Po[i][j]; } Xo[i][j] = cal( Po[i][j] ); E = E + ( Xo[i][j] - T[i][j] ) * ( Xo[i][j] - T[i][j] ) / 2; } } } void forQ() { int i,j,k; for( i=0; i<L; i++ ) { for( j=0; j<No; j++) { Qo[i][j] = ( T[i][j] - Xo[i][j] )* vcal( Xo[i][j] ); } for(j=0; j<Nm; j++) { Qm[i][j]=0; for( k=0; k<No; k++) { Qm[i][j] = Qo[i][k] * W2[j][k] + Qm[i][j]; } Qm[i][j] = Qm[i][j] * vcal( Xm[i][j] ); } } } void amend() { int i,j,k; double D; for( i=0; i<Nm; i++) { for( j=0; j<Ni; j++) { D1[j][i]=0; } for( j=0; j<No; j++) { D2[i][j]=0; } } for( i=0; i<Ni; i++) { for( j=0; j<Nm; j++) { for( k=0; k<L; k++) { D1[i][j] = Qm[k][j] * Pi[k][i] + D1[i][j]; } D = D1[i][j] * D11[i][j] ;//为D11付初值 a1[i][j] = newa( a1[i][j] , D ); // a 付初值 W1[i][j] = W1[i][j] + a1[i][j] * ( n * D1[i][j] + ( 1 - n ) * D11[i][j] ); D11[i][j] = D1[i][j]; } } for( i=0; i<Nm; i++) { for( j=0; j<No; j++) { for( k=0; k<L; k++) { D2[i][j] = Qo[k][j] * Xm[k][i] + D2[i][j]; } D = D2[i][j] * D22[i][j] ;//为D11付初值 a2[i][j] = newa( a2[i][j] , D ); W2[i][j] = W2[i][j] + a2[i][j] * ( n * D2[i][j] + ( 1 - n ) * D22[i][j] ); D22[i][j] = D2[i][j]; } } } void proceedR() { int i, j; float x; double input,output; char choice; for(;;) { for(;;) { printf("在此输入需要计算的值(0,1):\n"); scanf("%f",&x); input=(double)x; if((input>=0)&(input<=1))break; printf("注意输入值应介于0、1之间!\n"); for(;;) { choice=getchar(); printf("是否继续?(Y/N)\n"); choice=getchar(); choice=toupper(choice); if(choice=='Y')break; if(choice=='N')exit(0); } } for(i=0;i<Nm;i++) { Pm[0][i]=0; for( j=0; j<Ni; j++ ) { Pm[0][i] = input* W1[j][i]+Pm[0][i] ; } Xm[0][i] = cal( Pm[0][i] ); } for( i=0; i<No; i++) { Po[0][i] = 0; for( j=0; j<Nm; j++) { Po[0][i] = Xm[0][j] * W2[j][i]+Po[0][i]; } } output=cal( Po[0][0] ); printf("输入值为%20f对应的结果为%f\n",input,output); printf("输入值为%20f对应的正常结果为%f\n",input,sin(input)); for(;;) { choice=getchar(); printf("是否继续?(Y/N)\n"); choice=getchar(); choice=toupper(choice); if(choice=='Y')break; if(choice=='N')exit(0); } } } double newa(double a, double D) { if( D > 0 ) { { if(a<=0.04) a = a * 2; else a=0.08; } } else if ( D < 0) { if(a>=0.02) { a = a / 2; } else a=0.01; } return a; } double cal(double d) { d = - (d * u); // chushihua d = exp( d ); d = 1 / ( 1 + d ); return d; } double vcal(double d) { return u * d * ( 1 - d ); }
-
如何利用matlab做BP神经网络分析(利用matlab神经网络工具箱)
2018-08-02 16:19:53最近一段时间在研究如何利用...发现神经网络模型可以来预测,并且有很多是结合时间序列或者SVM(支持向量机)等组合模型来进行预测,本文结合实际数据,选取了常用的BP神经网络算法,其算法原理,因网上一大堆,所以...最近一段时间在研究如何利用预测其销量个数,在网上搜索了一下,发现了很多模型来预测,比如利用回归模型、时间序列模型,GM(1,1)模型,可是自己在结合实际的工作内容,发现这几种模型预测的精度不是很高,于是再在网上进行搜索,发现神经网络模型可以来预测,并且有很多是结合时间序列或者SVM(支持向量机)等组合模型来进行预测,本文结合实际数据,选取了常用的BP神经网络算法,其算法原理,因网上一大堆,所以在此不必一一展示,并参考了bp神经网络进行交通预测的Matlab源代码这篇博文,运用matlab 2016a,给出了下面的代码,并最终进行了预测
clc clear all close all %bp 神经网络的预测代码 %载入输出和输入数据 load C:\Users\amzon\Desktop\p.txt; load C:\Users\amzon\Desktop\t.txt; %保存数据到matlab的工作路径里面 save p.mat; save t.mat;%注意t必须为行向量 %赋值给输出p和输入t p=p; t=t; %数据的归一化处理,利用mapminmax函数,使数值归一化到[-1.1]之间 %该函数使用方法如下:[y,ps] =mapminmax(x,ymin,ymax),x需归化的数据输入, %ymin,ymax为需归化到的范围,不填默认为归化到[-1,1] %返回归化后的值y,以及参数ps,ps在结果反归一化中,需要调用 [p1,ps]=mapminmax(p); [t1,ts]=mapminmax(t); %确定训练数据,测试数据,一般是随机的从样本中选取70%的数据作为训练数据 %15%的数据作为测试数据,一般是使用函数dividerand,其一般的使用方法如下: %[trainInd,valInd,testInd] = dividerand(Q,trainRatio,valRatio,testRatio) [trainsample.p,valsample.p,testsample.p] =dividerand(p,0.7,0.15,0.15); [trainsample.t,valsample.t,testsample.t] =dividerand(t,0.7,0.15,0.15); %建立反向传播算法的BP神经网络,使用newff函数,其一般的使用方法如下 %net = newff(minmax(p),[隐层的神经元的个数,输出层的神经元的个数],{隐层神经元的传输函数,输出层的传输函数},'反向传播的训练函数'),其中p为输入数据,t为输出数据 %tf为神经网络的传输函数,默认为'tansig'函数为隐层的传输函数, %purelin函数为输出层的传输函数 %一般在这里还有其他的传输的函数一般的如下,如果预测出来的效果不是很好,可以调节 %TF1 = 'tansig';TF2 = 'logsig'; %TF1 = 'logsig';TF2 = 'purelin'; %TF1 = 'logsig';TF2 = 'logsig'; %TF1 = 'purelin';TF2 = 'purelin'; TF1='tansig';TF2='purelin'; net=newff(minmax(p),[10,1],{TF1 TF2},'traingdm');%网络创建 %网络参数的设置 net.trainParam.epochs=10000;%训练次数设置 net.trainParam.goal=1e-7;%训练目标设置 net.trainParam.lr=0.01;%学习率设置,应设置为较少值,太大虽然会在开始加快收敛速度,但临近最佳点时,会产生动荡,而致使无法收敛 net.trainParam.mc=0.9;%动量因子的设置,默认为0.9 net.trainParam.show=25;%显示的间隔次数 % 指定训练参数 % net.trainFcn = 'traingd'; % 梯度下降算法 % net.trainFcn = 'traingdm'; % 动量梯度下降算法 % net.trainFcn = 'traingda'; % 变学习率梯度下降算法 % net.trainFcn = 'traingdx'; % 变学习率动量梯度下降算法 % (大型网络的首选算法) % net.trainFcn = 'trainrp'; % RPROP(弹性BP)算法,内存需求最小 % 共轭梯度算法 % net.trainFcn = 'traincgf'; %Fletcher-Reeves修正算法 % net.trainFcn = 'traincgp'; %Polak-Ribiere修正算法,内存需求比Fletcher-Reeves修正算法略大 % net.trainFcn = 'traincgb'; % Powell-Beal复位算法,内存需求比Polak-Ribiere修正算法略大 % (大型网络的首选算法) %net.trainFcn = 'trainscg'; % ScaledConjugate Gradient算法,内存需求与Fletcher-Reeves修正算法相同,计算量比上面三种算法都小很多 % net.trainFcn = 'trainbfg'; %Quasi-Newton Algorithms - BFGS Algorithm,计算量和内存需求均比共轭梯度算法大,但收敛比较快 % net.trainFcn = 'trainoss'; % OneStep Secant Algorithm,计算量和内存需求均比BFGS算法小,比共轭梯度算法略大 % (中型网络的首选算法) %net.trainFcn = 'trainlm'; %Levenberg-Marquardt算法,内存需求最大,收敛速度最快 % net.trainFcn = 'trainbr'; % 贝叶斯正则化算法 % 有代表性的五种算法为:'traingdx','trainrp','trainscg','trainoss', 'trainlm' %在这里一般是选取'trainlm'函数来训练,其算对对应的是Levenberg-Marquardt算法 net.trainFcn='trainlm'; [net,tr]=train(net,trainsample.p,trainsample.t); %计算仿真,其一般用sim函数 [normtrainoutput,trainPerf]=sim(net,trainsample.p,[],[],trainsample.t);%训练的数据,根据BP得到的结果 [normvalidateoutput,validatePerf]=sim(net,valsample.p,[],[],valsample.t);%验证的数据,经BP得到的结果 [normtestoutput,testPerf]=sim(net,testsample.p,[],[],testsample.t);%测试数据,经BP得到的结果 %将所得的结果进行反归一化,得到其拟合的数据 trainoutput=mapminmax('reverse',normtrainoutput,ts); validateoutput=mapminmax('reverse',normvalidateoutput,ts); testoutput=mapminmax('reverse',normtestoutput,ts); %正常输入的数据的反归一化的处理,得到其正式值 trainvalue=mapminmax('reverse',trainsample.t,ts);%正常的验证数据 validatevalue=mapminmax('reverse',valsample.t,ts);%正常的验证的数据 testvalue=mapminmax('reverse',testsample.t,ts);%正常的测试数据 %做预测,输入要预测的数据pnew pnew=[313,256,239]'; pnewn=mapminmax(pnew); anewn=sim(net,pnewn); anew=mapminmax('reverse',anewn,ts); %绝对误差的计算 errors=trainvalue-trainoutput; %plotregression拟合图 figure,plotregression(trainvalue,trainoutput) %误差图 figure,plot(1:length(errors),errors,'-b') title('误差变化图') %误差值的正态性的检验 figure,hist(errors);%频数直方图 figure,normplot(errors);%Q-Q图 [muhat,sigmahat,muci,sigmaci]=normfit(errors);%参数估计 均值,方差,均值的0.95置信区间,方差的0.95置信区间 [h1,sig,ci]= ttest(errors,muhat);%假设检验 figure, ploterrcorr(errors);%绘制误差的自相关图 figure, parcorr(errors);%绘制偏相关图
运行之后的,结果如下:
BP神经网络的结果分析图
训练数据的梯度和均方误差之间的关系图
验证数据的梯度与学习次数
残差的正态的检验图(Q-Q图)
在网上,发现可以通过神经网络工具箱这个GUI界面来创建神经网络,其一般的操作步骤如下:
1:在输入命令里面输入nntool命令,或者在应用程序这个选项下找到Netrual Net Fitting 这个应用程序,点击打开,就能看见如下界面
2:输入数据和输出数据的导入(在本文中选取了matlab自带的案例数据)
3:随机选择三种类型的数据所占的样本量的比例,一般选取默认即可
4:隐层神经元的确定
5:训练算法的选取,一般是选择默认即可,选择完成后点击<train>按钮即可运行程序
6:根据得到的结果,一般是MSE的值越小,R值越接近1,其训练的效果比较,并第二张图给出了神经网络的各参数的设置以及其最终的结果,其拟合图R越接近1,模型拟合的更好
最终的结果图7:如果所得到的模型不能满足你的需求,则需重复上述的步骤直至能够得到你想要的精确度
8:将最终的得到的各种数据以及其拟合值进行保存,然后查看,就可以得到所要的拟合值
最后参考了网上和MATLAB的帮助,给出了一些与神经网络相关的函数,希望能够帮助大家。。
图形用户界面功能。
nnstart - 神经网络启动GUI
nctool - 神经网络分类工具
nftool - 神经网络的拟合工具
nntraintool - 神经网络的训练工具
nprtool - 神经网络模式识别工具
ntstool - NFTool神经网络时间序列的工具
nntool - 神经网络工具箱的图形用户界面。
查看 - 查看一个神经网络。
网络的建立功能。
cascadeforwardnet - 串级,前馈神经网络。
competlayer - 竞争神经层。
distdelaynet - 分布时滞的神经网络。
elmannet - Elman神经网络。
feedforwardnet - 前馈神经网络。
fitnet - 函数拟合神经网络。
layrecnet - 分层递归神经网络。
linearlayer - 线性神经层。
lvqnet - 学习矢量量化(LVQ)神经网络。
narnet - 非线性自结合的时间序列网络。
narxnet - 非线性自结合的时间序列与外部输入网络。
newgrnn - 设计一个广义回归神经网络。
newhop - 建立经常性的Hopfield网络。
newlind - 设计一个线性层。
newpnn - 设计概率神经网络。
newrb - 径向基网络设计。
newrbe - 设计一个确切的径向基网络。
patternnet - 神经网络模式识别。
感知 - 感知。
selforgmap - 自组织特征映射。
timedelaynet - 时滞神经网络。
利用网络。
网络 - 创建一个自定义神经网络。
SIM卡 - 模拟一个神经网络。
初始化 - 初始化一个神经网络。
适应 - 允许一个神经网络来适应。
火车 - 火车的神经网络。
DISP键 - 显示一个神经网络的属性。
显示 - 显示的名称和神经网络属性
adddelay - 添加延迟神经网络的反应。
closeloop - 神经网络的开放反馈转换到关闭反馈回路。
formwb - 表格偏见和成单个向量的权重。
getwb - 将它作为一个单一向量中的所有网络权值和偏差。
noloop - 删除神经网络的开放和关闭反馈回路。
开环 - 转换神经网络反馈,打开封闭的反馈循环。
removedelay - 删除延迟神经网络的反应。
separatewb - 独立的偏见和重量/偏置向量的权重。
setwb - 将所有与单个矢量网络权值和偏差。
Simulink的支持。
gensim - 生成Simulink模块来模拟神经网络。
setsiminit - 集神经网络的Simulink模块的初始条件
getsiminit - 获取神经网络Simulink模块的初始条件
神经元 - 神经网络Simulink的模块库。
培训职能。
trainb - 批具有重量与偏见学习规则的培训。
trainbfg - 的BFGS拟牛顿倒传递。
trainbr - 贝叶斯规则的BP算法。
trainbu - 与重量与偏见一批无监督学习规则的培训。
trainbuwb - 与体重无监督学习规则与偏见一批培训。
trainc - 循环顺序重量/偏见的培训。
traincgb - 共轭鲍威尔比尔重新启动梯度反向传播。
traincgf - 共轭弗莱彻-里夫斯更新梯度反向传播。
traincgp - 共轭波拉克- Ribiere更新梯度反向传播。
traingd - 梯度下降反向传播。
traingda - 具有自适应LR的反向传播梯度下降。
traingdm - 与动量梯度下降。
traingdx - 梯度下降瓦特/惯性与自适应LR的反向传播。
trainlm - 采用Levenberg -马奎德倒传递。
trainoss - 一步割线倒传递。
trainr - 随机重量/偏见的培训。
trainrp - RPROP反向传播。
trainru - 无监督随机重量/偏见的培训。
火车 - 顺序重量/偏见的培训。
trainscg - 规模化共轭梯度BP算法。
绘图功能。
plotconfusion - 图分类混淆矩阵。
ploterrcorr - 误差自相关时间序列图。
ploterrhist - 绘制误差直方图。
plotfit - 绘图功能适合。
plotinerrcorr - 图输入错误的时间序列的互相关。
plotperform - 小区网络性能。
plotregression - 线性回归情节。
plotresponse - 动态网络图的时间序列响应。
plotroc - 绘制受试者工作特征。
plotsomhits - 小区自组织图来样打。
plotsomnc - 小区自组织映射邻居的连接。
plotsomnd - 小区自组织映射邻居的距离。
plotsomplanes - 小区自组织映射重量的飞机。
plotsompos - 小区自组织映射重量立场。
plotsomtop - 小区自组织映射的拓扑结构。
plottrainstate - 情节训练状态值。
plotwb - 图寒春重量和偏差值图。
列出其他神经网络实现的功能。
nnadapt - 适应职能。
nnderivative - 衍生功能。
nndistance - 距离函数。
nndivision - 除功能。
nninitlayer - 初始化层功能。
nninitnetwork - 初始化网络功能。
nninitweight - 初始化权函数。
nnlearn - 学习功能。
nnnetinput - 净输入功能。
nnperformance - 性能的功能。
nnprocess - 处理功能。
nnsearch - 线搜索功能。
nntopology - 拓扑结构的功能。
nntransfer - 传递函数。
nnweight - 重量的功能。
nndemos - 神经网络工具箱的示威。
nndatasets - 神经网络工具箱的数据集。
nntextdemos - 神经网络设计教科书的示威。
nntextbook - 神经网络设计教科书的资讯。 -
python3_实现BP神经网络 + BP神经网络应用实例
2018-07-29 22:10:281.BP神经网络简介 BP神经网络是1986年由Rumelhart和McClelland为首的科学家提出的概念,是一种按照逆向传播算法训练的多层前馈神经网络,是目前应用最广泛的神经网络。 优点:具有任意复杂的模式分类能力和优良的...0.目录
1.BP神经网络简介
BP神经网络是1986年由Rumelhart和McClelland为首的科学家提出的概念,是一种按照逆向传播算法训练的多层前馈神经网络,是目前应用最广泛的神经网络。
目录
优点:
- 1.具有任意复杂的模式分类能力和优良的多维函数映射能力,解决了简单感知器不能解决的异或问题的问题(参考博客:https://www.jianshu.com/p/a25788130897 或 https://www.cnblogs.com/xym4869/p/11282469.html)
- 2.从结构上讲,BP神经网络具有输入层、隐含层和输出层
- 3.从本质上讲,BP算法就是以网络误差平方目标函数、采用梯度下降法来计算目标函数的最小值。基本BP算法包括信号的前向传播和误差的反向传播两个过程。
缺点:
- 1.学习速度慢,即使是一个简单的过程,也需要几百次甚至上千次的学习才能收敛。
- 2.容易陷入局部极小值
- 3.网络层数、神经元个数的选择没有相应的理论指导
- 4.网络推广能力有限。
应用:
- 1.函数逼近
- 2.模式识别
- 3.分类
- 4.数据压缩
2.前期理论准备
网络训练的目标:找到合适的权值和阈值,使得误差E最小。
sigmoid函数:在信息科学当中,由于其单增以及其反函数单增等性质,sigmoid函数常被用作神经网络的阈值函数,将变量映射当0和1之间。(该函数的对x的求导也应该理解)
2.算法数学原理
(一)符号说明
Xi: 输入信号。
Xd: 隐层的阈值(是从求和函数中-θ中分离出的-1)。
Vih: 第h个隐层神经元所对应输入信号Xi的权值。
αh: 第h个隐层神经元的输入。
-γh=--1*γh:隐层神经元的阈值。
bh: 第h个隐层神经元的输入。
ωhj: 第j个输出层神经元所对应的隐层神经元输出bh的权值。
-θj=-1*θj: 输出层神经元的阈值(bq)
:第j个输出层神经元的输出(预测输出值,yj为真实值)
(二)公式推导
通过公式变换可得输出层权值与阈值的变化量:
同理可得隐层权值和阈值的变化量:
3.python实现(python3编程实现)
(一)sigmoid函数
def sigmoid(x): """ 隐含层和输出层对应的函数法则 """ return 1/(1+np.exp(-x))
(二)BP主函数实现
def BP(data_tr, data_te, maxiter=600): # --pandas是基于numpy设计的,效率略低 # 为提高处理效率,转换为数组 data_tr, data_te = np.array(data_tr), np.array(data_te) # --隐层输入 # -1: 代表的是隐层的阈值 net_in = np.array([0.0, 0, -1]) w_mid = np.random.rand(3, 4) # 隐层权值阈值(-1x其中一个值:阈值) # 输出层输入 # -1:代表输出层阈值 out_in = np.array([0.0, 0, 0, 0, -1]) w_out = np.random.rand(5) # 输出层权值阈值(-1x其中一个值:阈值) delta_w_out = np.zeros([5]) # 存放输出层权值阈值的逆向计算误差 delta_w_mid = np.zeros([3, 4]) # 存放因此能权值阈值的逆向计算误差 yita = 1.75 # η: 学习速率 Err = np.zeros([maxiter]) # 记录总体样本每迭代一次的错误率 # 1.样本总体训练的次数 for it in range(maxiter): # 衡量每一个样本的误差 err = np.zeros([len(data_tr)]) # 2.训练集训练一遍 for j in range(len(data_tr)): net_in[:2] = data_tr[j, :2] # 存储当前对象前两个属性值 real = data_tr[j, 2] # 3.当前对象进行训练 for i in range(4): out_in[i] = sigmoid(sum(net_in*w_mid[:, i])) # 计算输出层输入 res = sigmoid(sum(out_in * w_out)) # 获得训练结果 err[j] = abs(real - res) # --先调节输出层的权值与阈值 delta_w_out = yita*res*(1-res)*(real-res)*out_in # 权值调整 delta_w_out[4] = -yita*res*(1-res)*(real-res) # 阈值调整 w_out = w_out + delta_w_out # --隐层权值和阈值的调节 for i in range(4): # 权值调整 delta_w_mid[:, i] = yita * out_in[i] * (1 - out_in[i]) * w_out[i] * res * (1 - res) * (real - res) * net_in # 阈值调整 delta_w_mid[2, i] = -yita * out_in[i] * (1 - out_in[i]) * w_out[i] * res * (1 - res) * (real - res) w_mid = w_mid + delta_w_mid Err[it] = err.mean() plt.plot(Err) plt.show() # 存储预测误差 err_te = np.zeros([100]) # 预测样本100个 for j in range(100): net_in[:2] = data_te[j, :2] # 存储数据 real = data_te[j, 2] # 真实结果 # net_in和w_mid的相乘过程 for i in range(4): # 输入层到隐层的传输过程 out_in[i] = sigmoid(sum(net_in*w_mid[:, i])) res = sigmoid(sum(out_in*w_out)) # 网络预测结果输出 err_te[j] = abs(real-res) # 预测误差 print('res:', res, ' real:', real) plt.plot(err_te) plt.show() if "__main__" == __name__: # 1.读取样本 data_tr = pd.read_csv("5.2 data_tr.txt") data_te = pd.read_csv("5.2 data_te.txt") BP(data_tr, data_te, maxiter=600)
4.数据格式
-
如何利用matlab做BP神经网络分析(包括利用matlab神经网络工具箱)
2016-11-21 21:54:01利用MATLAB 进行BP神经网络的预测(含有神经网络工具箱) 最近一段时间在研究如何利用预测其销量个数,在网上搜索了一下,发现了很多模型来预测,比如利用回归模型、时间序列模型,GM(1,1)模型,可是自己在结合... -
BP 神经网络
2019-06-22 11:09:00基于BP神经网络与遗传算法实现盾构砂浆性能优化方法技术 技术编号:14113655阅读:494留言:0更新日期:2016-12-07 11:00 本发明专利技术公开了一种基于BP神经网络与遗传算法实现盾构砂浆性能优化方法,包括以下...
-
2010-2020年暨南大学824环境保护概论考研真题
-
Anaconda for MAC安装及踩坑指北
-
MFC开发简单聊天程序
-
GAMES101图形学P5笔记(三角形的光栅化)
-
【数据分析-随到随学】Spark理论及实战
-
LED光源的光谱与色域面积关系
-
素数筛
-
第3章 入门程序、常量、变量
-
Spring Boot2.X仿朋友圈PC版系统实战_架构1.0
-
WPF上位机数据采集与监控系统零基础实战
-
全国综合性地方门户网站系统
-
条纹投影法中抗噪声干扰的相移编码去包裹方法
-
75. 颜色分类
-
国产工业级准单模光纤振荡器实现5.16 kW激光输出
-
MATLAB出入库车牌识别计费(语音播报,GUI界面,论文).zip
-
硫/碳复合材料在锂硫电池正极中的应用
-
中红外甲烷二氧化碳双气体传感系统的研制
-
MATLAB车票发票识别.zip
-
分布式面试之ZooKeeper面试题指南
-
Novel laser Doppler tachometer