📄 bpxor3.0.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 + -