数据挖掘之人工神经网络BP算法

/*
人工神经网络BP算法思想: 神经网络一般分为3层(也可以多层),包括输入层,隐含层和输出层。通过有监督的学习拟合非线性函数。假如输入层有3个神经元,隐含层有5个神经元,输出层有1个神经元。有监督的学习是指既给了输入也给了输出再进行样本训练。可以把该神经网络看做3维向量的输入,一维的输出。每一层的神经元与相邻的一层的神经元全连接,同层的神经元不连接。
比如样本A的输入是{1,2,3},输出是{1},样本B的输入是{2,1,3},输出是{2},当然还有其他的样本,先通过前向传播得到神经元实际的输出值,计算期望值(即样本给的输出值)与输出值得均方误差,如果误差非常小,就不需要调整,否则反向传播调整连接权值(调整涉及到数学中的一些微分的知识)。直到拟合程度比较好时结束训练。此时有一个新的样本输入,不知道输出值,可以通过此神经网络预测输出值。
*/
#include<cstdio> #include<iostream> #include<cmath> #include<time.h> #include<fstream> #include<cstdlib> using namespace std; #define RANDOM rand()/32767.0 const int Layer_Max=5; /**神经网络层数**/ const double PI=3.1415927; /**圆周率**/ const int Layer_number[Layer_Max]={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); /**定义类BP**/ class BP{ public: 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(); double Cost(double out,double Exp); /**代价函数**/ private: double W[Layer_Max][Neural_Max][Neural_Max]; /**W[i][j][k]表示第i层第j个神经元连接到前一层第k个神经元**/ double Input_Net[2][InMax];/**表示第i个样本的输入x1,x2**/ double Out_Exp[InMax][InMax]; /**期望输出**/ double Layer_Node[Layer_Max][Neural_Max]; /**各神经元的输出**/ double D[Layer_Max][Neural_Max]; /**各神经元的误差微分**/ 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[i];j++){ for(int k=0;k<Layer_number[i-1]+1;k++) W[i][j][k]=RANDOM; /**权系数**/ //Q[i][j]=RANDOM; /**初始化各神经元阈值**/ } } /**输入和输出归一化**/ for(int l=0;l<InMax;l++){ /**输入的x1,x2**/ Input_Net[0][l]=l*0.05; Input_Net[1][l]=1-l*0.05; } for(int i=0;i<InMax;i++){ for(int j=0;j<InMax;j++){ Out_Exp[i][j]=Y(Input_Net[0][i],Input_Net[1][j]); /**期望输出**/ Out_Exp[i][j]=Out_Exp[i][j]/3.000000; /**归一化**/ } } Study_Speed=0.5; /**初始化学习度**/ e=0.0001; /**误差限制**/ } double BP::F(double x){ return (1.0/(1+exp(-x))); } /**Sigmoid函数**/ double BP::Y(double x1,double x2){ double temp; temp=pow(x1-1,4)+2*pow(x2,2); return temp; } /**代价函数**/ double BP::Cost(double Out,double Exp){ return (pow(Out-Exp,2)); /** 计算(Ok-dk)^2 **/ } double BP::NetWorkOut(int x1,int x2){ int i,j,k; double N_node[Layer_Max][Neural_Max];/**表示 第i层 第j个神经元 的总输入**/ /**第0层的神经元为输入,不用权系数和阈值**/ N_node[0][0]=Input_Net[0][x1]; Layer_Node[0][0]=Input_Net[0][x1]; N_node[0][1]=Input_Net[1][x2]; Layer_Node[0][1]=Input_Net[1][x2]; for(i=1;i<Layer_Max;i++){ for(j=0;j<Layer_number[i];j++){ N_node[i][j]=0.0; for(k=0;k<Layer_number[i-1];k++){ N_node[i][j]+=Layer_Node[i-1][k]*W[i][j][k]; } N_node[i][j]=N_node[i][j]-W[i][j][k]; /**减掉阈值**/ Layer_Node[i][j]=F(N_node[i][j]); /**得到输出**/ } } return Layer_Node[Layer_Max-1][0]; /**最后一层的输出**/ } void BP::AllLayer_D(int x1,int x2){ int i,j,k; double temp; D[Layer_Max-1][0]=Layer_Node[Layer_Max-1][0]*(1-Layer_Node[Layer_Max-1][0]) *(Layer_Node[Layer_Max-1][0]-Out_Exp[x1][x2]);/** Ok*(1-Ok)*(Ok-dk) **/ for(i=Layer_Max-1;i>0;i--){ for(j=0;j<Layer_number[i-1];j++){ temp=0; for(k=0;k<Layer_number[i];k++) temp=temp+W[i][k][j]*D[i][k];/****/ D[i-1][j]=Layer_Node[i-1][j]*(1-Layer_Node[i-1][j])*temp; } } } void BP::Change_W(){ int i,j,k; for(i=1;i<Layer_Max;i++){ for(j=0;j<Layer_number[i];j++){ for(k=0;k<Layer_number[i-1];k++){ W[i][j][k]=W[i][j][k]-Study_Speed*D[i][j]*Layer_Node[i-1][k]; } W[i][j][k]=W[i][j][k]+Study_Speed*D[i][j]; /** 修改阈值,相当于-(-1)*Study_Speed*D[i][j] **/ } } } 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); /**权系数变化保存在文件里**/ ofstream outWFile1("W[2][0][0].txt",ios::out); ofstream outWFile2("W[2][1][1].txt",ios::out); ofstream outWFile3("W[1][0][0].txt",ios::out); ofstream outWFile4("W[1][1][0].txt",ios::out); ofstream outWFile5("W[3][0][1].txt",ios::out); while(ok<441){ /**训练21*21个样本,当所有的误差精度都满足要求才退出**/ count++; 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[i][j]); /**计算误差**/ if(err<e) ok++; /**是否满足误差精度**/ else Change_W(); /**修改权系数**/ } } if(count%1000==0){ cout<<count<<" "<<err<<endl; Out_count<<count<<","; Out_Error<<err<<","; outWFile1<<W[2][0][0]<<","; outWFile2<<W[2][1][1]<<","; outWFile3<<W[1][0][0]<<","; outWFile4<<W[1][1][0]<<","; outWFile5<<W[3][0][1]<<","; for(int p=1;p<Layer_Max;p++){ for(int j=0;j<Layer_number[p];j++){ for(int k=0;k<Layer_number[p-1]+1;k++){ Out_W_File<<'W'<<'['<<p<<']' <<'['<<j<<']' <<'['<<k<<']' <<'='<<W[p][j][k]<<' '<<' '; } } } Out_W_File<<'\n'<<'\n'; } } cout<<err<<endl; } void BP::BP_Print(){ cout<<"训练后的权系数"<<endl; for(int i=1;i<Layer_Max;i++){ for(int j=0;j<Layer_number[i];j++){ for(int k=0;k<Layer_number[i-1]+1;k++) cout<<W[i][j][k]<<" "; cout<<endl; } } cout<<endl<<endl; } 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[0][i]<<","; Out_x22<<Input_Net[1][j]<<","; Result1<<3*NetWorkOut(i,j)<<","; Out_x1<<Input_Net[0][i]<<","; Array<<Input_Net[0][i]<<" "; Out_x2<<Input_Net[1][j]<<","; Array<<Input_Net[1][j]<<" "; Out_Net<<3*NetWorkOut(i,j)<<","; Array<<Y(Input_Net[0][i],Input_Net[1][j])<<" "; Out_Exp<<Y(Input_Net[0][i],Input_Net[1][j])<<","; 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[0][i]<<","; Out_x222<<Input_Net[1][j]<<","; Result2<<3*NetWorkOut(i,j)<<","; } Out_x111<<'\n'; Out_x222<<'\n'; Result2<<'\n'; } for(i=0;i<Layer_Max;i++){ for(j=0;j<Layer_number[i];j++){ for(int k=0;k<Layer_number[i-1]+1;k++) W_End<<W[i][j][k]<<","; } } } int main(void){ /* BP B; B.Train(); B.BP_Print(); B.After_Train_Out(); */ return 0; }

 

posted @ 2017-03-29 22:10  wust_ouyangli  阅读(1500)  评论(0编辑  收藏  举报