BP神经网络

来源:互联网 发布:sqlserver数据备份方式 编辑:程序博客网 时间:2024/05/29 23:48

http://www.cnblogs.com/jzhlin/archive/2012/07/30/bp_c.html

在上一篇文章中,介绍了BP神经网络的基本模型、模型中的一些术语并对模型进行了数学上的分析,对它的原理有了初步的认识。那么如何用程序语言来具体的实现它,将是我们下一步需要讨论的问题。本文选取的是C语言来实现一个简单的单隐藏层的BP神经网络(默认大家了解了BP神经网络的基本概念,本文中涉及到些术语参见上一篇  基本模型 ),因此对于其他C类语言(C#、JAVA等)只需对本文中的代码稍作修改即可移植。

一些数据的定义

   首先,我们介绍些下文中描述的程序里面的一些重要数据的定义。

#define Data  820#define In 2#define Out 1#define Neuron 45#define TrainC 5500

 Data 用来表示已经知道的数据样本的数量,也就是训练样本的数量。In 表示对于每个样本有多少个输入变量; Out 表示对于每个样本有多少个输出变量。Neuron 表示神经元的数量,TrainC 来表示训练的次数。再来我们看对神经网络描述的数据定义,来看下面这张图里面的数据类型都是 double 型。



 d_in[Data][In] 存储 Data 个样本,每个样本的 In 个输入。d_out[Data][Out] 存储 Data 个样本,每个样本的 Out 个输出。我们用邻接表法来表示 图1 中的网络,w[Neuron][In]  表示某个输入对某个神经元的权重,v[Out][Neuron] 来表示某个神经元对某个输出的权重;与之对应的保存它们两个修正量的数组 dw[Neuron][In] 和 dv[Out][Neuron]。数组 o[Neuron] 记录的是神经元通过激活函数对外的输出,OutputData[Out]  存储BP神经网络的输出。

程序的执行过程

         在这里,先不考虑具体函数的执行细节,从大体上来介绍程序的执行过程。用伪代码来表示,具体的内容后面一步步介绍,如下:

复制代码
主函数main{    读取样本数据 readData();       初始化BP神经网络  initBPNework(){            包括数据的归一,神经元的初始化 w[Neuron][In]、v[Out][Neuron]等;        }        BP神经网络训练 trainNetwork(){            do{                for(i 小于 样本容量 Data){                                计算按照第 i 个样本输入,产生的BP神经网络的输出 computO(i);                    累记误差精度;                    反馈调节BP神经网络中的神经元,完成第 i 个样本的学习 backUpdate(i);                }            }while(达到训练次数 或者 符合误差精度);        }        存储训练好的神经元信息  writeNeuron();        用一些数据来测试,训练出来的BP神经网络的结果;        return 0;}
复制代码

 以上是处理的流程,对于读取数据、保存数据之类的处理本文将略去这方面内容,突出主干部分。

初始化BP神经网络

      初始化主要是涉及两个方面的功能,一方面是对读取的训练样本数据进行归一化处理,归一化处理就是指的就是将数据转换成0~1之间。在BP神经网络理论里面,并没有对这个进行要求,不过实际实践过程中,归一化处理是不可或缺的。因为理论模型没考虑到,BP神经网络收敛的速率问题,一般来说神经元的输出对于0~1之间的数据非常敏感,归一化能够显著提高训练效率。可以用以下公式来对其进行归一化,其中 加个常数A 是为了防止出现 0 的情况(0不能为分母)。

       y=(x-MinValue+A)/(MaxValue-MinValue+A)

      另一方面,就是对神经元的权重进行初始化了,数据归一到了(0~1)之间,那么权重初始化为(-1~1)之间的数据,另外对修正量赋值为0。实现参考代码如下:

复制代码
void initBPNework(){    int i,j;   /*    找到数据最小、最大值   */    for(i=0; i<In; i++){        Minin[i]=Maxin[i]=d_in[0][i];        for(j=0; j<Data; j++)        {            Maxin[i]=Maxin[i]>d_in[j][i]?Maxin[i]:d_in[j][i];            Minin[i]=Minin[i]<d_in[j][i]?Minin[i]:d_in[j][i];        }    }    for(i=0; i<Out; i++){        Minout[i]=Maxout[i]=d_out[0][i];        for(j=0; j<Data; j++)        {            Maxout[i]=Maxout[i]>d_out[j][i]?Maxout[i]:d_out[j][i];            Minout[i]=Minout[i]<d_out[j][i]?Minout[i]:d_out[j][i];        }    }    /*    归一化处理    */    for (i = 0; i < In; i++)        for(j = 0; j < Data; j++)            d_in[j][i]=(d_in[j][i]-Minin[i]+1)/(Maxin[i]-Minin[i]+1);    for (i = 0; i < Out; i++)        for(j = 0; j < Data; j++)            d_out[j][i]=(d_out[j][i]-Minout[i]+1)/(Maxout[i]-Minout[i]+1);    /*    初始化神经元  */    for (i = 0; i < Neuron; ++i)            for (j = 0; j < In; ++j){                w[i][j]=(rand()*2.0/RAND_MAX-1)/2;            dw[i][j]=0;        }    for (i = 0; i < Neuron; ++i)             for (j = 0; j < Out; ++j){             v[j][i]=(rand()*2.0/RAND_MAX-1)/2;              dv[j][i]=0;         }}
复制代码

 

BP神经网络训练

      这部分应当说是整个BP神经网络形成的引擎,驱动着样本训练过程的执行。由BP神经网络的基本模型知道,反馈学习机制包括两大部分,一是BP神经网络产生预测的结果,二是通过预测的结果和样本的准确结果进行比对,然后对神经元进行误差量的修正。因此,我们用两个函数来表示这样的两个过程,训练过程中还对平均误差 e 进行监控,如果达到了设定的精度即可完成训练。由于不一定能够到达预期设定的精度要求,我们添加一个训练次数的参数,如果次数达到也退出训练。实现参考代码如下:

 

复制代码
void  trainNetwork(){    int i,c=0;    do{        e=0;        for (i = 0; i < Data; ++i){            computO(i);            e+=fabs((OutputData[0]-d_out[i][0])/d_out[i][0]);            backUpdate(i);        }        //printf("%d  %lf\n",c,e/Data);        c++;    }while(c<TrainC && e/Data>0.01);}
复制代码

 

        其中的函数,computO(i) (O是output缩写)计算BP神经网络预测第 i 个样本的输出也就是第一个过程。backUpdate(i) 是根据预测的第 i 个样本输出对神经网络的权重进行更新,e用来监控误差。

BP神经网络输出

      函数 computO(i) 负责的是通过BP神经网络的机制对样本 i 的输入,预测其输出。回想BP神经网络的基本模型(详情见 基本模型 )对应的公式(1)还有 激活函数对应的公式(2):

BP神经网络     

BP神经网络

      

      在前篇设计的BP神经网络中,输入层与隐藏层权重对应的数据结构是w[Neuron][In],隐藏层与输出层权重对应的数据结构是v[Out][Neuron],并且数组 o[Neuron] 记录的是神经元通过激活函数对外的输出,BP神经网络预测的样本结果保存在OutputData[Out]中。由此,就可以得到以下实现的参考代码:

void computO(int var){    int i,j;    double sum,y;                /*            神经元输出         */            for (i = 0; i < Neuron; ++i){        sum=0;        for (j = 0; j < In; ++j)            sum+=w[i][j]*d_in[var][j];        o[i]=1/(1+exp(-1*sum));    }/*  隐藏层到输出层输出 */    for (i = 0; i < Out; ++i){        sum=0;        for (j = 0; j < Neuron; ++j)            sum+=v[i][j]*o[j];        OutputData[i]=sum;    }    }

 

BP神经网络的反馈学习

         函数 backUpdate(i) 负责的是将预测输出的结果与样本真实的结果进行比对,然后对神经网络中涉及到的权重进行修正,也这是BP神经网络实现的关键所在。如何求到对于 w[Neuron][In] 和 v[Out][Neuron] 进行修正的误差量便是 关键所在! 误差修正量的求法在基本模型一文中数学分析部分有解答, 具体问题具体分析 ,落实到我们设计的这个BP神经网络上来说,需要得到的是对w[Neuron][In] 和 v[Out][Neuron] 两个数据进行修正误差,误差量用数据结构 dw[Neuron][In]  和  dv[Out][Neuron]  来进行存储。那么来分析下这两个修正误差量是什么样的?推导的思路与基本模型中推导误差量的一致,这里仅列出对具体对于我们设计的BP神经网络中的数学推导过程:


如果你不想知道推导过程,那么只需要看上面中的两个 所以(有三个点的地方) 的内容,就可以知道所需要的误差量是什么样的了;如果想要想弄明白的话,或许需要自己在稿子上画画看推导推导。到这里完成了数学推导,实现的代码就很容易写了。在具体实现对误差修改中,我们再加上学习率,并且对先前学习到的修正误差量进行继承,直白的说就是都乘上一个0到1之间的数,具体的见如下实现参考代码:

#define A  0.2#define B  0.4#define a  0.2#define b  0.3

void backUpdate(int var){    int i,j;    double t;    for (i = 0; i < Neuron; ++i)    {        t=0;        for (j = 0; j < Out; ++j){            t+=(OutputData[j]-d_out[var][j])*v[j][i];            dv[j][i]=A*dv[j][i]+B*(OutputData[j]-d_out[var][j])*o[i];            v[j][i]-=dv[j][i];        }        for (j = 0; j < In; ++j){            dw[i][j]=a*dw[i][j]+b*t*o[i]*(1-o[i])*d_in[var][i];            w[i][j]-=dw[i][j];        }    }}

       好了,至此BP神经网络的C语言实现就全部完成了。最后,我们可以测试下BP神经网络的运行。我这里是这样给出数据的,两个输入a、b(10以内的数),一个输出 c,c=a+b。换句话说就是教BP神经网络加法运算。在 45个神经元,820个训练样例,样本平均误差小于0.01时完成训练(学习率等见参考代码)的条件下,最后预测 (6,8),(2.1,7),(4.3,8)实际输出结果如下:


最后附上参考实现代码,以及实验训练时的数据、和神经元信息。(本示例 仅为BP神经网络实现的 简单DEMO,若实际使用还需多加考虑!!!)

参考代码下载:

http://files.cnblogs.com/jzhlin/neuron.zip


阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 涂磊照片 涂磊身高 涂磊妻子 涂磊的老婆 涂磊资料 主持人涂磊 涂磊微薄 涂磊的节目 涂磊图片 涂磊名言 涂磊qq 涂磊 熊丹 涂磊 乐嘉 涂磊的综艺 涂磊说异地有三个阶段 涂磊经典语录 涂磊说人为什么要结婚 涂磊说一个男人三天不联系7天 涂磊说几种男人不能要 涂磊自爆自己离婚原因 涂磊老师解释贫贱夫妻百事哀 涂磊有几段婚姻 涂磊老婆熊丹个人资料 涂磊说夫妻分房睡那段话 爱情导师涂磊 涂磊说十种女人不能娶 涂磊说男人出轨不可怕 涂磊写给天下傻女人 涂磊婚姻忠告 涂磊批评婆婆语录 涂磊说男人打女人 涂磊婆媳问题经典语录 涂磊一家照片 涂磊谈守寡式婚姻 涂磊结过几次婚 涂磊老婆熊丹合照 涂磊个人资料 涂磊经典语录大全 涂磊联系方式 涂磊老婆熊丹照片 涂磊老师的联系方式