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]