// BpNet.cpp : implementation file
////////////////////////////////////////////////////////////////////
/////////////////人工神经网络BP算法/////////////////////////////////
//1、动态改变学习速率
//2、加入动量项
//3、运用了Matcom4.5的矩阵运算库(可免费下载,头文件matlib.h),
// 方便矩阵运算,当然,也可自己写矩阵类
//4、可暂停运算
//5、可将网络以文件的形式保存、恢复
///////////////作者:同济大学材料学院 张纯禹//////////////////////
///////////////email:chunyu_79@hotmail.com//////////////////////////
///////////////QQ:53806186//////////////////////////////////////////
///////////////欢迎不断改进!欢迎讨论其他实用的算法!/////////////////
#include "BpNet.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CBpNet
IMPLEMENT_SERIAL( CBpNet, CObject, 1 )
CBpNet::CBpNet()
{initM(MATCOM_VERSION);//启用矩阵运算库
}
CBpNet::~CBpNet()
{exitM();
delete this;
}
/////////////////////////////////////////////////////////////////////////////
// CBpNet message handlers
//创建新网络
void CBpNet::Create(Mm mInputData, Mm mTarget, int iInput, int iHidden, int iOutput)
{ int i,j;
mSampleInput=zeros(mInput.rows(),mInput.cols());
mSampleTarget=zeros(mTarget.rows(),mTarget.cols());
mSampleInput=mInputData;
mSampleTarget=mTarget;
this->iInput=iInput;
this->iHidden=iHidden;
this->iOutput=iOutput;
//创建计算用的单个样本矩阵
mInput=zeros(1,this->iInput);
mHidden=zeros(1,this->iHidden);
mOutput=zeros(1,this->iOutput);
//创建权重矩阵,并赋初值
mWeighti=zeros(this->iInput,this->iHidden);
mWeighto=zeros(this->iHidden,this->iOutput);
//赋初值
for(i=1;i<=this->iInput;i++)
for(j=1;j<=this->iHidden;j++)
mWeighti.r(i,j)=randab(-1.0,1.0);
for(i=1;i<=this->iHidden;i++)
for(j=1;j<=this->iOutput;j++)
mWeighto.r(i,j)=randab(-1.0,1.0);
//创建阙值矩阵,并赋值
mThresholdi=zeros(1,this->iHidden);
for(i=1;i<=this->iHidden;i++)
mThresholdi.r(i)=randab(-1.0,1.0);
mThresholdo=zeros(1,this->iOutput);
for(i=1;i<=this->iOutput;i++)
mThresholdo.r(i)=randab(-1.0,1.0);
//创建权重变化矩阵
mChangei=zeros(this->iInput,this->iHidden);
mChangeo=zeros(this->iHidden,this->iOutput);
mInputNormFactor=zeros(iInput,2);
mTargetNormFactor=zeros(iOutput,2);
//误差矩阵
mOutputDeltas=zeros(iOutput);
mHiddenDeltas=zeros(iHidden);
//学习速率赋值
dblLearnRate1=0.5;
dblLearnRate2=0.5;
dblMomentumFactor=0.95;
m_isOK=false;
m_IsStop=false;
dblMse=1.0e-6;//误差限
dblError=1.0;
lEpochs=0;
}
//根据已有的网络进行预测
Mm CBpNet::simulate(Mm mData)
{int i,j;
Mm mResult;
Mm data=zeros(mData.rows(),mData.cols());
data=mData;
if(mData.cols()!=iInput)
{::MessageBox(NULL,"输入数据变量个数错误!","输入数据变量个数错误!",MB_OK);
return mResult;
}
mResult=zeros(data.rows(),iOutput);
//正规化数据
for(i=1;i<=data.rows();i++)
for(j=1;j<=data.cols();j++)
data.r(i,j)=(data.r(i,j)-mInputNormFactor.r(j,1))/(mInputNormFactor.r(j,2)-mInputNormFactor.r(j,1));
//计算
int iSample;
Mm mInputdata,mHiddendata,mOutputdata;
mInputdata=zeros(1,iInput);
mHiddendata=zeros(1,iHidden);
mOutputdata=zeros(1,iOutput);
double sum=0.0;
for(iSample=1;iSample<=data.rows();iSample++){
//输入层数据
for(i=1;i<=iInput;i++)
mInputdata.r(i)=data.r(iSample,i);
//隐层数据
for(j=1;j<=iHidden;j++){
sum=0.0;
for(i=1;i<=iInput;i++)
sum+=mInputdata.r(i)*mWeighti.r(i,j);
sum-=mThresholdi.r(j);
mHiddendata.r(j)=1.0/(1.0+exp(-sum));
}
//输出数据
for(j=1;j<=iOutput;j++){
sum=0.0;
for(i=1;i<=iHidden;i++)
sum+=mHiddendata.r(i)*mWeighto.r(i,j);
sum-=mThresholdo.r(j);
mOutputdata.r(j)=1.0/(1.0+exp(-sum));
}
//转换
for(j=1;j<=iOutput;j++)
mResult.r(iSample,j)=mOutputdata.r(j)*(mTargetNormFactor.r(j,2)-mTargetNormFactor.r(j,1))+mTargetNormFactor.r(j,1);
}
return (mResult);
}
void CBpNet::LoadBpNet(CString &strNetName)
{CFile file;
if(file.Open(strNetName,CFile::modeRead)==0)
{MessageBox(NULL,"无法打开文件!","错误",MB_OK);
return;
}
else{
CArchive myar(&file,CArchive::load);
Serialize(myar);
myar.Close();
}
file.Close();
}
bool CBpNet::SaveBpNet(CString &strNetName)
{CFile file;
if(strNetName.GetLength()==0)
return(false);
if(file.Open(strNetName,CFile::modeCreate|CFile::modeWrite)==0)
{MessageBox(NULL,"无法创建文件!","错误",MB_OK);
return(false);
}
else{
CArchive myar(&file,CArchive::store);
Serialize(myar);
myar.Close();
}
file.Close();
return(true);
}
//网络学习
void CBpNet::learn()
{ int iSample=1;
double dblTotal;
MSG msg;
if(m_IsStop)
m_IsStop=false;
//数据正规化处理
normalize();
while(dblError>dblMse&&!m_IsStop){
dblTotal=0.0;
for(iSample=1;iSample<=mSampleInput.rows();iSample++){
forward(iSample);
backward(iSample);
dblTotal+=dblErr;//总误差
}
if(dblTotal/dblError>1.04){//动态改变学习速率
dblLearnRate1*=0.7;
dblLearnRate2*=0.7;
}
else{
dblLearnRate1*=1.05;
dblLearnRate2*=1.05;
}
lEpochs++;
dblError=dblTotal;
::PeekMessage(&msg,NULL,0,0,PM_REMOVE);
::DispatchMessage(&msg);
msg.message=-1;
::DispatchMessage(&msg);//这样可以消除屏闪和假死机
}
if(dblError<=dblMse)
m_isOK=true;
else
m_isOK=false;
}
void CBpNet::stop()
{
m_IsStop=true;
}
double CBpNet::randab(double a, double b)
{ //注意,如果应用矩阵库,头文件matlib.h对rand()函数重新定义,只产生(0,1)
//之间的随机数
return((b-a)*rand()+a);
}
//将数据转化到(0,1)区间
void CBpNet::normalize()
{
int i,j;
//输入数据范围
mInputNormFactor=scope(mSampleInput);
//目标数据范围
mTargetNormFactor=scope(mSampleTarget);
for(i=1;i<=mSampleInput.rows();i++)
for(j=1;j<=mSampleInput.cols();j++)
mSampleInput.r(i,j)=(mSampleInput.r(i,j)-mInputNormFactor.r(j,1))/(mInputNormFactor.r(j,2)-mInputNormFactor.r(j,1));
for(i=1;i<=mSampleTarget.rows();i++)
for(j=1;j<=mSampleTarget.cols();j++)
mSampleTarget.r(i,j)=(mSampleTarget.r(i,j)-mTargetNormFactor.r(j,1))/(mTargetNormFactor.r(j,2)-mTargetNormFactor.r(j,1));
}
//前向计算
void CBpNet::forward(int iSample)
{//根据第iSample个样本,前向计算
if(iSample<1||iSample>mSampleInput.rows()){
MessageBox(NULL,"无此样本数据:索引出界!","无此样本数据:索引出界!",MB_OK);
return;
}
int i,j;
double sum=0.0;
//输入层数据
for(i=1;i<=iInput;i++)
mInput.r(i)=mSampleInput.r(iSample,i);
//隐层数据
for(j=1;j<=iHidden;j++){
sum=0.0;
for(i=1;i<=iInput;i++)
sum+=mInput.r(i)*mWeighti.r(i,j);
sum-=mThresholdi.r(j);
mHidden.r(j)=1.0/(1.0+exp(-sum));
}
//输出数据
for(j=1;j<=iOutput;j++){
sum=0.0;
for(i=1;i<=iHidden;i++)
sum+=mHidden.r(i)*mWeighto.r(i,j);
sum-=mThresholdo.r(j);
mOutput.r(j)=1.0/(1.0+exp(-sum));
}
}
//后向反馈
void CBpNet::backward(int iSample)
{
if(iSample<1||iSample>mSampleInput.rows()){
MessageBox(NULL,"无此样本数据:索引出界!","无此样本数据:索引出界!",MB_OK);
return;
}
int i,j;
//输出误差
for(i=1;i<=iOutput;i++)
mOutputDeltas.r(i)=mOutput.r(i)*(1-mOutput.r(i))*(mSampleTarget.r(iSample,i)-mOutput.r(i));
//隐层误差
double sum=0.0;
for(j=1;j<=iHidden;j++){
sum=0.0;
for(i=1;i<=iOutput;i++)
sum+=mOutputDeltas.r(i)*mWeighto.r(j,i);
mHiddenDeltas.r(j)=mHidden.r(j)*(1-mHidden.r(j))*sum;
}
//更新隐层-输出权重
double dblChange;
for(j=1;j<=iHidden;j++)
for(i=1;i<=iOutput;i++){
dblChange=mOutputDeltas.r(i)*mHidden.r(j);
mWeighto.r(j,i)=mWeighto.r(j,i)+dblLearnRate2*dblChange+dblMomentumFactor*mChangeo.r(j,i);
mChangeo.r(j,i)=dblChange;
}
//更新输入-隐层权重
for(i=1;i<=iInpu
评论0
最新资源