📄 bpnetwork.cpp
字号:
// BpNetwork.cpp: implementation of the CBpNetwork class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "BP.h"
#include "BpNetwork.h"
#include "matlib.h"
#include "iostream.h"
#include "fstream.h"
#include "time.h"
#include "stdlib.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CBpNetwork::CBpNetwork()
{
initM(MATCOM_VERSION);//启用矩阵运算库
}
CBpNetwork::~CBpNetwork()
{
exitM();
delete this;
}
void CBpNetwork::create(Mm mInputData, Mm mTarget, int input, int hidden, int output)
{
int i,j;
srand((unsigned)time(NULL));
//初始化网络基本参数
mSampleInput=zeros(mInputData.rows(),mInputData.cols());
mSampleTarget=zeros(mTarget.rows(),mTarget.cols());
mSampleInput=mInputData;
mSampleTarget=mTarget;
this->input=input;
this->hidden=hidden;
this->output=output;
//初始化单个样本矩阵
this->mInput=zeros(input,1);
//初始化隐层数据
this->mHidden=zeros(hidden,1);
//初始化输出层数据
this->mOutput=zeros(output,1);
//创建权值矩阵
this->mWeighti=zeros(this->hidden,this->input);
this->mWeighto=zeros(this->output,this->hidden);
for(i=1;i<=hidden;i++)
for(j=1;j<=input;j++)
this->mWeighti.r(i,j)=randData(-1.0,1.0);
for(i=1;i<=output;i++)
for(j=1;j<=hidden;j++)
this->mWeighto.r(i,j)=randData(-1.0,1.0);
//创建阙值矩阵
this->mThresholdi=zeros(this->hidden,1);
for(i=1;i<=hidden;i++)
this->mThresholdi.r(i,1)=randData(-1.0,1.0);
this->mThresholdo=zeros(this->output,1);
for(i=1;i<=output;i++)
this->mThresholdo.r(i,1)=randData(-1.0,1.0);
//误差矩阵
mOutputDeltas=zeros(output,1);
mHiddenDeltas=zeros(hidden,1);
//学习速率赋值
learnRate1=0.5;
learnRate2=0.5;
m_isOk=false;
m_isStop=false;
dblMse=1.0e-6;
dblError=1.0;
}
void CBpNetwork::forward(int iSample)//前馈
{
if(iSample<0||iSample>mSampleInput.cols())
{
AfxMessageBox("输入错误");
return;
}
int i,j;
double temp=0.0;
//输入层数据
for(i=1;i<=input;i++)
mInput.r(i,1)=mSampleInput.r(i,iSample);
//隐层数据
for(i=1;i<=hidden;i++)
{
temp=0.0;
for(j=1;j<=input;j++)
{
temp+=mWeighti.r(i,j)*mInput.r(j,1);
}
temp+=mThresholdi.r(i,1);
mHidden.r(i,1)=f(temp);
}
//输出
for(i=1;i<=output;i++)
{
temp=0.0;
for(j=1;j<=hidden;j++)
{
temp+=mWeighto.r(i,j)*mHidden.r(j,1);
}
temp+=mThresholdo.r(i,1);
mOutput.r(i,1)=f(temp);
}
}
void CBpNetwork::backward(int iSample)
{
if(iSample<0||iSample>mSampleInput.cols())
{
AfxMessageBox("输入错误");
return;
}
int i,j;
double sum;
//输出层敏感性
for(i=1;i<=output;i++)
mOutputDeltas.r(i,1)=(-2)*f_1(mOutput.r(i,1))*(mSampleTarget.r(i,iSample)-mOutput.r(i,1));
//隐层敏感性
for(i=1;i<=hidden;i++)
{
sum=0.0;
for(j=1;j<=output;j++)
{
sum+=changeMm(mWeighto).r(i,j)*mOutputDeltas.r(j,1);
}
mHiddenDeltas.r(i,1)=f_1(mHidden.r(i,1))*sum;
}
for(i=1;i<=hidden;i++)
{
for(j=1;j<=output;j++)
{
mWeighto.r(j,i)-=learnRate2*mOutputDeltas.r(j,1)*changeMm(mHidden).r(1,i);
}
}
for(i=1;i<=input;i++)
{
for(j=1;j<=hidden;j++)
{
mWeighti.r(j,i)-=learnRate1*mHiddenDeltas.r(j,1)*changeMm(mInput).r(1,i);
}
}
for(j=1;j<=output;j++)
mThresholdo.r(j,1)-=learnRate2*mOutputDeltas.r(j,1);
for(i=1;i<=hidden;i++)
mThresholdi.r(i,1)-=learnRate1*mHiddenDeltas.r(i,1);
dblError=0.0;
for(i=1;i<=output;i++)
dblError+=0.5*(mSampleTarget.r(i,iSample)-mOutput.r(i,1))*(mSampleTarget.r(i,iSample)-mOutput.r(i,1));
}
//学习
void CBpNetwork::learn()
{
int iSample=1;
double dblTotal;
if(m_isStop)
m_isStop=false;
while(dblError>dblMse && !m_isStop){
dblTotal=0.0;
for(iSample=1;iSample<=mSampleInput.cols();iSample++){
forward(iSample);
backward(iSample);
dblTotal+=dblError;//总误差
}
if(dblTotal/dblError>1.04){//动态改变学习速率
learnRate1*=0.7;
learnRate2*=0.7;
}
else{
learnRate1*=1.05;
learnRate2*=1.05;
}
dblError=dblTotal;
}
if(dblError<=dblMse)
{
m_isOk=true;
save();
AfxMessageBox("训练结束");
}
else
m_isOk=false;
}
//停止训练
void CBpNetwork::stop()
{
m_isStop=true;
}
//矩阵转置
Mm CBpNetwork::changeMm(Mm temp)
{
Mm change;
int i,j,row,col;
row=temp.rows();
col=temp.cols();
change=zeros(col,row);
for(i=1;i<=row;i++)
for(j=1;j<=col;j++)
change.r(j,i)=temp.r(i,j);
return change;
}
void CBpNetwork::save()
{
int i,j;
ofstream wfile("c:\\权值.txt",ios::out);
ofstream bfile("c:\\偏置值.txt",ios::out);
wfile<<"输入层与隐含层之间的权\n";
for(i=1;i<=hidden;i++)
{
for(j=1;j<=input;j++)
{
wfile<<mWeighti.r(i,j)<<" ";
}
wfile<<"\n";
}
wfile<<"隐含层与输出层之间的权\n";
for(i=1;i<=output;i++)
{
for(j=1;j<=hidden;j++)
{
wfile<<mWeighto.r(i,j)<<" ";
}
wfile<<"\n";
}
bfile<<"隐层的偏置值为:\n";
for(i=1;i<=hidden;i++)
{
bfile<<mThresholdi.r(i,1)<<" "; //隐层偏置值写入文本
}
bfile<<"\n输出层的偏置值为:\n";
for(i=1;i<=output;i++)
{
bfile<<mThresholdo.r(i,1)<<" "; //输出层偏置值写入文本
}
}
//激活函数导数
double CBpNetwork::f_1(double temp)
{
return (1-temp)*temp;
}
//激活函数
double CBpNetwork::f(double n)
{
return 1.0/(1.0+exp(-n));
}
//随机产生a和b之间的随机数
double CBpNetwork::randData(double a, double b)
{
return((b-a)*rand()+a);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -