📄 bpnet002.txt
字号:
/****** 增加动量项alpha 初始化alpha=0.4 动态修改 ******/
/****** 自适应调节学习率eta 初始化eta=0.8 动态修改 ****/
/****** 隐含层权值矩阵w1 初始化接近0 ******************/
/****** terget 正弦函数 *******************************/
/*!!!!! 仿正弦函数效果不好!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
#include <math.h>
#include <stdio.h>
#include <time.h>
#define nP 1 //期望模式对数nP=1
#define nHiddenNodes 5 //隐含层节点数 5
#define nInputNodes 1 //输入节点数 1
#define nOutputNodes 1 //输出节点数 1
#define Sample 21 //样本数 1-10
void Initialw1(); //初始化w1矩阵
void Initialw2(); //初始化w2矩阵
void Initialdelw(); //初始化权值变化矩阵
void InitialSample(); //初始化样本
double w1[nHiddenNodes][nInputNodes]; //输入层--隐含层权值矩阵
double w2[nOutputNodes][nHiddenNodes]; //隐含层--输出层权值矩阵
double delw1[nHiddenNodes][nInputNodes]; //输入层--隐含层权值变化矩阵
double delw2[nOutputNodes][nHiddenNodes];//隐含层--输出层权值变化矩阵
double out0[Sample]; //输入样本 1维
double out1[nHiddenNodes][Sample]; //隐含层节点值 2维
double delta1[nHiddenNodes]; //隐含层节点偏差
double out2[Sample]; //输出层节点值 1维
double delta2[Sample]; //输出层节点偏差
double target[Sample]; //输出目标值 1维
float scale=42767; //求随机数时的标准化标尺因子
float wmax=0.8; //最大权值
int nlteration=10; //迭代次数
float eta=0.8; //学习因子
float alpha=0.4; //动态因子
float w11; //w1阵 产生随机数
float w22; //w2阵 产生随机数
float dw;
int i,j,h,p,q;
double sum,sum1;
float Erms=0.0;
float Ermspre=0.0;
/**************************************************************************/
/*****************************main()***************************************/
main()
{ Initialw1(); //初始化w1矩阵
Initialw2(); //初始化w2矩阵
Initialdelw(); //初始化权值变化矩阵
InitialSample(); //初始化样本
/***************************开始迭代********************************/
for(q=0;q<200;q++) //迭代步数
{for(p=0;p<Sample;p++) //输入样本对 第p个样本对
{//样本为第p个样本对
//p=0的样本不进行迭代
/*********************隐含层节点输出值****************************/
sum=0.0;
for(h=0;h<nHiddenNodes;h++)
{float sum=w1[h][0];
sum=w1[h][0]*out0[p];
out1[h][p]=1.0/(1.0+exp(-sum));
sum=0.0;
}
/********************输出层节点值********************************/
sum1=0.0;
sum=0.0;
for(h=0;h<nHiddenNodes;h++)
{float sum=w2[0][h];
sum=w2[0][h]*out1[h][p];
sum1=sum1+sum;
}
out2[p]=1.0/(1.0+exp(-sum1));
/************************样本p迭代结束后,计算误差,修正权值*********/
//输出节点偏差delta2
delta2[p]=(target[p]-out2[p])*out2[p]*(1.0-out2[p]);
//隐含层节点偏差delta1
for(h=0;h<nHiddenNodes;h++)
{float sum=0.0;
sum=delta2[p]*w2[0][h];
delta1[h]=sum*out1[h][p]*(1.0-out1[h][p]);
}
/*===================调节隐层与输出层间的权值==============*/
//计算权值偏差矩阵delw2
dw=sum=0.0;
//sum=delta2[p];
for(h=0;h<nHiddenNodes;h++)
{dw=eta*delta2[p]*out1[h][p]+alpha*delw2[0][h]; //计算权值变化
w2[0][h]+=dw; //新权值
delw2[0][h]=dw;} //保存变化值
/*===================调节输入与隐含层间的权值==============*/
dw=sum=0.0;
for(h=0;h<nHiddenNodes;h++)
{
dw=eta*delta1[h]*out0[p]+alpha*delw1[h][0]; //计算权值变化
w1[h][0]+=dw; //新权值
delw1[h][0]=dw; //保存变化值
dw=sum=0.0;
}
/***********************************************************************/
}//p个样本一次迭代结束
//动态修改学习因子eta
sum1=0.0;
for(p=1;p<Sample;p++)
{sum=0.0;
sum=0.5*(target[p]-out2[p])*(target[p]-out2[p]);
sum1=sum1+sum;} //sum1累加本次误差
Erms=sum1; //Erms本次误差,Ermspre上一次误差
if(Erms/Ermspre>1.0001) //Erms>Ermspre 减慢学习速率eta
{eta*=0.7;
alpha*=0.7;
if (eta>0.99)
eta=0.9;
if (alpha>0.5)
alpha=0.5;}
else //Erms<Ermspre 加快学习速率eta
{eta*=1.05;
alpha*=1.05;
if (eta>0.99)
eta=0.9;
if (alpha>0.5)
alpha=0.5;}
Ermspre=Erms; //保存本次误差值
}//q步迭代结束
puts ("diedai finish");
}//main结束
/****************************************************************************/
/*****************************初始化权矩阵***********************************/
//初始化输入层--隐含层权值矩阵w1
void Initialw1()
{
register int i1,j1;
srand((int)time(0)); // 初始化随机数生成器
for(i1=0;i1<nHiddenNodes;i1++)
{for(j1=0;j1<nInputNodes;j1++)
{float frand=rand();
w11 = wmax*(1.0-2*frand/scale);
w1[i1][j1]=w11/10;
}
}
puts ("initial w1 finish\n");
}
//初始化隐含层--输出层权值矩阵w2
void Initialw2()
{
register int i2,j2;
srand((int)time(0));
for(i2=0;i2<nOutputNodes;i2++)
{for(j2=0;j2<nHiddenNodes;j2++)
{float frand=rand();
//(wmax-0.05) 防止w1,w2矩阵初始值相同
w22 = (wmax-0.05)*(1.0-2*frand/scale);
w2[i2][j2]=w22;
}
}
puts ("initial w2 finish\n");
}
/**************************************************************************/
/*****************************初始化权值变化矩阵***************************/
void Initialdelw()
{register int h,i,j;
for(h=0;h<nHiddenNodes;h++) //delw1全部为0
for(i=0;i<nInputNodes;i++)
{delw1[h][i]=0.0;}
for(j=0;j<nOutputNodes;j++) //delw2全部为0
for(h=0;h<nHiddenNodes;h++)
{delw2[j][h]=0.0;}
for(j=0;j<nOutputNodes;j++) //调整delw2为0.0-0.04的小数,防止delw2在程序运行中全部相等
for(h=0;h<nHiddenNodes;h++)
{delw2[j][h]=delw2[j][h]+0.01*h;}
puts ("initial delw1 and delw2 finish\n");
}
/**************************************************************************/
/*****************************初始化样本***********************************/
void InitialSample()
{ for (i=0;i<Sample;i++) //输入样本值
{out0[i]=(double)(i)/20.0;}
for(i=0;i<Sample;i++) //输出目标值
{target[i]=(0.4 * sin ((2*3.1415926)*(out0[i]))+0.5);}
//隐含层 输出层 节点值及其偏差矩阵清零
//便于观察
for (i=0;i<Sample;i++)
{for (j=0;j<nHiddenNodes;j++)
{out1[j][i]=0.0;
delta1[j]=0.0;}
out2[i]=0.0;
delta2[i]=0.0;
}
puts ("initial Sample finish\n");
}
/**************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -