深度学习入门:一文详解BP神经网络

您所在的位置:网站首页 数据bp是啥 深度学习入门:一文详解BP神经网络

深度学习入门:一文详解BP神经网络

2024-07-16 01:34| 来源: 网络整理| 查看: 265

今天来讲BP神经网络,神经网络在机器学习中应用比较广泛,比如函数逼近,模式识别,分类,数据压缩,数据

挖掘等领域。接下来介绍BP神经网络的原理及实现。

1. BP神经网络的认识

   BP(Back Propagation)神经网络分为两个过程​​​​​​​

      (1)工作信号正向传递子过程

      (2)误差信号反向传递子过程

 

   在BP神经网络中,单个样本有个输入,有个输出,在输入层和输出层之间通常还有若干个隐含层。实际

   上,1989年Robert Hecht-Nielsen证明了对于任何闭区间内的一个连续函数都可以用一个隐含层的BP网

   络来逼近,这就是万能逼近定理。所以一个三层的BP网络就可以完成任意的维到维的映射。即这三层分

   别是输入层(I),隐含层(H),输出层(O)。如下图示

        

2. 隐含层的选取

   在BP神经网络中,输入层和输出层的节点个数都是确定的,而隐含层节点个数不确定,那么应该设置为多少

   才合适呢?实际上,隐含层节点个数的多少对神经网络的性能是有影响的,有一个经验公式可以确定隐含层

   节点数目,如下

                

   其中为隐含层节点数目,为输入层节点数目,为输出层节点数目,之间的调节常数。

3. 正向传递子过程

   现在设节点和节点之间的权值为,节点的阀值为,每个节点的输出值为,而每个节点的输出

   值是根据上层所有节点的输出值、当前节点与上一层所有节点的权值和当前节点的阀值还有激活函数来实现

   的。具体计算方法如下

                    

   其中为激活函数,一般选取S型函数或者线性函数。

   正向传递的过程比较简单,按照上述公式计算即可。在BP神经网络中,输入层节点没有阀值。

4. 反向传递子过程

   在BP神经网络中,误差信号反向传递子过程比较复杂,它是基于Widrow-Hoff学习规则的。假设输出层

   的所有结果为,误差函数如下

                    

   而BP神经网络的主要目的是反复修正权值和阀值,使得误差函数值达到最小。Widrow-Hoff学习规则

   是通过沿着相对误差平方和的最速下降方向,连续调整网络的权值和阀值,根据梯度下降法,权值矢量

   的修正正比于当前位置上E(w,b)的梯度,对于第个输出节点有

                    

   假设选择激活函数为

                    

   对激活函数求导,得到

                   

   那么接下来针对

                   

   其中有

                            

   同样对于

                 

   这就是著名的学习规则,通过改变神经元之间的连接权值来减少系统实际输出和期望输出的误差,这个规

   则又叫做Widrow-Hoff学习规则或者纠错学习规则。

  

   上面是对隐含层和输出层之间的权值和输出层的阀值计算调整量,而针对输入层和隐含层和隐含层的阀值调

   整量的计算更为复杂。假设是输入层第k个节点和隐含层第i个节点之间的权值,那么有

                

   其中有

                

   这样对学习规则理解更为深刻了吧。

   有了上述公式,根据梯度下降法,那么对于隐含层和输出层之间的权值和阀值调整如下

                

   而对于输入层和隐含层之间的权值和阀值调整同样有

                

   至此BP神经网络的原理基本讲完。

5. BP神经网络的注意点

 

   BP神经网络一般用于分类或者逼近问题。如果用于分类,则激活函数一般选用Sigmoid函数或者硬极限函

   数,如果用于函数逼近,则输出层节点用线性函数,即

 

   BP神经网络在训练数据时可以采用增量学习或者批量学习。

 

   增量学习要求输入模式要有足够的随机性,对输入模式的噪声比较敏感,即对于剧烈变化的输入模式,训

   练效果比较差,适合在线处理。批量学习不存在输入模式次序问题,稳定性好,但是只适合离线处理。

 

   标准BP神经网络的缺陷:

   (1)容易形成局部极小值而得不到全局最优值。

       BP神经网络中极小值比较多,所以很容易陷入局部极小值,这就要求对初始权值和阀值有要求,要使

       得初始权值和阀值随机性足够好,可以多次随机来实现。

   (2)训练次数多使得学习效率低,收敛速度慢。

   (3)隐含层的选取缺乏理论的指导。

   (4)训练时学习新样本有遗忘旧样本的趋势。

   

   BP算法的改进:

   (1)增加动量项

       引入动量项是为了加速算法收敛,即如下公式

       

       动量因子一般选取

   (2)自适应调节学习率

   (3)引入陡度因子

   通常BP神经网络在训练之前会对数据归一化处理,即将数据映射到更小的区间内,比如[0,1]或[-1,1]。

 

 

6. BP神经网络的C++实现

 

   BP神经网络的C++文件如下

   

BP.h:

[cpp]  view plain  copy #ifndef _BP_H_  #define _BP_H_     #include      #define LAYER    3        //三层神经网络  #define NUM      10       //每层的最多节点数     #define A        30.0  #define B        10.0     //A和B是S型函数的参数  #define ITERS    1000     //最大训练次数  #define ETA_W    0.0035   //权值调整率  #define ETA_B    0.001    //阀值调整率  #define ERROR    0.002    //单个样本允许的误差  #define ACCU     0.005    //每次迭代允许的误差     #define Type double  #define Vector std::vector     struct Data  {      Vector x;       //输入数据      Vector y;       //输出数据  };     class BP{     public:         void GetData(const Vector);      void Train();      Vector ForeCast(const Vector);     private:         void InitNetWork();         //初始化网络      void GetNums();             //获取输入、输出和隐含层节点数      void ForwardTransfer();     //正向传播子过程      void ReverseTransfer(int);  //逆向传播子过程      void CalcDelta(int);        //计算w和b的调整量      void UpdateNetWork();       //更新权值和阀值      Type GetError(int);         //计算单个样本的误差      Type GetAccu();             //计算所有样本的精度      Type Sigmoid(const Type);   //计算Sigmoid的值     private:      int in_num;                 //输入层节点数      int ou_num;                 //输出层节点数      int hd_num;                 //隐含层节点数         Vector data;          //输入输出数据         Type w[LAYER][NUM][NUM];    //BP网络的权值      Type b[LAYER][NUM];         //BP网络节点的阀值             Type x[LAYER][NUM];         //每个神经元的值经S型函数转化后的输出值,输入层就为原值      Type d[LAYER][NUM];         //记录delta学习规则中delta的值  };     #endif  //_BP_H_  

BP.cpp:

[cpp]  view plain  copy #include   #include   #include   #include   #include "BP.h"    //获取训练所有样本数据  void BP::GetData(const Vector _data)  {      data = _data;  }    //开始进行训练  void BP::Train()  {      printf("Begin to train BP NetWork!\n");      GetNums();      InitNetWork();      int num = data.size();        for(int iter = 0; iter 


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3