📄 wnn_bp.cpp
字号:
/************************************
* 采用参考文献中方法进行验证
* 小波神经网络的参数初始化研究
* 驺春华 陈统坚 叶邦彦 彭永红
* 华南理工大学学报(自然科学版) 第3卷第2期 2003年2月
* 4月10日版的 对a、b不进行反传学习过程
*************************************/
/************************************
* 系统采用的模型为
* 输入层:在输入节点的基础上多加了一个偏置,
* 向隐层求和后经由高斯小波函数求得输出
* 输出层多加了一个偏置,再经由加权求和后经由
* sigmoid函数(或线性函数)获得输出。
* 再通过误差反传调整输出和隐层、隐层和输入之间的权值沿着梯度下降的方向
* 这个版本没有让偏移和缩放尺度加入调整
*************************************/
#include <iostream.h>
#include <iomanip.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <fstream.h>
#include <time.h>
//#define RAND_MAX 65535
#define PI 3.14159267 //pi的近似值
#define ep_min 0.0000001 //本程序中使用的最小数
int sampnum; //样本数
int IN; //输入层节点数
int HN; //初始隐含层节点数
int ON; //输出层节点数
double alpha; //学习因子
double beta; //动量因子
int iternum; //最大循环次数
double ep; //最大误差
double *P; //单个样本输入数据,初始为P[IN][sampnum]
double *T; //单个样本教师数据,为T[ON][sampnum]
double *W; //输入层至隐层的连接权值,为W[HN][IN+1],加入了一个偏置
double *V; //隐层到输出层的连接权值,为V[ON][HN+1]
double *X; //X[HN]----隐层的输入
double *H; //H[HN]----隐层的输出
double *O; //O[ON]----输出层的输出,在输出层采用的是线性函数叠加
double *tempW; //为了进行权值的改进,加入一个修正量
double *tempV; //为了进行权值的改进,加入一个修正量
double *a; //小波函数的尺度值,大小为a[HN]
double *b; //小波函数的偏移量,大小为b[HN]
double *err_m; //err_m[sampnum]----第m个样本的总误差
double *d_err; //d_err[ON]---输出层至隐层的误差传递
double *e_err; //e_err[HN]---隐层至输入层的误差传递
//double *a_err; //a_err[HN]---隐层至输入层的误差a传递
//double *b_err; //b_err[HN]---隐层至输入层的误差b传递
void Display(int *choice);
void InputData(void);
void MemAlloc(void);
void FreeAlloc(void);
void RandInitialize(int seed);
double RandomNum(int a,int b);
double Func(double x);
double DFunc(double x);
double GaussFunc(double x);
double DGaussFunc(double x);
void ReadSample(void);
void Init_WNN(void);
void FeedForward(int samp);
void Err_O_H(int samp);
void Err_H_I(void);
void Update_O_H(void);
void Update_H_I(int samp);
double Err_sum(void);
void SaveParameter(void);
void ReadParameter(void);
void TestForward(double *test);
void main(void)
{
int i;
int choice;
int iter; //循环次数
int m; //当前样本
double total_error;
time_t start,ahead,stop;
start = clock();
stop = clock();
ahead = stop - start;
ofstream outfile("error2.txt");
Display(&choice);
if(choice==1)
{
//InputData(); //输入数据
ifstream runfile("runfile.txt");
runfile>>sampnum>>IN>>HN>>ON>>alpha>>beta>>iternum>>ep;
runfile.close();
MemAlloc(); //分配空间
ReadSample(); //读入样本和目标值
start = clock();
time_t t;
RandInitialize((unsigned)time(&t));
Init_WNN(); //初始化权值和阈值
for(iter=1;iter<iternum;iter++)
{
if(iter%100==0)
cout<<"Current Iteration = "<<iter<<'\n';
for(m=0;m<sampnum;m++)
{
FeedForward(m);
Err_O_H(m);
Err_H_I();
Update_O_H();
Update_H_I(m);
}
total_error=Err_sum();
total_error/=sampnum;
outfile<<total_error<<'\n';
if(total_error<ep)
{
cout<<"Actual Trainning number="<<iter<<'\n';
break;
}
}
outfile.close();
cout<<"误差为: "<<total_error<<'\n';
SaveParameter();
stop = clock();
cout<<"耗费时间为:\n";
cout<<stop - start - ahead<<'\n';
cout<<"神经网络训练完毕!\n";
cout<<"输入2进行网络测试!\n";
cin>>choice;
}
if(choice==2)
{
int testnum;
double *Stest; //用于测试样本测试
cout<<"请输入测试样本个数:\n";
cin>>testnum;
ReadParameter();
ifstream test("test.txt");
ofstream result("result.txt");
if(!test)
{
cout<<"不能打开输入文件!\n";
exit(1);
}
Stest=new double[IN];
m=0;//当前测试样本
do
{
for(i=0;i<IN;i++)
{
test>>Stest[i];
}
//前向测试
TestForward(Stest);
for(i=0;i<ON;i++)
{
result<<O[i]<<'\t';
}
result<<'\n';
m++;
}while(m<testnum);
delete Stest;
Stest=NULL;
test.close();
result.close();
}
FreeAlloc();
}
/*********************************
* 初始选择界面输出
***********************************/
void Display(int *choice)
{
cout<<"这是一个三层神经网络训练与测试程序:\n";
cout<<"请先进行训练再进行测试!\n";
cout<<"有两个选项:\n";
cout<<"1---神经网络训练\n";
cout<<"2---神经网络测试\n";
cout<<"请选择:\n";
cin>>*choice;
}
/*********************************
* 各个初始量的输入
**********************************/
void InputData(void)
{
do{
cout<<"请输入训练样本数:\n";
cin>>sampnum;
}while(sampnum<=0);
do
{
cout<<"请输入输入层节点数:\n";
cin>>IN;
}while(IN<=0);
do
{
cout<<"请输入隐层节点数:\n";
cin>>HN;
}while(HN<=0);
do
{
cout<<"请输入输出层节点数:\n";
cin>>ON;
}while(ON<=0);
do
{
cout<<"请输入学习速率(alpha):\n";
cin>>alpha;
}while(alpha<=0||alpha>=1);
do
{
cout<<"请输入平滑因子(beta):\n";
cin>>beta;
}while(beta<=0||beta>=1);
do
{
cout<<"请输入最大循环次数:\n";
cin>>iternum;
}while(iternum<0||iternum>100000);
do
{
cout<<"请输入目标误差(0.01--0.00001):\n";
cin>>ep;
}while(ep<0.00001||ep>0.01);
}
/*********************************
* 分配内存
*********************************/
void MemAlloc(void)
{
//P[IN][sampnum]---单个样本输入数据
P=new double[IN*sampnum];
if(P==NULL)
{
cout<<"P内存分配失败!\n";
exit(1);
}
memset(P,0,sizeof(double)*IN*sampnum);
//T[ON][sampnum]---单个样本教师数据
T=new double[ON*sampnum];
if(T==NULL)
{
cout<<"T内存分配失败!\n";
exit(1);
}
memset(T,0,sizeof(double)*ON*sampnum);
//W[HN][IN+1]---输入层至隐层权值
W=new double[(IN+1)*HN];
if(W==NULL)
{
cout<<"W内存分配失败!\n";
exit(1);
}
memset(W,0,sizeof(double)*(IN+1)*HN);
//tempW[HN][IN+1]---加入的修正量
tempW=new double[(IN+1)*HN];
if(tempW==NULL)
{
cout<<"tempW内存分配失败!\n";
exit(1);
}
memset(tempW,0,sizeof(double)*(IN+1)*HN);
//V[ON][HN+1]---隐层至输出层权值
V=new double[(HN+1)*ON];
if(V==NULL)
{
cout<<"V内存分配失败!\n";
exit(1);
}
memset(V,0,sizeof(double)*(HN+1)*ON);
//tempV[ON][HN+1]---加入的修正量
tempV=new double[(HN+1)*ON];
if(tempV==NULL)
{
cout<<"tempV内存分配失败!\n";
exit(1);
}
memset(tempV,0,sizeof(double)*(HN+1)*ON);
//X[HN]----隐层的输入
X=new double[HN];
if(X==NULL)
{
cout<<"X内存分配失败!\n";
exit(1);
}
memset(X,0,sizeof(double)*HN);
//H[HN]---隐层的输出
H=new double[HN];
if(H==NULL)
{
cout<<"H内存分配失败!\n";
exit(1);
}
memset(H,0,sizeof(double)*HN);
//O[ON]---输出层的输出,在输出层采用的是线性函数叠加
O=new double[ON];
if(O==NULL)
{
cout<<"O内存分配失败!\n";
exit(1);
}
memset(O,0,sizeof(double)*ON);
//a[HN]---隐层的偏移量
a=new double[HN];
if(a==NULL)
{
cout<<"a内存分配失败!\n";
exit(1);
}
memset(a,0,sizeof(double)*HN);
//b[HN]---隐层的缩放尺度
b=new double[HN];
if(b==NULL)
{
cout<<"b内存分配失败!\n";
exit(1);
}
memset(b,0,sizeof(double)*HN);
//err_m[sampnum]----第m个样本的总误差
err_m=new double[sampnum];
if(err_m==NULL)
{
cout<<"err_m内存分配失败!\n";
exit(1);
}
memset(err_m,0,sizeof(double)*sampnum);
//d_err[ON]---输出层至隐层的误差传递
d_err=new double[ON];
if(d_err==NULL)
{
cout<<"d_err内存分配失败!\n";
exit(1);
}
memset(d_err,0,sizeof(double)*ON);
//e_err[HN]---隐层至输入层的误差传递
e_err=new double[HN];
if(e_err==NULL)
{
cout<<"e_err内存分配失败!\n";
exit(1);
}
memset(e_err,0,sizeof(double)*HN);
}
/*************************************
* 释放空间
**************************************/
void FreeAlloc(void)
{
delete []P; P=NULL;
delete []T; T=NULL;
delete []W; W=NULL;
delete []tempW; tempW=NULL;
delete []tempV; tempV=NULL;
delete []V; V=NULL;
delete []X; X=NULL;
delete []H; H=NULL;
delete []O; O=NULL;
delete []a; a=NULL;
delete []b; b=NULL;
delete []err_m; err_m=NULL;
delete []d_err; d_err=NULL;
delete []e_err; e_err=NULL;
}
/********************************
* 产生随机数种子
*********************************/
void RandInitialize(int seed)
{
srand(seed);
}
/*********************************
* 产生一个位于(a,b)的随机数
*********************************/
double RandomNum(int a,int b)
{
double result;
result=(b-a)*(double)rand()/(double)RAND_MAX+a;
return result;
}
double Func(double x)
{
double result;
result=1/(1+exp(-x));
return result;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -