📄 long-bp.cpp
字号:
/*********** universal BP algorithm ***********
*********** dglag@163.com ***********/
#include "iostream.h"
#include "iomanip.h"
#include "stdlib.h"
#include "math.h"
#include "stdio.h"
#include "time.h"
#include "fstream.h"
/* definition of user data */
int N;//学习样本个数
int M;//神经网络层数
int note[10];//各层的节点数,层数一般小于10
/*定义一个输入输出结构*/
struct individual{
double input[50]; //输入小于50个
double teach[50]; //输出小于50个
};
/* definition of global variables */
double W[50][10][50];//权值
double YU[50][10];//阈值
double X[200][10][50];//每个样本各层的输出,设样本数小于200
double a=0.6; //学习效率
struct individual Study_Data[200];//N个学习样本
double pre_error;//预定误差
/* function prototype */
void talk();//与用户交谈
void initial();//初始化权、阈值
void GetTrainingData();//从txt中读取样本数据
void IO_process();//计算各层输出
void adjust();//调整权、阈值
double Err_Sum();//计算总的误差
void savevalue();//储存权、阈值
/* main program */
int main()
{
double sum_err;
int study=0;//训练次数
srand(static_cast<unsigned>(time(static_cast<time_t *>(NULL))));//随机数种子
talk();
GetTrainingData();
initial();
do
{
IO_process();
adjust();
study++;
sum_err=Err_Sum(); //全部样本全局误差计算
cout<<"第"<<study<<"次学习的均方误差为"<<sum_err<<endl;
}while (sum_err>pre_error);
cout<<"网络已经学习了"<<study<<"次,学习的均方误差为"<<sum_err<<endl;
savevalue();
return 0;
}
/* 与用户交谈 */
void talk()
{
cout<<"请输入您需要的神经网络层数: ";
cin>>M;
cout<<"请输入您需要的各层的节点数(依次从输入到输出层,空格隔开): ";
for(int i=0;i<M;i++)
cin>>note[i];
cout<<"请确保学习样本已存入“学习样本.txt”,并输入学习样本的个数: ";
cin>>N;
cout<<"请输入您需要的预定精度: ";
cin>>pre_error;
cout<<"学习中....... "<<endl;
}
/* 初始化权、阈值 */
void initial()
{
double random_0_1;
int q,i,j;
for(q=0;q<M-1;q++)
{
for(i=0;i<note[q+1];i++)
{
for(j=0;j<note[q];j++)
{
random_0_1=rand()/static_cast<double>(RAND_MAX);//[0.0,1]间
W[i][q][j]=2.0*random_0_1-1.0; //初始化所有的权值,[-1.0,1.0]
}
}
}
for(q=0;q<M-1;q++)
{
for(i=0;i<note[q+1];i++)
{
random_0_1=rand()/static_cast<double>(RAND_MAX);//[0.0,1]间
YU[i][q]=2.0*random_0_1-1.0; //阈值初始化 ,[-1.0,1.0]
}
}
}
/* 从txt中读取样本数据 */
void GetTrainingData()
{
ifstream GetTrainingData ( "训练样本.txt", ios::in );
for(int m=0;m<N;m++)
{
for(int i=0;i<note[0];i++)
{
GetTrainingData>>Study_Data[m].input[i]; //取得输入数据
}
for(int j=0;j<note[M-1];j++)
{
GetTrainingData>>Study_Data[m].teach[j]; //取得输出数据
}
}
GetTrainingData.close();
}
/* 计算各层输出 */
void IO_process()
{
double sigma1;
double sigma2;
int i,m,q,h;
//X[200][10][50]
for(m=0;m<N;m++)
{
for(i=0;i<note[0];i++)
X[m][0][i]=Study_Data[m].input[i];//第0层输入即输出
for(q=1;q<M;q++)
{
for(i=0;i<note[q];i++)
{
sigma1=0;
for(h=0;h<note[q-1];h++)
{
sigma1+=X[m][q-1][h]*W[i][q-1][h];
}
sigma2=sigma1-YU[i][q-1];
X[m][q][i]=1.0/(1.0+exp(-sigma2));
}
}
}
}
/* 调整权、阈值 */
void adjust()
{
double delta[200][10][50];
int i,j,k,h,m,q;
for(m=0;m<N;m++)
{
for(h=0;h<note[M-1];h++)
delta[m][M-1][h]=(Study_Data[m].teach[h]-X[m][M-1][h])*X[m][M-1][h]*(1-X[m][M-1][h]);
for(j=M-2;j>0;j--)
{
for(i=0;i<note[j];i++)
{
delta[m][j][i]=0;
for(k=0;k<note[j+1];k++)
delta[m][j][i]+=delta[m][j+1][k]*W[k][j][i]*X[m][j][i]*(1-X[m][j][i]);
}
}
}
for(q=0;q<M-1;q++)
{
for(i=0;i<note[q+1];i++)
{
for(j=0;j<note[q];j++)
{
for(m=0;m<N;m++)
{
W[i][q][j]+=a*delta[m][q+1][i]*X[m][q][j];//权值调整
}
}
}
}
for(q=0;q<M-1;q++)
{
for(i=0;i<note[q+1];i++)
{
for(m=0;m<N;m++)
{
YU[i][q]-=a*delta[m][q+1][i];//阈值调整
}
}
}
}
/* 计算总的误差 */
double Err_Sum()
{
double s_err=0;
int m,h;
for(m=0;m<N;m++)
{
for(h=0;h<note[M-1];h++)
{
s_err+=(Study_Data[m].teach[h]-X[m][M-1][h])*(Study_Data[m].teach[h]-X[m][M-1][h])/2;
}
}
return s_err;
}
/* 储存权、阈值 */
void savevalue()
{
ofstream outQuanFile( "权值.txt", ios::out );
ofstream outYuFile( "阈值.txt", ios::out );
outQuanFile<<"W[i][q][j]:第q层j指向i的权,\n";
for(int q=0;q<M-1;q++)
{
for(int j=0;j<note[q];j++)
{
outQuanFile<<"\n"<<"q="<<q<<","<<"j="<<j<<":"<<endl;
for(int i=0;i<note[q+1];i++)
{
outQuanFile<<W[i][q][j]<<" ";
}
}
outQuanFile<<"\n";
}
outYuFile<<"各层的阈值为YU[i][q](第q+1层第i个阈值):\n";
for(int qq=0;qq<M-1;qq++)
{
outYuFile<<"\n"<<"第"<<qq+1<<"层:"<<endl;
for(int ii=0;ii<note[qq+1];ii++)
{
outYuFile<<YU[ii][qq]<<" "; //输出层阈值写入文本
}
}
outQuanFile.close();
outYuFile.close();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -