//BpNet.h: interface for the Bp class.
// 2006.8.8 by 曾志军 版权所有
//E-Mail:zengzhijun369@163.com
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "BpNet.h"
#include "math.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
BpNet::BpNet()
{
error=1.0;
e=0.0;
rate_w=0.05; //权值学习率(输入层--隐含层)
rate_w1=0.047; //权值学习率 (隐含层--输出层)
rate_b1=0.05; //隐含层阀值学习率
rate_b2=0.047; //输出层阀值学习率
error=1.0;
e=0.0;
rate_w=0.05; //权值学习率(输入层--隐含层)
rate_w1=0.047; //权值学习率 (隐含层--输出层)
rate_b1=0.05; //隐含层阀值学习率
rate_b2=0.047; //输出层阀值学习率
}
BpNet::~BpNet()
{
}
void winit(double w[],int sl)//权值初始化
{int i;
double randx();
for(i=0;i<sl;i++){
*(w+i)=0.2*randx();
}
}
double randx()//kqy error
{double d;
d=(double) rand()/32767.0;
return d;
}
void BpNet::init()
{
winit((double*)w,innode*hidenode);
winit((double*)w1,hidenode*outnode);
winit(b1,hidenode);
winit(b2,outnode);
}
void BpNet::train(double p[trainsample][innode],double t[trainsample][outnode])
{
double pp[hidenode];//隐含结点的校正误差
double qq[outnode];//希望输出值与实际输出值的偏差
double yd[outnode];//希望输出值
double x[innode]; //输入向量
double x1[hidenode];//隐含结点状态值
double x2[outnode];//输出结点状态值
double o1[hidenode];//隐含层激活值
double o2[hidenode];//输出层激活值
for(int isamp=0;isamp<trainsample;isamp++)//循环训练一次样品
{
for(int i=0;i<innode;i++)
x[i]=p[isamp][i];
for(i=0;i<outnode;i++)
yd[i]=t[isamp][i];
//构造每个样品的输入和输出标准
for(int j=0;j<hidenode;j++)
{
o1[j]=0.0;
for(i=0;i<innode;i++)
o1[j]=o1[j]+w[i][j]*x[i];//隐含层各单元输入激活值
x1[j]=1.0/(1+exp(-o1[j]-b1[j]));//隐含层各单元的输出kqy1
// if(o1[j]+b1[j]>0) x1[j]=1;
//else x1[j]=0;
}
for(int k=0;k<outnode;k++)
{
o2[k]=0.0;
for(j=0;j<hidenode;j++)
o2[k]=o2[k]+w1[j][k]*x1[j];//输出层各单元输入激活值
x2[k]=1.0/(1.0+exp(-o2[k]-b2[k]));//输出层各单元输出
// if(o2[k]+b2[k]>0) x2[k]=1;
// else x2[k]=0;
}
for(k=0;k<outnode;k++)
{
e=0.0;
qq[k]=(yd[k]-x2[k])*x2[k]*(1.-x2[k]);//希望输出与实际输出的偏差
e+=fabs(yd[k]-x2[k])*fabs(yd[k]-x2[k]);//计算均方差
for(j=0;j<hidenode;j++)
w1[j][k]=w1[j][k]+rate_w1*qq[k]*x1[j];//下一次的隐含层和输出层之间的新连接权
e=sqrt(e);
error=e;
}
for(j=0;j<hidenode;j++)
{
pp[j]=0.0;
for(k=0;k<outnode;k++)
pp[j]=pp[j]+qq[k]*w1[j][k];
pp[j]=pp[j]*x1[j]*(1-x1[j]);//隐含层的校正误差
for(i=0;i<innode;i++)
w[i][j]=w[i][j]+rate_w*pp[j]*x[i];//下一次的输入层和隐含层之间的新连接权
}
for(k=0;k<outnode;k++)
b2[k]=b2[k]+rate_b2*qq[k];//下一次的隐含层和输出层之间的新阈值
for(j=0;j<hidenode;j++)
b1[j]=b1[j]+rate_b1*pp[j];//下一次的输入层和隐含层之间的新阈值
}//end isamp样品循环
}
///////////////////////////end train/////////////////////////////
/////////////////////////////////////////////////////////////////
double *BpNet::recognize(double *p)
{
double x[innode]; //输入向量
double x1[hidenode];//隐含结点状态值
double x2[outnode];//输出结点状态值
double o1[hidenode];//隐含层激活值
double o2[hidenode];//输出层激活值
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]+w[i][j]*x[i];//隐含层各单元激活值
x1[j]=1.0/(1.0+exp(-o1[j]-b1[j]));//隐含层各单元输出
//if(o1[j]+b1[j]>0) x1[j]=1;
// else x1[j]=0;
}
for(int k=0;k<outnode;k++)
{
o2[k]=0.0;
for(int j=0;j<hidenode;j++)
o2[k]=o2[k]+w1[j][k]*x1[j];//输出层各单元激活值
x2[k]=1.0/(1.0+exp(-o2[k]-b2[k]));//输出层各单元输出
//if(o2[k]+b2[k]>0) x2[k]=1;
//else x2[k]=0;
}
for(k=0;k<outnode;k++)
{
shuchu[k]=x2[k];
}
return shuchu;
}////////////////////////////end sim///////////////////////////
void BpNet::writetrain()
{//曾志军 for 2006.7
AfxMessageBox("你还没有训练呢,训练后再写吧!请不要乱写,除非你认为这次训练是最好的,否则会覆盖我训练好的权值,那样你又要花时间训练!");
AfxMessageBox("你认为这次训练结果是最好的,就存下来,下次就不要花时间训练了!",MB_YESNO,NULL);
FILE *stream0;
FILE *stream1;
FILE *stream2;
FILE *stream3;
int i,j;
////////////////////////
if(( stream0 = fopen("w.txt", "w+" ))==NULL)
{
AfxMessageBox("创建文件失败!");
}
for(i=0;i<innode;i++)
{
for(j=0;j<hidenode;j++)
{
fprintf(stream0, "%f\n", w[i][j]);
}
}
fclose( stream0);
///////////////////////////////////
if(( stream1 = fopen("w1.txt", "w+" ))==NULL)
{
AfxMessageBox("创建文件失败!");
}
for(i=0;i<hidenode;i++)
{
for(j=0;j<outnode;j++)
{
fprintf(stream1, "%f\n",w1[i][j]);
}
}
fclose( stream1);
////////////////////////////
if(( stream2 = fopen("b1.txt", "w+" ))==NULL)
{
AfxMessageBox("创建文件失败!");
}
for(i=0;i<hidenode;i++)
{
fprintf(stream2, "%f\n",b1[i]);
}
fclose( stream2);
/////////////////////////
if(( stream3 = fopen("b2.txt", "w+" ))==NULL)
{
AfxMessageBox("创建文件失败!");
}
for(i=0;i<outnode;i++)
{
fprintf(stream3, "%f\n",b2[i]);
}
fclose( stream3);
}
void BpNet::readtrain()
{
//曾志军 for 2006.7
AfxMessageBox("读入已训练好的权值,这样你就不要花时间训练了!",MB_YESNO,NULL);
FILE *stream0;
FILE *stream1;
FILE *stream2;
FILE *stream3;
int i,j;
/////////////////
if(( stream0 = fopen("w.txt", "r" ))==NULL)
{
AfxMessageBox("文件不存在,请先写入权值,再读!");
}
float wx[innode][hidenode];
for(i=0;i<innode;i++)
for(j=0;j<hidenode;j++)
{
fscanf(stream0, "%f", &wx[i][j]);
w[i][j]=wx[i][j];
}
fclose( stream0);
///////////////////////////////////////////////
if(( stream1 = fopen("w1.txt", "r" ))==NULL)
{
AfxMessageBox("文件不存在,请先写入权值,再读!");
}
float wx1[hidenode][outnode];
for(i=0;i<hidenode;i++)
{
for(j=0;j<outnode;j++)
{
fscanf(stream1, "%f", &wx1[i][j]);
w1[i][j]=wx1[i][j];
}
}
fclose( stream1);
///////////////////
if(( stream2 = fopen("b1.txt", "r" ))==NULL)
{
AfxMessageBox("文件不存在,请先写入权值,再读!");
}
float xb1[hidenode];
for(i=0;i<hidenode;i++)
{
fscanf(stream2, "%f",&xb1[i]);
b1[i]=xb1[i];
}
fclose( stream2);
//////////////////////////
if(( stream3 = fopen("b2.txt", "r" ))==NULL)
{
AfxMessageBox("文件不存在,请先写入权值,再读!");
}
float xb2[outnode];
for(i=0;i<outnode;i++)
{
fscanf(stream3, "%f",&xb2[i]);
b2[i]=xb2[i];
}
fclose( stream3);
/*CFile TheFile("w.txt",CFile::modeRead);
CArchive ar(&TheFile,CArchive::load,40960);
TheFile.SeekToBegin();
int i,j;
for(i=0;i<innode;i++)
{
for(j=0;j<hidenode;j++)
{
ar>>w[i][j];
}
}
ar.Close();
TheFile.Close();*/
}
//BpNet.h: interface for the Bp class.
// 2006.8.8 by 曾志军 版权所有
//E-Mail:zengzhijun369@163.com
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_BPNET_H__3A171E41_1E8B_11D7_BA67_936006E9954B__INCLUDED_)
#define AFX_BPNET_H__3A171E41_1E8B_11D7_BA67_936006E9954B__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define innode 5 //输入结点数
#define hidenode 10//隐含结点数
#define outnode 4 //输出结点数
#define trainsample 500//BP训练样本为10个
class BpNet
{
public:
void train(double p[trainsample][innode ],double t[trainsample][outnode]);//Bp训练
//double p[trainsample][innode] //输入的样本
//double t[trainsample][outnode]//样本要输出的
//Bp训练前要调用readtemplate()
double *recognize(double *p);//Bp识别
void writetrain();//写训练完的权值
void readtrain();//读训练好的权值,这使的不用每次去训练了,只要把训练最好的权值存下来writetrain()就OK!
BpNet();
virtual ~BpNet();
public:
void init();
double w[innode][hidenode];//隐含结点权值
double w1[hidenode][outnode];//输出结点权值
double b1[hidenode];//隐含结点阀值
double b2[outnode];//输出结点阀值
double rate_w; //权值学习率(输入层-隐含层)
double rate_w1;//权值学习率 (隐含层-输出层)
double rate_b1;//隐含层阀值学习率
double rate_b2;//输出层阀值学习率
double e;//误差计算
double error;//允许的最大误差
double shuchu[outnode];// Bp输出
};
#endif // !defined(AFX_BPNET_H__3A171E41_1E8B_11D7_BA67_936006E9954B__INCLUDED_)
// 2006.8.8 by 曾志军 版权所有
//E-Mail:zengzhijun369@163.com
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "BpNet.h"
#include "math.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
BpNet::BpNet()
{
error=1.0;
e=0.0;
rate_w=0.05; //权值学习率(输入层--隐含层)
rate_w1=0.047; //权值学习率 (隐含层--输出层)
rate_b1=0.05; //隐含层阀值学习率
rate_b2=0.047; //输出层阀值学习率
error=1.0;
e=0.0;
rate_w=0.05; //权值学习率(输入层--隐含层)
rate_w1=0.047; //权值学习率 (隐含层--输出层)
rate_b1=0.05; //隐含层阀值学习率
rate_b2=0.047; //输出层阀值学习率
}
BpNet::~BpNet()
{
}
void winit(double w[],int sl)//权值初始化
{int i;
double randx();
for(i=0;i<sl;i++){
*(w+i)=0.2*randx();
}
}
double randx()//kqy error
{double d;
d=(double) rand()/32767.0;
return d;
}
void BpNet::init()
{
winit((double*)w,innode*hidenode);
winit((double*)w1,hidenode*outnode);
winit(b1,hidenode);
winit(b2,outnode);
}
void BpNet::train(double p[trainsample][innode],double t[trainsample][outnode])
{
double pp[hidenode];//隐含结点的校正误差
double qq[outnode];//希望输出值与实际输出值的偏差
double yd[outnode];//希望输出值
double x[innode]; //输入向量
double x1[hidenode];//隐含结点状态值
double x2[outnode];//输出结点状态值
double o1[hidenode];//隐含层激活值
double o2[hidenode];//输出层激活值
for(int isamp=0;isamp<trainsample;isamp++)//循环训练一次样品
{
for(int i=0;i<innode;i++)
x[i]=p[isamp][i];
for(i=0;i<outnode;i++)
yd[i]=t[isamp][i];
//构造每个样品的输入和输出标准
for(int j=0;j<hidenode;j++)
{
o1[j]=0.0;
for(i=0;i<innode;i++)
o1[j]=o1[j]+w[i][j]*x[i];//隐含层各单元输入激活值
x1[j]=1.0/(1+exp(-o1[j]-b1[j]));//隐含层各单元的输出kqy1
// if(o1[j]+b1[j]>0) x1[j]=1;
//else x1[j]=0;
}
for(int k=0;k<outnode;k++)
{
o2[k]=0.0;
for(j=0;j<hidenode;j++)
o2[k]=o2[k]+w1[j][k]*x1[j];//输出层各单元输入激活值
x2[k]=1.0/(1.0+exp(-o2[k]-b2[k]));//输出层各单元输出
// if(o2[k]+b2[k]>0) x2[k]=1;
// else x2[k]=0;
}
for(k=0;k<outnode;k++)
{
e=0.0;
qq[k]=(yd[k]-x2[k])*x2[k]*(1.-x2[k]);//希望输出与实际输出的偏差
e+=fabs(yd[k]-x2[k])*fabs(yd[k]-x2[k]);//计算均方差
for(j=0;j<hidenode;j++)
w1[j][k]=w1[j][k]+rate_w1*qq[k]*x1[j];//下一次的隐含层和输出层之间的新连接权
e=sqrt(e);
error=e;
}
for(j=0;j<hidenode;j++)
{
pp[j]=0.0;
for(k=0;k<outnode;k++)
pp[j]=pp[j]+qq[k]*w1[j][k];
pp[j]=pp[j]*x1[j]*(1-x1[j]);//隐含层的校正误差
for(i=0;i<innode;i++)
w[i][j]=w[i][j]+rate_w*pp[j]*x[i];//下一次的输入层和隐含层之间的新连接权
}
for(k=0;k<outnode;k++)
b2[k]=b2[k]+rate_b2*qq[k];//下一次的隐含层和输出层之间的新阈值
for(j=0;j<hidenode;j++)
b1[j]=b1[j]+rate_b1*pp[j];//下一次的输入层和隐含层之间的新阈值
}//end isamp样品循环
}
///////////////////////////end train/////////////////////////////
/////////////////////////////////////////////////////////////////
double *BpNet::recognize(double *p)
{
double x[innode]; //输入向量
double x1[hidenode];//隐含结点状态值
double x2[outnode];//输出结点状态值
double o1[hidenode];//隐含层激活值
double o2[hidenode];//输出层激活值
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]+w[i][j]*x[i];//隐含层各单元激活值
x1[j]=1.0/(1.0+exp(-o1[j]-b1[j]));//隐含层各单元输出
//if(o1[j]+b1[j]>0) x1[j]=1;
// else x1[j]=0;
}
for(int k=0;k<outnode;k++)
{
o2[k]=0.0;
for(int j=0;j<hidenode;j++)
o2[k]=o2[k]+w1[j][k]*x1[j];//输出层各单元激活值
x2[k]=1.0/(1.0+exp(-o2[k]-b2[k]));//输出层各单元输出
//if(o2[k]+b2[k]>0) x2[k]=1;
//else x2[k]=0;
}
for(k=0;k<outnode;k++)
{
shuchu[k]=x2[k];
}
return shuchu;
}////////////////////////////end sim///////////////////////////
void BpNet::writetrain()
{//曾志军 for 2006.7
AfxMessageBox("你还没有训练呢,训练后再写吧!请不要乱写,除非你认为这次训练是最好的,否则会覆盖我训练好的权值,那样你又要花时间训练!");
AfxMessageBox("你认为这次训练结果是最好的,就存下来,下次就不要花时间训练了!",MB_YESNO,NULL);
FILE *stream0;
FILE *stream1;
FILE *stream2;
FILE *stream3;
int i,j;
////////////////////////
if(( stream0 = fopen("w.txt", "w+" ))==NULL)
{
AfxMessageBox("创建文件失败!");
}
for(i=0;i<innode;i++)
{
for(j=0;j<hidenode;j++)
{
fprintf(stream0, "%f\n", w[i][j]);
}
}
fclose( stream0);
///////////////////////////////////
if(( stream1 = fopen("w1.txt", "w+" ))==NULL)
{
AfxMessageBox("创建文件失败!");
}
for(i=0;i<hidenode;i++)
{
for(j=0;j<outnode;j++)
{
fprintf(stream1, "%f\n",w1[i][j]);
}
}
fclose( stream1);
////////////////////////////
if(( stream2 = fopen("b1.txt", "w+" ))==NULL)
{
AfxMessageBox("创建文件失败!");
}
for(i=0;i<hidenode;i++)
{
fprintf(stream2, "%f\n",b1[i]);
}
fclose( stream2);
/////////////////////////
if(( stream3 = fopen("b2.txt", "w+" ))==NULL)
{
AfxMessageBox("创建文件失败!");
}
for(i=0;i<outnode;i++)
{
fprintf(stream3, "%f\n",b2[i]);
}
fclose( stream3);
}
void BpNet::readtrain()
{
//曾志军 for 2006.7
AfxMessageBox("读入已训练好的权值,这样你就不要花时间训练了!",MB_YESNO,NULL);
FILE *stream0;
FILE *stream1;
FILE *stream2;
FILE *stream3;
int i,j;
/////////////////
if(( stream0 = fopen("w.txt", "r" ))==NULL)
{
AfxMessageBox("文件不存在,请先写入权值,再读!");
}
float wx[innode][hidenode];
for(i=0;i<innode;i++)
for(j=0;j<hidenode;j++)
{
fscanf(stream0, "%f", &wx[i][j]);
w[i][j]=wx[i][j];
}
fclose( stream0);
///////////////////////////////////////////////
if(( stream1 = fopen("w1.txt", "r" ))==NULL)
{
AfxMessageBox("文件不存在,请先写入权值,再读!");
}
float wx1[hidenode][outnode];
for(i=0;i<hidenode;i++)
{
for(j=0;j<outnode;j++)
{
fscanf(stream1, "%f", &wx1[i][j]);
w1[i][j]=wx1[i][j];
}
}
fclose( stream1);
///////////////////
if(( stream2 = fopen("b1.txt", "r" ))==NULL)
{
AfxMessageBox("文件不存在,请先写入权值,再读!");
}
float xb1[hidenode];
for(i=0;i<hidenode;i++)
{
fscanf(stream2, "%f",&xb1[i]);
b1[i]=xb1[i];
}
fclose( stream2);
//////////////////////////
if(( stream3 = fopen("b2.txt", "r" ))==NULL)
{
AfxMessageBox("文件不存在,请先写入权值,再读!");
}
float xb2[outnode];
for(i=0;i<outnode;i++)
{
fscanf(stream3, "%f",&xb2[i]);
b2[i]=xb2[i];
}
fclose( stream3);
/*CFile TheFile("w.txt",CFile::modeRead);
CArchive ar(&TheFile,CArchive::load,40960);
TheFile.SeekToBegin();
int i,j;
for(i=0;i<innode;i++)
{
for(j=0;j<hidenode;j++)
{
ar>>w[i][j];
}
}
ar.Close();
TheFile.Close();*/
}
//BpNet.h: interface for the Bp class.
// 2006.8.8 by 曾志军 版权所有
//E-Mail:zengzhijun369@163.com
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_BPNET_H__3A171E41_1E8B_11D7_BA67_936006E9954B__INCLUDED_)
#define AFX_BPNET_H__3A171E41_1E8B_11D7_BA67_936006E9954B__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define innode 5 //输入结点数
#define hidenode 10//隐含结点数
#define outnode 4 //输出结点数
#define trainsample 500//BP训练样本为10个
class BpNet
{
public:
void train(double p[trainsample][innode ],double t[trainsample][outnode]);//Bp训练
//double p[trainsample][innode] //输入的样本
//double t[trainsample][outnode]//样本要输出的
//Bp训练前要调用readtemplate()
double *recognize(double *p);//Bp识别
void writetrain();//写训练完的权值
void readtrain();//读训练好的权值,这使的不用每次去训练了,只要把训练最好的权值存下来writetrain()就OK!
BpNet();
virtual ~BpNet();
public:
void init();
double w[innode][hidenode];//隐含结点权值
double w1[hidenode][outnode];//输出结点权值
double b1[hidenode];//隐含结点阀值
double b2[outnode];//输出结点阀值
double rate_w; //权值学习率(输入层-隐含层)
double rate_w1;//权值学习率 (隐含层-输出层)
double rate_b1;//隐含层阀值学习率
double rate_b2;//输出层阀值学习率
double e;//误差计算
double error;//允许的最大误差
double shuchu[outnode];// Bp输出
};
#endif // !defined(AFX_BPNET_H__3A171E41_1E8B_11D7_BA67_936006E9954B__INCLUDED_)