📄 wnn_bp.cpp
字号:
double DFunc(double x)
{
double result;
result=x*(1-x);
return result;
}
/**********************************
* 选择高斯的一阶导数作为小波母函数
* 即 y=x*exp(-0.5*x^2)
**********************************/
double GaussFunc(double x)
{
double result;
result=x*exp(-0.5*x*x);
return result;
}
/*********************************
* 返回高斯二阶导数的值
* 即 y=(1-x^2)*exp(-0.5*x^2)
*********************************/
double DGaussFunc(double x)
{
double result;
result=(1-x*x)*exp(-0.5*x*x);
return result;
}
/***********************************************
* 将样本中的所有数据、以及目标向量读入输入数据中
************************************************/
void ReadSample(void)
{
int i;
int samp;
ifstream infile("sample.txt");
samp=0;
while(samp<sampnum)
{
for(i=0;i<IN;i++)
{
infile>>P[i*sampnum+samp];
}
for(i=0;i<ON;i++)
{
infile>>T[i*sampnum+samp];
}
samp++;
}
}
/***********************************************
* 用参考文献提供的方法初始化输入层至隐层的权值
* 以及初始化平移和缩放尺度
* 将隐层和输出层之间的权值随机初始化为 [-1 1]的值
*************************************************/
void Init_WNN(void)
{
/************************************************
* 先把输入层和隐层之间的权值随机初始化在[-1,1]之间
*************************************************/
int i;
int j;
double square;
double C=2.0*pow(HN,(double)1/IN); //根据文献设置的参考值
for(i=0;i<HN;i++)
{
square=0;
for(j=0;j<IN+1;j++)
{
W[i*(IN+1)+j]=RandomNum(-1,1);
square+=W[i*(IN+1)+j]*W[i*(IN+1)+j];
}
//按行进行归一
square=C/sqrt(square);
for(j=0;j<IN+1;j++)
{
W[i*(IN+1)+j]*=square;
}
}
//测试权值第一次初始化的值
/*
ofstream offile("weight.txt");
for(i=0;i<HN;i++)
{
for(j=0;j<IN+1;j++)
{
offile<<W[i*(IN+1)+j]<<'\n';
}
}
offile.close();
*/
//和样本中的最大和最小值发生关系
double min;
double max;
double temp;
double d;
int k;
for(i=0;i<IN;i++)
{
max=0;
min=10000;
//返回第i个神经元输入样本中的最大和最小值
for(j=0;j<sampnum;j++)
{
temp=P[i*sampnum+j];
if(temp>max)
max=temp;
if(temp<min)
min=temp;
}
d=2/(max-min+ep_min);
for(k=0;k<HN;k++)
{
W[k*(IN+1)+i]*=d;
}
}
ofstream offile("weight.txt");
for(i=0;i<HN;i++)
{
for(j=0;j<IN+1;j++)
{
offile<<W[i*(IN+1)+j]<<'\n';
}
}
offile.close();
//开始a,b的初始化
//memset(a,0,HN*sizeof(double));
//memset(b,0,HN*sizeof(double));
// float center=0; //高斯小波的时域中心
//float radius=1.2247; //高斯小波的半径
double coeff=1/(2*1.2247);
for(j=0;j<IN;j++)
{
max=0;
min=1000;
for(k=0;k<sampnum;k++)
{
//寻找第i个输入节点样本中的最大和最小值
if(P[j*sampnum+k]>max)
max=P[j*sampnum+k];
if(P[j*sampnum+k]<min)
min=P[j*sampnum+k];
}
for(i=0;i<HN;i++)
{
a[i]+=W[i*(IN+1)+j]*(max-min)*coeff;
b[i]+=W[i*(IN+1)+j]*(max+min)*0.5;
}
}
//平移和缩放尺度初始化完毕
//初始化隐层至输出层的权值
//加入了偏置的
for(i=0;i<ON;i++)
{
for(j=0;j<HN+1;j++)
{
V[i*(HN+1)+j]=RandomNum(-1,1);
}
}
}
/***************************
* 第samp样本的网络前向传递过程
****************************/
void FeedForward(int samp)
{
int i;
int j;
double t;
double sum;
//the layer input-hidden layer
for(i=0;i<HN;i++)
{
sum=W[i*(IN+1)+IN]; //the weight of bias
for(j=0;j<IN;j++)
{
sum+=P[j*sampnum+samp]*W[i*(IN+1)+j];
}
X[i]=sum; //隐层的输入
t=(sum-a[i])/b[i];
H[i]=GaussFunc(t); //隐层的输出
}
//the layer hidden-output layer
for(i=0;i<ON;i++)
{
sum=V[i*(HN+1)+HN];
for(j=0;j<HN;j++)
{
sum+=H[j]*V[i*(HN+1)+j];
}
//输出层采用了sigmoid函数
//O[i]=Func(sum); //采用sigmoid函数
//输出层采用线性叠加
O[i]=sum;
}
}
/*****************************************
*输出层至隐层的一般化误差子程序
*第samp个样本输入时,存储输出端的总标准误差
******************************************/
void Err_O_H(int samp)
{
double ep;
double e;
int i;
ep=0.0;
e=0.0;
//求输出端的总误差
for(i=0;i<ON;i++)
{
ep=T[i*sampnum+samp]-O[i];
//输出层采用了sigmoid函数
//d_err[i]=DFunc(O[i])*ep; //有函数的导数部分
//输出层采用了线性叠加
d_err[i]=ep;
ep=0.5*ep*ep;
e+=ep;
}
err_m[samp]=e;
}
/****************************************
*隐层至输入层的一般化误差子程序
*****************************************/
void Err_H_I(void)
{
int i;
int j;
double sum;
double t;
for(i=0;i<HN;i++)
{
sum=0.0;
//输出层向隐层误差反传求和
for(j=0;j<ON;j++)
{
sum+=d_err[j]*V[j*(HN+1)+i];
}
t=(X[i]-a[i])/b[i];
e_err[i]=sum*DGaussFunc(t)/b[i];
}
}
/*************************************************
* 输出层至隐层的权值调整、输出层阈值调整计算子程序
*************************************************/
void Update_O_H(void)
{
int i;
int j;
double dw;
for(i=0;i<ON;i++)
{
dw=alpha*d_err[i]+beta*tempV[i*(HN+1)+HN];
V[i*(HN+1)+HN]+=dw;
tempV[i*(HN+1)+HN]=dw;
for(j=0;j<HN;j++)
{
dw=alpha*d_err[i]*H[j]+beta*tempV[i*(HN+1)+j];
V[i*(HN+1)+j]+=dw;
tempV[i*(HN+1)+j]=dw;
}
}
}
void Update_H_I(int samp)
{
int i;
int j;
double dw;
for(i=0;i<HN;i++)
{
dw=alpha*e_err[i]+beta*tempW[i*(IN+1)+IN];
W[i*(IN+1)+IN]+=dw;
tempW[i*(IN+1)+IN]=dw;
for (j=0;j<IN;j++)
{
dw=alpha*e_err[i]*P[j*sampnum+samp]+beta*tempW[i*(IN+1)+j];
W[i*(IN+1)+j]+=dw;
tempW[i*(IN+1)+j]=dw;
}
}
}
double Err_sum(void)
{
//N个样本的全局误差计算子程序
int i;
double sum;
sum=0.0;
for(i=0;i<sampnum;i++)
{
sum+=err_m[i];
}
return sum;
}
void SaveParameter(void)
{
int i;
int j;
ofstream outfile("OutParameter.txt");
if(!outfile)
{
cout<<"不能打开目的地文件!\n";
exit(1);
}
outfile<<IN<<'\n';
outfile<<HN<<'\n';
outfile<<ON<<'\n';
outfile<<'\n';
//output the weight of Hidden-Input layer
for(i=0;i<HN;i++)
{
for(j=0;j<IN+1;j++)
{
outfile<<W[i*(IN+1)+j]<<'\n';
}
}
outfile<<'\n';
//output the translation and dilation of Hidden layer
for(i=0;i<HN;i++)
{
outfile<<a[i]<<'\t'<<b[i]<<'\n';
}
outfile<<'\n';
//output the weight of Output-Hidden layer
for(i=0;i<ON;i++)
{
for(j=0;j<HN+1;j++)
{
outfile<<V[i*(HN+1)+j]<<'\n';
}
}
outfile.close();
}
void ReadParameter(void)
{
int i;
int j;
ifstream infile("OutParameter.txt");
if(!infile)
{
cout<<"不能打开输入文件!\n";
exit(1);
}
infile>>IN;
infile>>HN;
infile>>ON;
//load the weight of Hidden-Input layer
for(i=0;i<HN;i++)
{
for(j=0;j<(IN+1);j++)
{
infile>>W[i*(IN+1)+j];
}
}
//load the translation and dilation of Hidden layer
for(i=0;i<HN;i++)
{
infile>>a[i]>>b[i];
}
for(i=0;i<ON;i++)
{
for(j=0;j<HN+1;j++)
{
infile>>V[i*(HN+1)+j];
}
}
infile.close();
}
void TestForward(double *test)
{
int i;
int j;
double t;
double sum;
//the layer input-hidden layer
for(i=0;i<HN;i++)
{
sum=W[i*(IN+1)+IN]; //the weight of bias
for(j=0;j<IN;j++)
{
sum+=test[j]*W[i*(IN+1)+j];
}
X[i]=sum; //隐层的输入
t=(sum-a[i])/b[i];
H[i]=GaussFunc(t); //隐层的输出
}
//the layer hidden-output layer
for(i=0;i<ON;i++)
{
sum=V[i*(HN+1)+HN];
for(j=0;j<HN;j++)
{
sum+=H[j]*V[i*(HN+1)+j];
}
//采用了sigmoid函数
//O[i]=Func(sum); //采用sigmoid函数
O[i]=sum;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -