BP神经网络

忘记转载的哪里的了,见谅

// ConsoleApplication3.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "atltime.h"
#include<iostream>        
#include<cmath>      
#include<fstream>    
using namespace std;


#define  innode 9  //输入结点数        
#define  hidenode 10//隐含结点数           
#define  sample 8//BP样本数     
double allow_e = 0.001;//允许误差    


class BpNet
{
public:
	void train(double p[sample][innode], double t[sample]);//Bp训练        
	double p[sample][innode];     //输入的样本        
	double t[sample];    //样本要输出的        
	
	double test(double *p);//Bp识别        
	
	BpNet();
	virtual ~BpNet();
	
public:
	void init();
	double w1[innode][hidenode];//隐含结点权值        
	double w2[hidenode];//输出结点权值        
	
	double rate_w1; //权值学习率(输入层-隐含层)        
	double rate_w2;//权值学习率 (隐含层-输出层)        
	
	double e;//单个样本误差计算        
	double error;//误差均值     
	double result;// Bp输出    
};


BpNet::BpNet()
{
	error = 0.1;
	e = 0.0;

	rate_w1 = 0.6;  //权值学习率(输入层--隐含层)        
	rate_w2 = 0.6; //权值学习率 (隐含层--输出层)        


}


BpNet::~BpNet()
{


}


void winit(double w[], int n) //权值初始化        
{
	for (int i = 0; i < n; i++)
		w[i] = (rand() % 10)*0.1 - 0.5;
}


void BpNet::init()
{
	winit((double*)w1, innode*hidenode);
	winit((double*)w2, hidenode);
}


void BpNet::train(double p[sample][innode], double t[sample])
{
	double pp[hidenode];//隐含结点的校正误差        
	double qq;//希望输出值与实际输出值的偏差        
	double yd;//希望输出值        

	double x[innode]; //输入向量        
	double x1[hidenode];//隐含结点状态值        
	double x2;//输出结点状态值        
	double o1[hidenode];//隐含层激活值        
	double o2;//输出层激活值        
	
	for (int isamp = 0; isamp < sample; isamp++)//循环训练一次样品        
	{
		for (int i = 0; i < innode; i++)
			x[i] = p[isamp][i]; //输入的样本        
		
		yd = t[isamp]; //期望输出的样本        
		
		//构造每个样品的输入和输出标准  ///输入层到隐层      
		for (int j = 0; j < hidenode; j++)
		{
			o1[j] = 0.0;
			for (int i = 0; i < innode; i++)
				o1[j] = o1[j] + w1[i][j] * x[i];//隐含层各单元输入激活值        
			x1[j] = 1.0 / (1 + exp(-o1[j]));//隐含层各单元的输出        
		}

		///隐层到输出层      
		o2 = 0.0;
		for (int j = 0; j < hidenode; j++)
			o2 = o2 + w2[j] * x1[j];
		x2 = 1.0 / (1.0 + exp(-o2));  //输出层各单元输出      
									  /计算偏差并调整权值    
		qq = (yd - x2)*x2*(1 - x2); //希望输出与实际输出的偏差        
		for (int j = 0; j < hidenode; j++)
			w2[j] += rate_w2*qq*x1[j];  //下一次的隐含层和输出层之间的新连接权        
		
		for (int j = 0; j < hidenode; j++)
		{
			pp[j] = 0.0;

			pp[j] = pp[j] + qq * w2[j];
			pp[j] = pp[j] * x1[j] * (1 - x1[j]); //隐含层的校正误差        
			
			for (int i = 0; i < innode; i++)
				w1[i][j] += rate_w1 * pp[j] * x[i]; //下一次的输入层和隐含层之间的新连接权        
		}
		e += fabs(yd - x2)*fabs(yd - x2) / 2;
	}
	error = double(e / double(sample));//计算误差均值    
}


double BpNet::test(double *p)
{
	double x[innode]; //输入向量        
	double x1[hidenode]; //隐含结点状态值        
	double x2; //输出结点状态值        
	double o1[hidenode]; //隐含层激活值        
	double o2; //输出层激活值        


	for (int i = 0; i < innode; i++)
		x[i] = p[i];
	
	for (int j = 0; j < hidenode; j++)
	{
		o1[j] = 0.0;
		for (int i = 0; i < innode; i++)
			o1[j] = o1[j] + w1[i][j] * x[i]; //隐含层各单元激活值        
		x1[j] = 1.0 / (1 + exp(-o1[j]));//x1[j]=1.0/(1.0+exp(-o1[j]-b1[j])); //隐含层各单元输出        
	}

	o2 = 0.0;
	for (int j = 0; j < hidenode; j++)
		o2 = o2 + w2[j] * x1[j];//输出层各单元激活值        
	x2 = 1.0 / (1.0 + exp(-o2)); //  x2[k]=1.0/(1.0+exp(-o2[k]-b2[k]));//输出层各单元输出        
	result = x2;
	return result;
}


//输入样本  可改变,以实现不同函数的模拟      
double X[sample][innode] = {
	{ 1,1,1,-1,1,-1,-1,1,-1 },
	{ 1,-1,-1,1,1,1,1,-1,-1 },
	{ -1,1,-1,-1,1,-1,1,1,1 },
	{ -1,-1,1,1,1,1,-1,-1,1 },
	{ 1,-1,-1,1,-1,-1,1,1,1 },
	{ -1,-1,1,-1,-1,1,1,1,1 },
	{ 1,1,1,-1,-1,1,-1,-1,1 },
	{ 1,1,1,1,-1,-1,1,-1,-1 }
};
//期望输出样本        
double Y[sample] = { 1,1,1,1,0,0,0,0 };


int main()
{
	BpNet bp;
	bp.init();
	int times = 0;
	ofstream out("error.txt");
	ofstream Result("result.txt");
	进行训练,直到误差小于等于allow_e    
	while (bp.error > allow_e)
	{
		bp.e = 0.0;
		times++;
		bp.train(X, Y);
		cout << "Times=" << times << " error=" << bp.error << endl;
		out << bp.error << endl;
	}
	out.close();
	cout << "trainning complete..." << endl;
	进行验证    
	for (int k = 0; k < sample; k++)
	{
		double r = bp.test(X[k]);
		for (int i = 0; i < innode; ++i)
		{
			if (X[k][i] == 1)
				cout << "* ";
			if (X[k][i] == -1)
				cout << "  ";
			if ((i + 1) % 3 == 0)
				cout << endl;
		}
		cout << "的训练结果为";
		cout << bp.result << " ";
		Result << bp.result << endl;
		double cha[sample];
		double mi = 100;
		double index;
		for (int i = 0; i < sample; i++)
		{
			//找差值最小的那个样本        
			cha[i] = (double)(fabs(Y[i] - bp.result));
			if (cha[i] < mi)
			{
				mi = cha[i];
				index = Y[i];  //得到对应的期望输出      
			}
		}
		cout << " 期望输出为 " << index << endl;
		cout << "-------------------------------------" << endl;
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值