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

📄 bpxor3.0.cpp

📁 用c语言实现的bp神经网络实现异或功能
💻 CPP
字号:
// BPxor3.0.cpp : Defines the entry point for the console application.
//
//---------------------------------------------------------------------
// Copyright (c) 2005 Bobby.  All rights reserved.
//				
// Using BP network to resolve the XOR problem.
// Compiled under Visual C++ .NET 2003.
//
// AUTHOR:		Bobby
// DATE:		May 6 2005
//
//----------------------------------------------------------------------
#include <tchar.h>
//#include "stdafx.h"
#include <iostream>
//#include <fstream>
#include <time.h>
#include <stdlib.h>
#include <math.h>
#define   HN    7              //隐含层神经元个数, 请多次修改其值来进行比较

using namespace std;

void timestart(void);           //获取程序开始运行时的时间
void timeend(void);             //获取程序结束时的时间
double timevalue(void);         //获取程序运行时间

double _tmain(int argc, _TCHAR* argv[])
{
	timestart();

	double x_out[7];                 //输入层的输出值
	double hn_out[HN];               //隐含层的输出值
	double y;                        //输出层的输出值

	double w[7][HN];                 //输入层到隐含层的权值
	double hn_b[HN];                 //隐含层的偏置系数
	double v[HN];                    //隐含层到输出层的权值
	double y_b;                      //输出层的偏置系数

	double hn_delta[HN];             //隐含层的delta
	double y_delta;                  //输出层的delta

	double error;                    //全局误差
	double errlimit=0.001;           //预设的全局误差极限
	double alpha=0.2, beta=0.4;      //预设的学习速率
		
	int loop=0;                      //训练次数
	int times=10000;                 //预设的训练次数上限
	int i, j, m;
	double sumtemp;
	double errtemp;

	struct                           //训练样本对. 对XOR问题, 共有4对
	{
		double input[7];
		double teach;
	}data[2] = {{0  ,  0.1100  ,  0.4164  ,  0.4284  ,  0.9193   , 0.5176  ,  1.0000 ,1},{0,0.1939,0.4520,0.4320,1,0.5660,0.9365 }};

	//-----------------------------------------------------------
	//初始化. 将连接权值、偏置系数置为(-1,1)之间的随机数
	cout<<"initializing............"<<endl;
	srand((unsigned)time(NULL));
	for(i=0; i<3; i++)
		for(j=0; j<HN; j++)
		{
			w[i][j] = ((double)rand()/32767.0)*2-1;    //输入层隐含层权值矩阵赋(-1,1)的随机数
			cout<<"w["<<i+1<<"]["<<j+1<<"]="<<w[i][j]<<endl;  //显示随机数
		}
	for(i=0; i<HN; i++)
	{
		hn_b[i] = ((double)rand()/32767.0)*2-1;     //隐含层偏置系数赋随机数
		cout<<"hn_b["<<i+1<<"]="<<hn_b[i]<<endl;		
	}
	for(i=0; i<HN; i++)
	{		
		v[i] = ((double)rand()/32767.0)*2-1;      //隐含层到输出层权值矩阵赋(-1,1)的随机值
		cout<<"v["<<i+1<<"]="<<v[i]<<endl;
	}
	y_b = ((double)rand()/32767.0)*2-1;          //输出层的偏置系数
	cout<<"y_b="<<y_b<<endl;

	//------------------------------------------------------------
	//训练.
	cout<<endl<<"training beginning............"<<endl;
	while(loop < times)
	{
		loop++;
		error = 0.0;
		
		for(m=0; m<1; m++)                     //对4个样本进行增量训练
		{
			//输入正向传播
			for(i=0; i<7; i++)                 //设置输入层的输出
				x_out[i] = data[m].input[i];
			for(i=0; i<HN; i++)                //计算隐含层的输出
			{
				sumtemp = 0.0;
				for(j=0; j<7; j++)
					sumtemp += w[j][i] * x_out[j];
				sumtemp =sumtemp+ hn_b[i];
				hn_out[i] = tanh(sumtemp);     //隐含层作用函数为y=tanh(x)
			}
			sumtemp = 0.0;                     //计算输出层的输出
			for(i=0; i<HN; i++)
				sumtemp += v[i] * hn_out[i];
			sumtemp = sumtemp+y_b;
			y = sumtemp;                       //输出层作用函数为y=x

			//误差反向传播			
			errtemp = data[m].teach - y;    
			error += (0.5 * errtemp * errtemp);//所有样本的全局误差
			y_delta = errtemp;                 //计算输出层的delta
			for(i=0; i<HN; i++)                //计算隐含层的delta
			{
				errtemp = 0.0;
				errtemp += y_delta * v[i];
				hn_delta[i] = errtemp * (1.0 + hn_out[i]) * (1.0 - hn_out[i]);
			}
			for(i=0; i<HN; i++)                //调整输出层的权值和偏置系数
				v[i] += alpha * y_delta * hn_out[i];//偏置系数既是指阀值
            y_b += alpha * y_delta;
			for(i=0; i<HN; i++)                //调整隐含层的权值和偏置系数
			{
				for(j=0; j<7; j++)
				{
					w[j][i] += beta * hn_delta[i] * x_out[j];
				}
				hn_b[i] += beta * hn_delta[i]; 
			}
		}		

		//全局误差判断
		//cout<<"全局误差Error="<<error<<endl;
		if(error < errlimit)
			break;
	}

	//----------------------------------------------------------------
    //输出训练结果
	cout<<endl<<"training completion............"<<endl;
	cout<<"HN="<<HN<<endl;
	cout<<"Error="<<error<<endl;
	cout<<"Loop="<<loop<<endl;
    for(i=0; i<7; i++)
		for(j=0; j<HN; j++)
		{
			cout<<"w["<<i+1<<"]["<<j+1<<"]="<<w[i][j]<<endl;
		}
	for(i=0; i<HN; i++)
	{
		cout<<"hn_b["<<i+1<<"]="<<hn_b[i]<<endl;		
	}
	for(i=0; i<HN; i++)
	{	
		cout<<"v["<<i+1<<"]="<<v[i]<<endl;
	}	
	cout<<"y_b="<<y_b<<endl;

	//------------------------------------------------------------------
	//利用上面训练得到的权值和偏置系数进行检验
	cout<<endl<<"testing............"<<endl;
	for(m=0; m<1; m++)                     //对4个样本分别检验其实际输出
	{
		for(i=0; i<7; i++)                 //设置输入层的输出
		{
			x_out[i] = data[m].input[i];
			cout<<"data["<<m+1<<"].x["<<i+1<<"]="<<data[m].input[i]<<endl;
		}
		for(i=0; i<HN; i++)                //计算隐含层的输出
		{
			sumtemp = 0.0;
			for(j=0; j<7; j++)
				sumtemp += w[j][i] * x_out[j];
			sumtemp += hn_b[i];
			hn_out[i] = tanh(sumtemp);     //隐含层作用函数为y=tanh(x)
		}
		sumtemp = 0.0;                     //计算输出层的输出
		for(i=0; i<HN; i++)
			sumtemp += v[i] * hn_out[i];
		sumtemp += y_b;
		y = sumtemp;                       //输出层作用函数为y=x
		cout<<"data["<<m+1<<"].y="<<y<<endl;
	}

	timeend();
	cout<<endl<< "the code running time(by Win32 function)="<<timevalue()<<"s"<<endl;
for(m=1; m<2; m++)                     //对4个样本分别检验其实际输出
	{
		for(i=0; i<7; i++)                 //设置输入层的输出
		{
			x_out[i] = data[m].input[i];
			cout<<"data["<<m+1<<"].x["<<i+1<<"]="<<data[m].input[i]<<endl;
		}
		for(i=0; i<HN; i++)                //计算隐含层的输出
		{
			sumtemp = 0.0;
			for(j=0; j<7; j++)
				sumtemp += w[j][i] * x_out[j];
			sumtemp += hn_b[i];
			hn_out[i] = tanh(sumtemp);     //隐含层作用函数为y=tanh(x)
		}
		sumtemp = 0.0;                     //计算输出层的输出
		for(i=0; i<HN; i++)
			sumtemp += v[i] * hn_out[i];
		sumtemp += y_b;
		y = sumtemp;                       //输出层作用函数为y=x
		cout<<"data["<<m+1<<"].y="<<y<<endl;
	}

	return 0;
}

//----------------------------------------------------------------
//测量程序运行时间的函数(包括Windows和Linux两个版本) - by Edward G. Bradford
#ifdef _WIN32
#include <Windows.h>
static LARGE_INTEGER _timestart, _timeend;
static LARGE_INTEGER freq;

void timestart(void)
{
    static int first = 1;

    if(first) 
	{
        QueryPerformanceFrequency(&freq);
        first = 0;
    }
    QueryPerformanceCounter(&_timestart);
}
void timeend(void)
{
    QueryPerformanceCounter(&_timeend);
}
double timevalue(void)
{
    return ((double)_timeend.QuadPart - (double)_timestart.QuadPart)/((double)freq.QuadPart);
}

#else
#include <sys/utsname.h>
static struct timeval _timestart, _timeend;
static struct timezone tz;

void timestart(void)
{
    gettimeofday(&_timestart, &tz);
}
void timeend(void)
{
    gettimeofday(&_timeend,&tz);
}
double timevalue(void)
{
    double t1, t2;

    t1 =  (double)_timestart.tv_sec + (double)_timestart.tv_usec/(1000*1000);
    t2 =  (double)_timeend.tv_sec + (double)_timeend.tv_usec/(1000*1000);
    return t2-t1;
}
#endif

⌨️ 快捷键说明

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