173806613 发表于 2013-1-30 20:45:59

BP算法

//---------------------------------------------------------------------------------------////         BP算法例子:用一个五层的神经网络去逼近函数            ////         f(x1,x2)=pow(x1-1,4)+2*pow(x2,2)                                       ////                                 作者:MaxMatrix                                             ////                                 2004.5.9调通 运行于VC++6.0                     ////--------------------------------------------------------------------------------------//#include<iostream.h>#include<math.h>#include<stdlib.h>#include<time.h>#include<fstream.h>//---------------------------------------------------------------------#define RANDOM rand()/32767.0//0~1随机数生成函数   const int Layer_Max=5;//神经网络的层数const double PI=3.1415927;//圆周率const int Layer_number={2,4,4,2,1};//神经网络各层的神经元个数const int Neural_Max=4;//神经网络各层最大神经元个数const int InMax=21;//样本输入的个数ofstream Out_W_File("All_W.txt",ios::out) ;ofstream Out_Error("Error.txt",ios::out) ;//定义类 BPclass BP{public: BP(); //BP类的构造函数 void BP_Print();//打印权系数 double F(double x);//神经元的激发函数 double Y(double x1,double x2);//要逼近的函数                               //double NetWorkOut(int x1 , int x2);//网络输出,他的输入为                              //第input个样本 void AllLayer_D(int x1 , int x2);//求所有神经元的输出误差微分void Change_W();   //改变权系数   void Train();   //训练函数 void After_Train_Out(); //经过训练后,21样本的神经网络输出 double Cost(double out,double Exp);//代价函数private: double W;//保存权系数      //规定W表示网络第i层的第j个神经元连接到      //第i-1层第k个神经元的权系数 double Input_Net;//21个样本输入,约定Input_Net                            //表示第i个样本的输入x1                            //而 Input_Net表示第i个样本的输入x2 double Out_Exp;//期望输出double Layer_Node;//保存各神经元的输出   //规定Layer_Node表示第i层的第j个神经元的输出 double D;//保存各神经元的误差微分   //规定D表示第i层第j个神经元的误差微分 double Study_Speed;//学习速度double e;//误差};//构造函数,用来初始化权系数,输入,期望输出和学习速度BP::BP(){ srand(time(NULL));//播种,以便产生随即数 for(int i=1 ; i<Layer_Max ; i++) {for(int j=0 ; j<Layer_number ; j++){      for(int k=0 ; k<Layer_number+1 ; k++)   {    W = RANDOM;//随机初始化权系数       }//   Q = RANDOM ;//初始化各神经元的阀值} }//输入归和输出归一化 for(int l=0 ; l<InMax ; l++) {Input_Net = l * 0.05 ;//把0~1分成20等分,表示x1Input_Net = 1 - l * 0.05 ;//表示x2 } for(i=0 ; i<InMax ; i++) {for(int j=0 ; j<InMax ; j++){   Out_Exp = Y(Input_Net,Input_Net) ;//期望输出      Out_Exp = Out_Exp/3.000000;//期望输出归一化} }Study_Speed=0.5;//初始化学习速度e=0.0001;//误差精度   }//end//激发函数F()double BP::F(double x){ return(1.0/(1+exp(-x)));}//end//要逼近的函数Y()//输入:两个浮点数//输出:一个浮点数double BP::Y(double x1,double x2){ double temp; temp = pow(x1-1,4) + 2 * pow(x2,2); return temp;}//end//--------------------------------------------------------//代价函数double BP::Cost(double Out,double Exp){ return(pow(Out-Exp,2));}//end//网络输出函数//输入为:第input个样本double BP::NetWorkOut(int x1 , int x2){ int i,j,k; double N_node;    //约定N_node表示网络第i层的第j个神经元的总输入 //第0层的神经元为输入,不用权系数和阀值,即输进什么即输出什么 N_node = Input_Net ; Layer_Node = Input_Net ; N_node = Input_Net ; Layer_Node = Input_Net ; for(i=1 ; i<Layer_Max ; i++)//神经网络的第i层 {for(j=0 ; j<Layer_number ; j++)//Layer_number为第i层的{                           //神经元个数            N_node = 0.0;   for(k=0 ; k<Layer_number ; k++)//Layer_number   {            //表示与第i层第j个神经元连接的上一层的             //神经元个数      //求上一层神经元对第i层第j个神经元的输入之和    N_node+=Layer_Node * W;       }   N_node = N_node-W;//减去阀值   //求Layer_Node,即第i层第j个神经元的输出   Layer_Node = F(N_node);} } return Layer_Node;//最后一层的输出}//end//求所有神经元的输出误差微分函数//输入为:第input个样本//计算误差微分并保存在D[][]数组中void BP::AllLayer_D(int x1 , int x2){ int i,j,k; double temp; D = Layer_Node *                  (1-Layer_Node)*                  (Layer_Node-Out_Exp); for(i=Layer_Max-1 ; i>0 ; i--) {for(j=0 ; j<Layer_number ; j++){   temp = 0 ;   for(k=0 ; k<Layer_number ; k++)   {    temp = temp+W*D ;   }   D = Layer_Node * (1-Layer_Node)            *temp ;} }}//end//修改权系数和阀值void BP::Change_W(){ int i,j,k; for(i=1 ; i<Layer_Max ; i++) {for(j=0;j<Layer_number;j++){   for(k=0;k<Layer_number;k++)   {    //修改权系数    W=W-Study_Speed*            D*Layer_Node;                  }   W=W+Study_Speed*D;//修改阀值} }}//end//训练函数void BP::Train(){ int i,j; int ok=0; double Out; long int count=0; double err;    ofstream Out_count("Out_count.txt",ios::out) ; //把其中的5个权系数的变化保存到文件里 ofstream outWFile1("W.txt",ios::out) ; ofstream outWFile2("W.txt",ios::out) ; ofstream outWFile3("W.txt",ios::out) ; ofstream outWFile4("W.txt",ios::out) ; ofstream outWFile5("W.txt",ios::out) ; while(ok<441) {count++;//20个样本输入for(i=0,ok=0 ; i<InMax ; i++){   for(j=0 ; j<InMax ; j++)   {      Out = NetWorkOut(i,j);      AllLayer_D(i,j);         err = Cost(Out,Out_Exp);//计算误差                  if(err<e) ok++;//是否满足误差精度       else Change_W();//否修改权系数和阀值   }         }if((count%1000)==0)//每1000次,保存权系数{   cout<<count<<"   "<<err<<endl;   Out_count<<count<<"," ;   Out_Error<<err<<"," ;   outWFile1<<W<<"," ;   outWFile2<<W<<"," ;   outWFile3<<W<<"," ;   outWFile4<<W<<"," ;   outWFile5<<W<<"," ;   for(int p=1 ; p<Layer_Max ; p++)   {    for(int j=0 ; j<Layer_number ; j++)    {   for(int k=0 ; k<Layer_number+1 ; k++)   {      Out_W_File<<'W'<<'['<<p<<']'                  <<'['<<j<<']'            <<'['<<k<<']'            <<'='<<W<<' '<<' ';   }    }   }   Out_W_File<<'\n'<<'\n' ;} } cout<<err<<endl;}//end//打印权系数void BP::BP_Print(){ //打印权系数 cout<<"训练后的权系数"<<endl; for(int i=1 ; i<Layer_Max ; i++) {for(int j=0 ; j<Layer_number ; j++){      for(int k=0 ; k<Layer_number+1 ; k++)   {    cout<<W<<"         ";   }   cout<<endl;} } cout<<endl<<endl;}//end//把结果保存到文件void BP::After_Train_Out(){ int i,j ; ofstream Out_x1("Out_x1.txt",ios::out) ;ofstream Out_x2("Out_x2.txt",ios::out) ;ofstream Out_Net("Out_Net.txt",ios::out) ;ofstream Out_Exp("Out_Exp.txt",ios::out) ; ofstream W_End("W_End.txt",ios::out) ; ofstream Q_End("Q_End.txt",ios::out) ; ofstream Array("Array.txt",ios::out) ; ofstream Out_x11("x1.txt",ios::out) ; ofstream Out_x22("x2.txt",ios::out) ; ofstream Result1("result1.txt",ios::out) ; ofstream Out_x111("x11.txt",ios::out) ; ofstream Out_x222("x22.txt",ios::out) ; ofstream Result2("result2.txt",ios::out) ;for( i=0 ; i<InMax ; i++) {for(j=0 ; j<InMax ; j++){   Out_x11<<Input_Net<<',';   Out_x22<<Input_Net<<"," ;   Result1<<3*NetWorkOut(i,j)<<"," ;   Out_x1<<Input_Net<<"," ;   Array<<Input_Net<<"      " ;      Out_x2<<Input_Net<<"," ;   Array<<Input_Net<<"      " ;      Out_Net<<3*NetWorkOut(i,j)<<"," ;   Array<<Y(Input_Net,Input_Net)<<"      " ;      Out_Exp<<Y(Input_Net,Input_Net)<<"," ;   Array<<3*NetWorkOut(i,j)<<"      " ;   Array<<'\n' ;}Out_x1<<'\n' ;Out_x2<<'\n' ;Out_x11<<'\n';Out_x22<<'\n';Result1<<'\n' ;   } for(j=0 ; j<InMax ; j++) {for(i=0 ; i<InMax ; i++){   Out_x111<<Input_Net<<',';   Out_x222<<Input_Net<<"," ;   Result2<<3*NetWorkOut(i,j)<<"," ;}Out_x111<<'\n';Out_x222<<'\n' ;Result2<<'\n' ; }    //把经过训练后的权系数和阀值保存到文件里    for(i=1 ; i<Layer_Max ; i++) {for(int j=0 ; j<Layer_number ; j++){      for(int k=0 ; k<Layer_number+1 ; k++)   {       W_End<<W<<"," ;//保存权系数   }} }//end for    }//endvoid main(void){    BP B;//生成一个BP类对象B B.Train();//开始训练 B.BP_Print();//把结果打印出来 B.After_Train_Out();//把结果保存到文件}//end
页: [1]
查看完整版本: BP算法