Bp神经网络算法

 

// BpNet.h: interface for the Bp class.
//  2006.8.8 by 曾志军 版权所有  
// E-Mail:[email protected]
//////////////////////////////////////////////////////////////////////
#include  " stdafx.h "
#include 
" BpNet.h "
#include 
" math.h "

#ifdef _DEBUG
#undef  THIS_FILE
static   char  THIS_FILE[] = __FILE__;
#define  new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
//  Construction/Destruction
//////////////////////////////////////////////////////////////////////

BpNet::BpNet()
{       
    error
=1.0;
    e
=0.0;
    
    rate_w
=0.05;  //权值学习率(输入层--隐含层)
    rate_w1=0.047//权值学习率 (隐含层--输出层)
    rate_b1=0.05//隐含层阀值学习率
    rate_b2=0.047//输出层阀值学习率
    error=1.0;
    e
=0.0;
    
    rate_w
=0.05;  //权值学习率(输入层--隐含层)
    rate_w1=0.047//权值学习率 (隐含层--输出层)
    rate_b1=0.05//隐含层阀值学习率
    rate_b2=0.047//输出层阀值学习率
}


BpNet::
~ BpNet()
{
    
}


void  winit( double  w[], int  sl) // 权值初始化
{int i;
double randx();
for(i=0;i<sl;i++){
    
*(w+i)=0.2*randx();
}

}


double  randx() // kqy error
{double d;
d
=(double) rand()/32767.0;
return d;
}


void  BpNet::init()
{
    winit((
double*)w,innode*hidenode);
    winit((
double*)w1,hidenode*outnode);
    winit(b1,hidenode);
    winit(b2,outnode);
}



void  BpNet::train( double  p[trainsample][innode], double  t[trainsample][outnode])
{
    
double pp[hidenode];//隐含结点的校正误差
    double qq[outnode];//希望输出值与实际输出值的偏差
    double yd[outnode];//希望输出值
    
    
double x[innode]; //输入向量
    double x1[hidenode];//隐含结点状态值
    double x2[outnode];//输出结点状态值
    double o1[hidenode];//隐含层激活值
    double o2[hidenode];//输出层激活值
    for(int isamp=0;isamp<trainsample;isamp++)//循环训练一次样品
    
        
for(int i=0;i<innode;i++)
            x[i]
=p[isamp][i];
        
for(i=0;i<outnode;i++)
            yd[i]
=t[isamp][i];
        
        
//构造每个样品的输入和输出标准
        for(int j=0;j<hidenode;j++)
        
{
            o1[j]
=0.0;
            
            
for(i=0;i<innode;i++)
                o1[j]
=o1[j]+w[i][j]*x[i];//隐含层各单元输入激活值
            x1[j]=1.0/(1+exp(-o1[j]-b1[j]));//隐含层各单元的输出kqy1
            
//    if(o1[j]+b1[j]>0) x1[j]=1;
            
//else x1[j]=0;
        }

        
        
for(int k=0;k<outnode;k++)
        
{
            o2[k]
=0.0;
            
            
for(j=0;j<hidenode;j++)
                o2[k]
=o2[k]+w1[j][k]*x1[j];//输出层各单元输入激活值
            x2[k]=1.0/(1.0+exp(-o2[k]-b2[k]));//输出层各单元输出
            
//    if(o2[k]+b2[k]>0) x2[k]=1;
            
//    else x2[k]=0;
        }

        
        
for(k=0;k<outnode;k++)
        
{
            e
=0.0;
            qq[k]
=(yd[k]-x2[k])*x2[k]*(1.-x2[k]);//希望输出与实际输出的偏差
            e+=fabs(yd[k]-x2[k])*fabs(yd[k]-x2[k]);//计算均方差
            
            
for(j=0;j<hidenode;j++)
                w1[j][k]
=w1[j][k]+rate_w1*qq[k]*x1[j];//下一次的隐含层和输出层之间的新连接权
            e=sqrt(e);
            error
=e;
        
        }

        
        
for(j=0;j<hidenode;j++)
        
{
            pp[j]
=0.0;
            
for(k=0;k<outnode;k++)
                pp[j]
=pp[j]+qq[k]*w1[j][k];
            pp[j]
=pp[j]*x1[j]*(1-x1[j]);//隐含层的校正误差
            
            
for(i=0;i<innode;i++)
                w[i][j]
=w[i][j]+rate_w*pp[j]*x[i];//下一次的输入层和隐含层之间的新连接权
        }

        
        
for(k=0;k<outnode;k++)
            b2[k]
=b2[k]+rate_b2*qq[k];//下一次的隐含层和输出层之间的新阈值
        for(j=0;j<hidenode;j++)
            b1[j]
=b1[j]+rate_b1*pp[j];//下一次的输入层和隐含层之间的新阈值
        
    }
//end isamp样品循环
    
}

///////////////////////////end train/////////////////////////////

/////////////////////////////////////////////////////////////////


double   * BpNet::recognize( double   * p)
{   
    
double x[innode]; //输入向量
    double x1[hidenode];//隐含结点状态值
    double x2[outnode];//输出结点状态值
    double o1[hidenode];//隐含层激活值
    double o2[hidenode];//输出层激活值

    
for(int i=0;i<innode;i++)
        x[i]
=p[i];
    
for(int j=0;j<hidenode;j++)
    
{
        o1[j]
=0.0;
        
        
for(int i=0;i<innode;i++)
            o1[j]
=o1[j]+w[i][j]*x[i];//隐含层各单元激活值
        x1[j]=1.0/(1.0+exp(-o1[j]-b1[j]));//隐含层各单元输出
        
//if(o1[j]+b1[j]>0) x1[j]=1;
        
//    else x1[j]=0;
    }

    
    
for(int k=0;k<outnode;k++)
    
{
        o2[k]
=0.0;
        
for(int j=0;j<hidenode;j++)
            o2[k]
=o2[k]+w1[j][k]*x1[j];//输出层各单元激活值
        x2[k]=1.0/(1.0+exp(-o2[k]-b2[k]));//输出层各单元输出
        
//if(o2[k]+b2[k]>0) x2[k]=1;
        
//else x2[k]=0;
    }
 
    
    
for(k=0;k<outnode;k++)
    
{
        shuchu[k]
=x2[k];
    }
 
    
return shuchu;
}
////////////////////////////end sim///////////////////////////

void  BpNet::writetrain()
{//曾志军 for 2006.7
    AfxMessageBox("你还没有训练呢,训练后再写吧!请不要乱写,除非你认为这次训练是最好的,否则会覆盖我训练好的权值,那样你又要花时间训练!");
    AfxMessageBox(
"你认为这次训练结果是最好的,就存下来,下次就不要花时间训练了!",MB_YESNO,NULL);
    FILE 
*stream0;
    FILE 
*stream1;
    FILE 
*stream2;
    FILE 
*stream3;
    
int i,j;
    
////////////////////////
    if(( stream0 = fopen("w.txt""w+" ))==NULL)
    
{
        AfxMessageBox(
"创建文件失败!");
    }

    
for(i=0;i<innode;i++)
    
{
        
for(j=0;j<hidenode;j++)
        
{
            
            fprintf(stream0, 
"%f\n", w[i][j]);
        }

        
    }

    fclose( stream0);
    
///////////////////////////////////
    if(( stream1 = fopen("w1.txt""w+" ))==NULL)
    
{
        AfxMessageBox(
"创建文件失败!");
    }

    
for(i=0;i<hidenode;i++)
    
{
        
for(j=0;j<outnode;j++)
        
{
            fprintf(stream1, 
"%f\n",w1[i][j]);
        }

        
    }

    fclose( stream1);
    
////////////////////////////
    if(( stream2 = fopen("b1.txt""w+" ))==NULL)
    
{
        AfxMessageBox(
"创建文件失败!");
    }

        
for(i=0;i<hidenode;i++)
    
{
        fprintf(stream2, 
"%f\n",b1[i]);
        
        
    }

    fclose( stream2);
    
/////////////////////////
    if(( stream3 = fopen("b2.txt""w+" ))==NULL)
    
{
        AfxMessageBox(
"创建文件失败!");
    }

    
for(i=0;i<outnode;i++)
    
{
        fprintf(stream3, 
"%f\n",b2[i]);
        
        
    }

    fclose( stream3);
    
    
}



void  BpNet::readtrain()
{
    
//曾志军 for 2006.7
    AfxMessageBox("读入已训练好的权值,这样你就不要花时间训练了!",MB_YESNO,NULL);
    FILE 
*stream0;
    FILE 
*stream1;
    FILE 
*stream2;
    FILE 
*stream3;
    
int i,j;
    
/////////////////
    if(( stream0 = fopen("w.txt""r" ))==NULL)
    
{
        AfxMessageBox(
"文件不存在,请先写入权值,再读!");
    }

    
    
float  wx[innode][hidenode];
    
for(i=0;i<innode;i++)
        
for(j=0;j<hidenode;j++)
        
{
            fscanf(stream0, 
"%f"&wx[i][j]);
            w[i][j]
=wx[i][j];
        }

    fclose( stream0);
    
///////////////////////////////////////////////    
    if(( stream1 = fopen("w1.txt""r" ))==NULL)
        
{
            AfxMessageBox(
"文件不存在,请先写入权值,再读!");
        }

         
float  wx1[hidenode][outnode]; 
        
for(i=0;i<hidenode;i++)
        
{
            
for(j=0;j<outnode;j++)
            
{
                fscanf(stream1, 
"%f"&wx1[i][j]);
                w1[i][j]
=wx1[i][j];
            }

            
        }

        fclose( stream1);
        
        
///////////////////
        if(( stream2 = fopen("b1.txt""r" ))==NULL)
        
{
            AfxMessageBox(
"文件不存在,请先写入权值,再读!");
        }

        
float xb1[hidenode];    
        
for(i=0;i<hidenode;i++)
        
{
            fscanf(stream2, 
"%f",&xb1[i]);
            b1[i]
=xb1[i];
        }

        fclose( stream2);
        
//////////////////////////
        if(( stream3 = fopen("b2.txt""r" ))==NULL)
        
{
            AfxMessageBox(
"文件不存在,请先写入权值,再读!");
        }

        
float xb2[outnode];  
        
for(i=0;i<outnode;i++)
        
{
            fscanf(stream3, 
"%f",&xb2[i]);
            b2[i]
=xb2[i];
        }

        
        fclose( stream3);
        
/*CFile TheFile("w.txt",CFile::modeRead);
        CArchive ar(&TheFile,CArchive::load,40960);
        TheFile.SeekToBegin();
        int i,j;
        for(i=0;i<innode;i++)
        {
        for(j=0;j<hidenode;j++)
        {   
        ar>>w[i][j];
        
          }
          
            }
            ar.Close();
        TheFile.Close();
*/

        
}

// BpNet.h: interface for the Bp class.
//  2006.8.8 by 曾志军 版权所有  
// E-Mail:[email protected]
//////////////////////////////////////////////////////////////////////

#if  !defined(AFX_BPNET_H__3A171E41_1E8B_11D7_BA67_936006E9954B__INCLUDED_)
#define  AFX_BPNET_H__3A171E41_1E8B_11D7_BA67_936006E9954B__INCLUDED_

#if  _MSC_VER > 1000
#pragma  once
#endif   //  _MSC_VER > 1000


#define   innode 5   // 输入结点数
#define   hidenode 10 // 隐含结点数
#define   outnode 4  // 输出结点数
#define   trainsample 500 // BP训练样本为10个
class  BpNet  
{
public:
    
void train(double p[trainsample][innode ],double t[trainsample][outnode]);//Bp训练
    
//double p[trainsample][innode]     //输入的样本
    
//double t[trainsample][outnode]//样本要输出的
    
//Bp训练前要调用readtemplate()
    double *recognize(double *p);//Bp识别
    
    
void writetrain();//写训练完的权值
    void readtrain();//读训练好的权值,这使的不用每次去训练了,只要把训练最好的权值存下来writetrain()就OK!
    
    BpNet();
    
virtual ~BpNet();


public:
    
void init();
    
double w[innode][hidenode];//隐含结点权值
    double w1[hidenode][outnode];//输出结点权值
    double b1[hidenode];//隐含结点阀值
    double b2[outnode];//输出结点阀值
    
    
double rate_w; //权值学习率(输入层-隐含层)
    double rate_w1;//权值学习率 (隐含层-输出层)
    double rate_b1;//隐含层阀值学习率
    double rate_b2;//输出层阀值学习率

    
    
double e;//误差计算
    double error;//允许的最大误差
    double shuchu[outnode];// Bp输出
    

}
;

#endif   //  !defined(AFX_BPNET_H__3A171E41_1E8B_11D7_BA67_936006E9954B__INCLUDED_)

你可能感兴趣的:(算法)