⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bp5.cpp

📁 用三层BP网络实现一个单输入单输出函数的逼近
💻 CPP
字号:
#include<iostream.h>
#include<math.h>
float sigmoid(float x)
{
	float y;
	y=1/(1+exp(-1*x));
	return y;
}
float myfunction(float x)
{
	float y;
//	y=x;
	y=0.5+0.3*(sin(2*x));
//	y=x*x;
//	y=exp(-1*x);
//	y=-1*x*(x*x-3.2*x+1.7*1.7)*(x-3)/2;
//	y=1/x;
	return y;
}
void main()
{
	int i, p, pt, pp, j, count=0;

	int midnumber;//隐层节点数
	float **x0;//第0层(输入层)的两个输入
	float **y0;//第0层(输入层)的两个输出
    float **x1, **y1;//第一层各节点的输入输出
	float *x2, *y2;//输出层的输入输出
	float **w0, *w1;//两个权矩阵
	float *samplex, *sampley;//训练样本对
	float *testx, *testy;//推广测试样本对
	float *erreach, err, enderr=0.001;//每个样本误差,总误差,期望误差
	float **delta0, **delta1;//误差修正向量
	float **sumdelta0, *sumdelta1;//总修正量
	float **predelta0, *predelta1;//上一次修正量
	float step = 0.3;//步长
	float moti = 0.2;//动量项因子
		
	cout<<"请输入隐层节点数: ";
	cin>>midnumber;
	
	cout<<endl<<"用于训练的样本个数为: ";
	cin>>p;
	samplex = new float[p];
	sampley = new float[p];
	erreach = new float[p];

    x0=new float*[p];
	for(pp=0;pp<p;pp++)
		x0[pp]=new float[2];
	y0=new float*[p];
	for(pp=0;pp<p;pp++)
		y0[pp]=new float[2];
	x1=new float*[p];
	for(pp=0;pp<p;pp++)
		x1[pp]=new float[midnumber+1];
	y1=new float*[p];
	for(pp=0;pp<p;pp++)
		y1[pp]=new float[midnumber+1];
	x2=new float[p];
	y2=new float[p];	
	
	w0=new float*[2];
	for(i=0;i<2;i++)
		w0[i] = new float[midnumber];
	w1=new float[midnumber+1];

	delta1=new float*[p];
	for(pp=0;pp<p;pp++)
		delta1[pp]=new float[1];
	delta0=new float*[p];
	for(pp=0;pp<p;pp++)
		delta0[pp]=new float[midnumber+1];
	
	sumdelta0 = new float*[2];
	for(i=0;i<2;i++)
		sumdelta0[i] = new float[midnumber+1];
	sumdelta1 = new float[midnumber+1];

	predelta0 = new float*[2];
	for(i=0;i<2;i++)
		predelta0[i] = new float[midnumber+1];
	predelta1 = new float[midnumber+1];
	for(i=0;i<2;i++)
		for(j=1;j<=midnumber;j++)
			predelta0[i][j]=0;
	for(j=0;j<=midnumber;j++)
		predelta1[j]=0;

	////test: 初始化样本及权矩阵////
	for(pp=0;pp<p;pp++)
	{
		samplex[pp]=0.1+0.9*float(pp)/float(p);
		sampley[pp]=myfunction(samplex[pp]);
	}
/*	samplex[p-6]=0.93;
	samplex[p-5]=0.95;
	samplex[p-4]=0.96;
	samplex[p-3]=0.97;
	samplex[p-2]=0.98;
	samplex[p-1]=0.99;
	for(pp=p-6;pp<p;pp++)
	{
	
		sampley[pp]=myfunction(samplex[pp]);
	}
*/	for(i=0;i<2;i++)
		for(j=1;j<=midnumber;j++)
			w0[i][j]=0.05;//double(rand())/32767*2-1;//
	for(j=0;j<=midnumber;j++)
		w1[j]=0.01;//double(rand())/32767*2-1;//
	////test: 初始化样本及权矩阵////

	//计算各层输入输出
	for(pp=0;pp<p;pp++)
	{
		x0[pp][0]=1;
		x0[pp][1]=samplex[pp];
		for(i=0;i<2;i++)
			y0[pp][i]=x0[pp][i];

		x1[pp][0]=1;
		y1[pp][0]=1;
		for(j=1;j<=midnumber;j++)
		{
			x1[pp][j]=y0[pp][0]*w0[0][j]+y0[pp][1]*w0[1][j];
			y1[pp][j]=sigmoid(x1[pp][j]);
		}

		x2[pp]=0;
		for(j=0;j<=midnumber;j++)
			x2[pp]=x2[pp]+y1[pp][j]*w1[j];
		y2[pp]=sigmoid(x2[pp]);

		erreach[pp] = (y2[pp]-sampley[pp])*(y2[pp]-sampley[pp])/2;
	}

	//计算p个样本总误差
	err = 0;
	for(pp=0;pp<p;pp++)
		err = err + erreach[pp];
	cout<<"初始误差:"<<err<<endl;

	while(err>enderr)
//	for(count=0;count<10;)
	{
		count++;
		//计算误差修正向量
		for(pp=0;pp<p;pp++)
		{
			for(j=0;j<1;j++)
				delta1[pp][j] = (y2[pp]-sampley[pp])*y2[pp]*(1-y2[pp]);
			for(j=1;j<=midnumber;j++)
				delta0[pp][j] = y1[pp][j]*(1-y1[pp][j])*delta1[pp][0]*w1[j];
		} 
		//初始化各修正值为0
		for(i=0;i<2;i++)
			for(j=0;j<=midnumber;j++)
				sumdelta0[i][j] = 0;
		for(i=0;i<=midnumber+1;i++)
			sumdelta1[i] = 0;
		//w1[j]的修正值
		for(j=0;j<=midnumber;j++)
			for(pp=0;pp<p;pp++)
				sumdelta1[j] = sumdelta1[j] + (delta1[pp][0]*y1[pp][j]);
		//w0[0][j]的修正值
		for(j=1;j<=midnumber;j++)
			for(pp=0;pp<p;pp++)
				sumdelta0[0][j] = sumdelta0[0][j]+(delta0[pp][j]*x0[pp][0]);
	    //w0[1][j]的修正值
		for(j=1;j<=midnumber;j++)
			for(pp=0;pp<p;pp++)
				sumdelta0[1][j] = sumdelta0[1][j]+(delta0[pp][j]*x0[pp][1]);

		//修改w1
		for(j=0;j<=midnumber;j++)
			w1[j] = w1[j] - step*sumdelta1[j];//-moti*predelta1[j];
		//修改w0[0][j]
		for(j=1;j<=midnumber;j++)
			w0[0][j] = w0[0][j] - step*sumdelta0[0][j];//-moti*predelta0[0][j];
		//修改w0[0][j]
		for(j=1;j<=midnumber;j++)
			w0[1][j] = w0[1][j] - step*sumdelta0[1][j];//-moti*predelta0[1][j];

		//重新计算各层输入输出
		for(pp=0;pp<p;pp++)
		{
			x0[pp][0]=1;
			x0[pp][1]=samplex[pp];
			for(i=0;i<2;i++)
				y0[pp][i]=x0[pp][i];

			x1[pp][0]=1;
			y1[pp][0]=1;
			for(j=1;j<=midnumber;j++)
			{
				x1[pp][j]=y0[pp][0]*w0[0][j]+y0[pp][1]*w0[1][j];
				y1[pp][j]=sigmoid(x1[pp][j]);
			}

			x2[pp]=0;
			for(j=0;j<=midnumber;j++)
				x2[pp]=x2[pp]+y1[pp][j]*w1[j];
			y2[pp]=sigmoid(x2[pp]);

			erreach[pp] = (y2[pp]-sampley[pp])*(y2[pp]-sampley[pp])/2;
		}

		//计算p个样本总误差
		err = 0;
		for(pp=0;pp<p;pp++)
			err = err + erreach[pp];
//		cout<<err<<" ";
		for(i=0;i<2;i++)
			for(j=1;j<=midnumber;j++)
				predelta0[i][j]=sumdelta0[i][j];
		for(j=0;j<=midnumber;j++)
			predelta1[j]=sumdelta1[j];
		////test w1,w2////
/*		cout<<"权值矩阵: "<<endl<<"w0: "<<endl;
		for(i=0;i<2;i++)
		{
			cout<<"w0(0,"<<j<<"): ";
			for(j=1;j<=midnumber;j++)
				cout<<w0[i][j]<<", ";
			cout<<endl;
		}
		cout<<"w1: "<<endl;
		for(j=0;j<=midnumber;j++)
		{
			cout<<"w1("<<j<<",0): "<<w1[j]<<endl;
		}
*/
	}
	cout<<endl<<"迭代次数为: "<<count<<endl;
	//输出权值矩阵
	cout<<"权值矩阵: "<<endl<<"w0: "<<endl;
	for(i=0;i<2;i++)
	{
		cout<<"w0(0,"<<j<<"): ";
		for(j=1;j<=midnumber;j++)
			cout<<w0[i][j]<<", ";
		cout<<endl;
	}
	cout<<"w1: "<<endl;
	for(j=0;j<=midnumber;j++)
	{
		cout<<"w1("<<j<<",0): "<<w1[j]<<endl;
	}
	cout<<"终止误差:"<<err<<endl;

	cout<<"(sampley,y2): "<<endl;
	for(pp=0;pp<p;pp++)
		cout<<"("<<samplex[pp]<<sampley[pp]<<", "<<y2[pp]<<") ";
	cout<<endl;
	//推广测试
	cout<<endl<<"请输入用于推广测试的样本个数(注意要少于训练样本个数): ";
	cin>>pt;
	testx = new float[pt];
	testy = new float[pt];
	for(pp=0;pp<pt;pp++)
	{
		testx[pp]=0.2+float(pp)/float(2*pt);
		testy[pp]=myfunction(testx[pp]);
	}
	//计算各层输入输出
	for(pp=0;pp<p;pp++)
	{
		x0[pp][0]=1;
		x0[pp][1]=testx[pp];
		for(i=0;i<2;i++)
			y0[pp][i]=x0[pp][i];

		x1[pp][0]=1;
		y1[pp][0]=1;
		for(j=1;j<=midnumber;j++)
		{
			x1[pp][j]=y0[pp][0]*w0[0][j]+y0[pp][1]*w0[1][j];
			y1[pp][j]=sigmoid(x1[pp][j]);
		}

		x2[pp]=0;
		for(j=0;j<=midnumber;j++)
			x2[pp]=x2[pp]+y1[pp][j]*w1[j];
		y2[pp]=sigmoid(x2[pp]);

		erreach[pp] = (y2[pp]-testy[pp])*(y2[pp]-testy[pp])/2;
	}

	cout<<"样本输入输出为:"<<endl;
	for(pp=0;pp<pt;pp++)
		cout<<"("<<testx[pp]<<", "<<testy[pp]<<", "<<y2[pp]<<") ";
	//计算p个样本总误差
	err = 0;
	for(pp=0;pp<pt;pp++)
		err = err + erreach[pp];
	cout<<"推广测试的误差:"<<err<<endl;

}
       

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -