BP神经网络详解程序员

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, '--')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

这是用C语言写的:用BP神经网络拟合函数:Y=sin(X)

#include "math.h" http://xwfkvpuohb.inuobi.com/ http://eazjpwcwck.inuobi.com/ http://dosxqxqxrz.inuobi.com/ 
#include "time.h" http://qqntzzysaj.inuobi.com/ http://kmsldxdwqc.inuobi.com/ http://dvvoazbopb.inuobi.com/ 
#include "stdio.h" 
#include "stdlib.h" 
#include "ctype.h" 
#define Ni 1 http://jgskbshnut.inuobi.com/ http://ztvcvoevoh.inuobi.com/ http://mbwchbhavw.inuobi.com/ 
#define Nm 4 
#define No 1 
#define L 100 
#define Enom 0.02 
#define loopmax 100000 
#define e 2.71828 
double E; http://azewozrwpw.inuobi.com/ http://bmyqwdbuoi.inuobi.com/ http://tdknewayqw.inuobi.com/ 
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(); http://qbaxpvohav.inuobi.com/ http://qdalgpxksc.inuobi.com/ http://zjsyqqwpwd.inuobi.com/ 
void proceedR(); 
void forQ(); http://gpmrkkdwqz.inuobi.com/ http://jnmiahgmut.inuobi.com/ http://gvgtysrxdy.inuobi.com/ 
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(;;) 
    { http://tcpitghqam.inuobi.com/ http://qdpwovtwzg.inuobi.com/ http://kurbhbhaho.inuobi.com/ 
        flag=0; 
        initiate(); 
        for(i=0;;i++) 
        { http://cgglchfwcw.inuobi.com/ http://cgcunuatnm.inuobi.com/ http://dalttpynqz.inuobi.com/ 
            proceed(); 
            if( E < Enom ) 
            {  http://yielzjsolb.inuobi.com/ http://bxhafntmxt.inuobi.com/ http://wxxlpydows.inuobi.com/ 
                flag=1; 
                break; 
            } 
            if( i >= loopmax) 
            { http://jrpibohovf.inuobi.com/ http://thbcjqjhaj.inuobi.com/ http://cwhzkdjcvr.inuobi.com/ 
                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(;;) 
        { http://kkxszddkdy.inuobi.com/ http://ccqilpfqwf.inuobi.com/ http://qdnewpuzrb.inuobi.com/ 
            choice=getchar(); 
            printf("是否继续?(Y/N)/n"); 
            choice=getchar(); 
            choice=toupper(choice); 
            if(choice=='Y')break; 
            if(choice=='N')exit(0); 
        } 
    } 
} 
void initiate() 
{ http://qmjphgmslu.inuobi.com/ http://kwgnwrwcwk.inuobi.com/ http://itloiacgki.inuobi.com/ 
    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++) 
    { http://enpunfydks.inuobi.com/ http://rclochbdhn.inuobi.com/ http://vuuwlcxzdi.inuobi.com/ 
        for( j=0; j<Ni; j++) 
        { http://gwggsserdi.inuobi.com/ http://kywbubzfzi.inuobi.com/ http://jgskqxdpif.inuobi.com/ 
            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++) 
        { http://xbdoipioir.inuobi.com/ http://ultyyobchc.inuobi.com/ http://euintzrwuq.inuobi.com/ 
            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++) 
    { http://ezjohoufmu.inuobi.com/ http://qiuafrkdxe.inuobi.com/ http://hdbgzydjdx.inuobi.com/ 
        x=i; 
        Pi[i][0]=x*step; 
        T[i][0]=sin(Pi[i][0]); 
    } 
    printf("初始化成功!/n/n下面将对神经网络进行训练请稍候。/n"); 
} 
void proceed() 
{ http://npyejwbhnj.inuobi.com/ http://omvaysyrlt.inuobi.com/ http://cpllfcxghq.inuobi.com/ 
    int i, j, k; 
    E=0 ; 
    for( i=0; i<L; i++ ) 
    { http://dutdjqwpje.inuobi.com/ http://btdwojpngq.inuobi.com/ http://kvdvnhexrm.inuobi.com/ 
        for( j=0; j<Nm; j++ ) 
        { http://hfhzfmsmso.inuobi.com/ http://fqbhzhmgnz.inuobi.com/ http://potmrlwpje.inuobi.com/ 
            Pm[i][j] = 0; 
            for( k=0; k<Ni; k++ ) 
            { http://cllibhagzh.inuobi.com/ http://czpauivhuh.inuobi.com/ http://qwhlpvnfvs.inuobi.com/ 
                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++) 
        { http://glsniobxbo.inuobi.com/ http://hvamzktcmh.inuobi.com/ http://cirxpxvovd.inuobi.com/ 
            Po[i][j] = 0; 
            for( k=0; k<Nm; k++) 
            { http://urkxvwjvet.inuobi.com/ http://azatltmfzp.inuobi.com/ http://vqyzbwmorv.inuobi.com/ 
                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() 
{ http://kpyqjekdwz.inuobi.com/ http://zrqiaitivm.inuobi.com/ http://acevmchsmx.inuobi.com/ 
    int i,j,k; 
    for( i=0; i<L; i++ ) 
    { http://lezdjqvapr.inuobi.com/ http://yzzltdzcqy.inuobi.com/ http://yzjbgohflg.inuobi.com/ 
        for( j=0; j<No; j++) 
        { http://ifshgjyqjr.inuobi.com/ http://khgbskbtki.inuobi.com/ 
            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 ); 
} 

BP神经网络详解程序员

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/7384.html

(0)
上一篇 2021年7月17日
下一篇 2021年7月17日

相关推荐

发表回复

登录后才能评论