📄 bp.cpp
字号:
#include "iostream.h"
#include "iomanip.h"
#include <math.h>
#include "stdio.h"
#include <stdlib.h>
#include "stdafx.h"
#include "IniFile.h"
#define MAX 100
int n; //学习样本个数
int in; //输入层神经元数目
int hn; //隐层神经元数目
int on; //输出层神经元数目
double alpha; //输出层至隐层的学习效率
double beta; //隐层至输入层学习效率
double P[MAX]; //单个样本输入数据
double T[MAX]; //单个样本教师数据
double W[MAX][MAX]; //输入层至隐层权值
double V[MAX][MAX]; //隐层至输出层权值
double X[MAX]; //隐层的输入
double Y[MAX]; //输出层的输入
double H[MAX]; //隐层的输出
double O[MAX]; //输出层的输出
double sita[MAX]; //隐层的阈值
double gama[MAX]; //输出层的阈值
double err_m[MAX]; //第m个样本的总误差
FILE *fp=fopen("bp.log","a+");
//定义一个放学习样本的结构
struct {
double input[MAX];
double teach[MAX];
}Study_Data[MAX][MAX];
//初始化权、阈值
initial()
{
float rnd;
int i,j;
cout<<"---------开始初始化------------------\n";
cout<<"随机产生的权值\n";
//隐层权、阈值初始化
for (j=0;j<hn;j++)
{
for (i=0;i<in;i++)
{
rnd=rand()%10000;
W[j][i]= rnd/10000; //隐层权值初始化。
cout<<"W[][]:"<<W[j][i]<<endl;
}
rnd=rand()%10000;
sita[j]= rnd/10000; //中间层阈值初始化
//sita[j]=0;
//cout<<"第"<<j+1<<"个sita:"<<sita[j]<<endl;
}
cout<<"随机产生的权值\n";
//输出层权、阈值初始化
for (int k=0;k<on;k++)
{
for (int j=0;j<hn;j++)
{
rnd=rand()%10000;
V[k][j]=rnd/10000; //第m个样本输出层权值初始化
cout<<"V[][]:"<<V[k][j]<<endl;
}
rnd=rand()%10000;
gama[k]=rnd/10000; //输出层阈值初始化
//gama[k]=0;
//cout<<"第"<<k+1<<"个gama:"<<gama[k]<<endl;
}
cout<<"---------初始化结束------------------\n";
return 1;
}
//第m个学习样本输入
input_P(int m)
{
for (int i=0;i<in;i++)
P[i]=Study_Data[m]->input[i];
return 1;
}
//第m个样本教师信号
input_T(int m)
{
for (int k=0;k<on;k++)
T[k]=Study_Data[m]->teach[k];
return 1;
}
//隐层各单元输入、输出值
H_I_O()
{
double sigma;
int i,j;
for (j=0;j<hn;j++)
{
sigma=0.0;
for (i=0;i<in;i++)
{
sigma+=W[j][i]*P[i]; //求隐层内积
}
X[j]=sigma + sita[j]; //求隐层净输入
//cout<<"sigma:"<<sigma<<"\n";
//cout<<"隐层净输入X[]:"<<X[j]<<"\n";
H[j]=1.0/(1.0+exp(-X[j])); //求隐层输出
//cout<<"隐层输出H[]:"<<H[j]<<"\n";
}
return 1;
}
//输出层各单元输入、输出值
O_I_O()
{
double sigma;
for (int k=0;k<on;k++)
{
sigma=0.0;
for (int j=0;j<hn;j++)
{
sigma+=V[k][j]*H[j]; //求输出层内积
}
Y[k]=sigma-gama[k]; //求输出层净输入
//cout<<"输出层净输入Y[]:"<<Y[k]<<"\n";
O[k]=1.0/(1.0+exp(-Y[k])); //求输出层输出
//cout<<"输出层输出O[]:"<<O[k]<<"\n";
}
return 1;
}
//输出层至隐层的一般化误差
double d_err[MAX];
Err_O_H(int m)
{
double abs_err[100]; //每个样本的绝对误差都是从0开始的
double sqr_err=0; //每个样本的平方误差计算都是从0开始的
for (int k=0;k<on;k++)
{
abs_err[k]=T[k]-O[k];
//cout<<"T[K]:"<<T[k]<<"\tO[K]:"<<T[k]<<"\n";
//cout<<"abs_err:"<<abs_err[k]<<"\n";
//求第m个样本下的第k个神经元的绝对误差
sqr_err+=(abs_err[k])*(abs_err[k]); //求第m个样本下输出层的平方误差
d_err[k]=abs_err[k]*O[k]*(1.0-O[k]); //d_err[k]输出层各神经元的一般化误差
}
err_m[m]=sqr_err/2; //第m个样本下输出层的平方误差/2=第m个样本的均方误差
//cout<<"第"<<m+1<<"个样本err_m:"<<err_m[m]<<"\n";
return 1;
}
//隐层至输入层的一般化误差
double e_err[MAX];
Err_H_I(){
double sigma;
for (int j=0;j<hn;j++)
{
sigma=0.0;
for (int k=0;k<on;k++)
{
sigma+=d_err[k]*V[k][j];
}
e_err[j]=sigma*H[j]*(1-H[j]); //隐层各神经元的一般化误差
}
return 1;
}
//输出层至隐层的权值调整、输出层阈值调整计算
Delta_O_H(int m,FILE* fp)
{
for (int k=0;k<on;k++)
{
for (int j=0;j<hn;j++)
{
V[k][j]+=alpha*d_err[k]*H[j]; //输出层至隐层的权值调整
//cout<<"输出层至隐层的权值调整V[][]:"<<V[k][j]<<"\n";
//cout<<"alpha:"<<alpha<<"\td_eer[]"<<d_err[k]<<"\tH[]"<<H[j]<<"\n";
}
gama[k]+=alpha*d_err[k]; //输出层至隐层的阈值调整
}
return 1;
}
//隐层至输入层的权值调整、隐层阈值调整计算
Delta_H_I(int m,FILE* fp)
{
for (int j=0;j<hn;j++)
{
for (int i=0;i<in;i++)
{
W[j][i]+=beta*e_err[j]*P[i]; //隐层至输入层的权值调整
//cout<<"隐层至输入层的权值调整W[][]:"<<W[j][i]<<"\n";
}
sita[j]+=beta*e_err[j];
}
return 1;
}
//N个样本的全局误差计算
double Err_Sum()
{
double total_err=0;
for (int m=0;m<n;m++)
{
total_err+=err_m[m]; //每个样本的均方误差加起来就成了全局误差
}
return total_err;
}
main()
{
double sum_err;
int study=1; //学习次数
double Pre_error ; //预定误差
int Pre_times; //预定学习次数
cout<<"以下为从配置文件中读取的参数:\n";
IniFile *ini = new IniFile();
char szPathName[100];
GetModuleFileName(NULL,szPathName,sizeof(szPathName));
CString path=CString(szPathName);
int nPos=path.ReverseFind('\\');
path=path.Left(nPos);
path+=CString("\\bp.ini");
ini->setIniFile(path);
n=ini->getNumber(1,"init");
in=ini->getNumber(2,"init");
hn=ini->getNumber(3,"init");
on=ini->getNumber(4,"init");
cout<<"样本个数:"<<n<<"\t输入层个数:"<<in<<"\t隐含层个数:"<<hn<<"\t输出层个数:"<<on<<"\n";
alpha=ini->getNumber(1,"efficiency");
beta=ini->getNumber(2,"efficiency");
cout<<"alpha="<<alpha<<"\tbeta="<<beta<<"\n";
Pre_error=ini->getNumber(1,"Pre_error");
Pre_times=ini->getNumber(1,"Pre_times");
cout<<"预定误差="<<Pre_error<<"\t预定学习次数="<<Pre_times<<"\n";
int m=0;
cout<<"学习样本:";
for (m=0;m<n;m++)
{
for (int i=0;i<in;i++)
{
Study_Data[m]->input[i]=ini->getNumber(in*m+i+1,"input");
cout<<Study_Data[m]->input[i]<<"\t";
}
}
cout<<"\n";
cout<<"教师样本:";
for (m=0;m<n;m++)
{
for (int k=0;k<on;k++)
{
Study_Data[m]->teach[k]=ini->getNumber(on*m+k+1,"output");
cout<<Study_Data[m]->teach[k]<<"\t";
}
}
cout<<"\n";
char start;
cout<<"是否开始学习(y/n):";
cin>>start;
if(start=='y')
{
initial(); //隐层、输出层权、阈值初始化
double total_err=0;
do
{
for (int m=0;m<n;m++)
{
cout<<"第"<<m+1<<"个样本学习中...\n";
input_P(m); //输入第m个学习样本
input_T(m); //输入第m个样本的教师信号
H_I_O(); //第m个学习样本隐层各单元输入、输出值
O_I_O(); //第m个学习样本输出层各单元输入、输出值
Err_O_H(m); //第m个学习样本输出层至隐层一般化误差
Err_H_I(); //第m个学习样本隐层至输入层一般化误差
Delta_O_H(m,fp); //第m个学习样本输出层至隐层权阈值调整、修改
Delta_H_I(m,fp); //第m个学习样本隐层至输入层权阈值调整、修改
cout<<"经过学习后的输出:";
for(int k=0;k<on;k++)
cout<<O[k]<<"\t";
cout<<"\n教师样本为:";
for(k=0;k<on;k++)
cout<<Study_Data[m]->teach[k]<<"\t";
cout<<"\n";
cout<<"----------样本学习结束-----------------\n";
} //全部样本训练完毕
sum_err=Err_Sum(); //全部样本全局误差计算
cout<<"第"<<study<<"次学习的均方误差为"<<sum_err<<endl;
fprintf(fp,"第%d次学习的均方误差为:%f\n",study,sum_err);
cout<<"调整后的权值为:\n";
for(int i1=0;i1<hn;i1++)
for(int j1=0;j1<in;j1++)
cout<<"W[][]:"<<W[i1][j1]<<"\n";
for(int i2=0;i2<on;i2++)
for(int j2=0;j2<hn;j2++)
cout<<"V[][]:"<<V[i2][j2]<<"\n";
//char c;
//cout<<"请随便输入一个字符,按回车!\n";
//cin>>c;
cout<<"*************************************"<<"\n";
if(study>=Pre_times)
break;
study++;
}while (sum_err > Pre_error) ;
//N个样本全局误差小于预定误差否?小于则退出
if(sum_err <= Pre_error)
{
char study='y';
cout<<"学习结束,是否要验证(y/n):";
cin>>study;
while(study=='y')
{
for (int i=0;i<in;i++)
{
cout<<"请输入第"<<i+1<<"个输入:";
cin>>Study_Data[0]->input[i];
}
input_P(0);
input_T(0);
H_I_O();
O_I_O();
Err_O_H(0);
Err_H_I();
//Delta_O_H(0,fp);
//Delta_H_I(0,fp);
cout<<"经过学习后的输出:";
for(int k=0;k<on;k++)
cout<<O[k]<<"\t";
cout<<"\n";
cout<<"是否还验证(y/n):";
cin>>study;
}
}
else
{
cout<<"学习次数太少,不能到达预期目的\n";
cout<<"请重新设定学习次数\n";
}
}
char s;
cout<<"请随便输入一个字符,按回车退出程序!\n";
cin>>s;
fclose(fp);
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -