📄 bpnn_simulate.cpp
字号:
// BPNN_Simulate.cpp: implementation of the CBPNN_Simulate_Simulate class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "nn_simulate.h"
#include "BPNN_Simulate.h"
#include "math.h"
#include "ProgrApi.h"
#include "mserrors.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
/////////////////////////////////////////////////////////////////////////
CBPNN_Simulate::CBPNN_Simulate()
{
m_dError=0;
m_lHideLayers=0;
m_lInNodes=0;
m_lOutNodes=0;
m_lpHideNodes=NULL;
m_dpInput = NULL;
m_pOutNode=NULL;
m_ppHideNode=NULL;
}
CBPNN_Simulate::~CBPNN_Simulate()
{
Close();
}
/*========================================================================
功能:构造神经网络
参数:(入口)lInputNodes:输入层节点数
(入口)lHideLayers:隐层数,一般隐层数设为1
(入口)lpHideNodes:指向各隐层节点数的指针
返回:成功,返回0;否则,返回错误信息
==========================================================================*/
long CBPNN_Simulate::Create(long lInputNodes,long lHideLayers, long *lpHideNodes)
{
long lErr=0;
int i,j;
//获取输入、输出神经元数及隐层数、各隐层节点数
m_lInNodes=lInputNodes;
m_lOutNodes=1; //输出层节点数设为1
m_lHideLayers=lHideLayers;
m_lpHideNodes=lpHideNodes;
//输入层节点
m_dpInput=new double[lInputNodes];
if(m_dpInput==NULL)
{
lErr=MS_CANNOT_ALLOCMEM;
goto ERROR_END;
}
//输出层节点
m_pOutNode=new NeuralNetNode[m_lOutNodes];
if(m_pOutNode==NULL)
{
lErr=MS_CANNOT_ALLOCMEM;
goto ERROR_END;
}
//隐层节点
m_ppHideNode=new NeuralNetNode *[m_lHideLayers];
if(m_ppHideNode==NULL)
{
lErr=MS_CANNOT_ALLOCMEM;
goto ERROR_END;
}
for(i=0;i<m_lHideLayers;i++)
{
m_ppHideNode[i] =new NeuralNetNode[m_lpHideNodes[i]];
if(m_ppHideNode[i]==NULL)
{
lErr=MS_CANNOT_ALLOCMEM;
goto ERROR_END;
}
}
//第一隐层
for(j=0;j<m_lpHideNodes[0];j++)
{
m_ppHideNode[0][j].pLink=new double[m_lInNodes];
if(m_ppHideNode[0][j].pLink==NULL)
{
lErr=MS_CANNOT_ALLOCMEM;
goto ERROR_END;
}
m_ppHideNode[0][j].pPreLink=new double[m_lInNodes];
if(m_ppHideNode[0][j].pPreLink==NULL)
{
lErr=MS_CANNOT_ALLOCMEM;
goto ERROR_END;
}
}
//其余隐层
for(i=1;i<m_lHideLayers;i++)
for(j=0;j<m_lpHideNodes[i];j++)
{
m_ppHideNode[i][j].pLink=new double[m_lpHideNodes[i-1]];
if(m_ppHideNode[i][j].pLink==NULL)
{
lErr=MS_CANNOT_ALLOCMEM;
goto ERROR_END;
}
m_ppHideNode[i][j].pPreLink=new double[m_lpHideNodes[i-1]];
if(m_ppHideNode[i][j].pPreLink==NULL)
{
lErr=MS_CANNOT_ALLOCMEM;
goto ERROR_END;
}
}
//输出层
for(j=0;j<m_lOutNodes;j++)
{
m_pOutNode[j].pLink=new double[m_lpHideNodes[m_lHideLayers-1]];
if(m_pOutNode[j].pLink==NULL)
{
lErr=MS_CANNOT_ALLOCMEM;
goto ERROR_END;
}
m_pOutNode[j].pPreLink=new double[m_lpHideNodes[m_lHideLayers-1]];
if(m_pOutNode[j].pPreLink==NULL)
{
lErr=MS_CANNOT_ALLOCMEM;
goto ERROR_END;
}
}
ERROR_END:
if(lErr) Close();//如果在构造网络时产生错误,则释放内存
return lErr;
}
//获取一个界于dLow、dHigh之间的随机数
double CBPNN_Simulate::Random(double dLow,double dHigh)
{
double dResult;
dResult = ((double)(rand()%100)/100.0)*(dHigh - dLow) + dLow ;
return dResult;
}
//对各层之间的连接权值进行初始化
void CBPNN_Simulate::Initialize()
{
double dLinkBound[2],dOffBound[2];//连接权值、偏移值的初始化范围
int i,j,k;
//下面四个值是通过实验得到的经验值,也可以对它们在[0,1]之间进行修改。
dLinkBound[0]=0.0;//连接权值的下界
dLinkBound[1]=0.2;//连接权值的上界
dOffBound[0]=0.0;//偏移值的下界
dOffBound[1]=0.1;//偏移值的上界
m_dError=0.0;//误差
//输入层
for(i=0;i<m_lInNodes;i++)
m_dpInput[i]=0.0;
//第一隐层
for(j=0;j<m_lpHideNodes[0];j++)
{
m_ppHideNode[0][j].dOut=0.0;
m_ppHideNode[0][j].dErr=0.0;
m_ppHideNode[0][j].dOff=Random(dOffBound[0],dOffBound[1]);
m_ppHideNode[0][j].dPreOff=0.0;
for(k=0;k<m_lInNodes;k++)
{
m_ppHideNode[0][j].pLink[k]=Random(dLinkBound[0],dLinkBound[1]);
m_ppHideNode[0][j].pPreLink[k]=0.0;
}
}
//其余隐层
for(i=1;i<m_lHideLayers;i++)
for(j=0;j<m_lpHideNodes[i];j++)
{
m_ppHideNode[i][j].dOut=0.0;
m_ppHideNode[i][j].dErr=0.0;
m_ppHideNode[i][j].dOff=Random(dOffBound[0],dOffBound[1]);
m_ppHideNode[i][j].dPreOff=0.0;
for(k=0;k<m_lpHideNodes[i-1];k++)
{
m_ppHideNode[i][j].pLink[k]=Random(dLinkBound[0],dLinkBound[1]);
m_ppHideNode[i][j].pPreLink[k]=0.0;
}
}
//输出层
for(j=0;j<m_lOutNodes;j++)
{
m_pOutNode[j].dOut=0.0;
m_pOutNode[j].dErr=0.0;
m_pOutNode[j].dOff=Random(dOffBound[0],dOffBound[1]);
m_pOutNode[j].dPreOff=0.0;
for(k=0;k<m_lpHideNodes[m_lHideLayers-1];k++)
{
m_pOutNode[j].pLink[k]=Random(dLinkBound[0],dLinkBound[1]);
m_pOutNode[j].pPreLink[k]=0.0;
}
}
}
//释放内存
void CBPNN_Simulate::Close()
{
int i,j;
//隐层节点
for(i=0;i<m_lHideLayers;i++)
for(j=0;j<m_lpHideNodes[i];j++)
{
if(m_ppHideNode[i][j].pLink)
{
delete[] m_ppHideNode[i][j].pLink;
m_ppHideNode[i][j].pLink=NULL;
}
if(m_ppHideNode[i][j].pPreLink)
{
delete[] m_ppHideNode[i][j].pPreLink;
m_ppHideNode[i][j].pPreLink=NULL;
}
}
for(i=0;i<m_lHideLayers;i++)
{
if(m_ppHideNode[i])
{
delete[] m_ppHideNode[i];
m_ppHideNode[i]=NULL;
}
}
if(m_ppHideNode)
{
delete[] m_ppHideNode;
m_ppHideNode=NULL;
}
//输出层节点
for(i=0;i<m_lOutNodes;i++)
{
if(m_pOutNode[i].pLink)
{
delete[] m_pOutNode[i].pLink;
m_pOutNode[i].pLink=NULL;
}
if(m_pOutNode[i].pPreLink)
{
delete[] m_pOutNode[i].pPreLink;
m_pOutNode[i].pPreLink=NULL;
}
}
if(m_pOutNode)
{
delete[] m_pOutNode;
m_pOutNode=NULL;
}
//输入层节点
if(m_dpInput)
{
delete[] m_dpInput;
m_dpInput=NULL;
}
}
//=====================================================================//
//功能:输入的前向传播过程,即输入一像元,逐层计算各层输出,直到输出层,
//=====================================================================//
void CBPNN_Simulate::FPInput(double *dpInput)
{
double dInput;//节点总的输入
int i,j,k;
//输入层节点的输入、输出都等于外界输入
for(i=0;i<m_lInNodes;i++)
m_dpInput[i]=dpInput[i];
//第一隐层输入、输出
for(j=0;j<m_lpHideNodes[0];j++)
{
//节点输入 = 输入层各节点输出的加权和+ 节点偏移量
dInput=0;
for(k=0;k<m_lInNodes;k++)
dInput+=m_ppHideNode[0][j].pLink[k]*m_dpInput[k];
dInput+=m_ppHideNode[0][j].dOff;
//节点输出
m_ppHideNode[0][j].dOut=1.0/(1.0+exp(-dInput));
}
//其余隐层输入、输出
for(i=1;i<m_lHideLayers;i++)
for(j=0;j<m_lpHideNodes[i];j++)
{
//节点输入= 前一隐层各节点输出的加权和+ 节点偏移量
dInput=0;
for(k=0;k<m_lpHideNodes[i-1];k++)
dInput+=m_ppHideNode[i][j].pLink[k]*m_ppHideNode[i-1][k].dOut;
dInput+=m_ppHideNode[i][j].dOff;//偏移量
//节点输出
m_ppHideNode[i][j].dOut=1.0/(1.0+exp(-dInput));
}
//输出层输入、输出
for(j=0;j<m_lOutNodes;j++)
{
//节点输入= 最后隐层各节点输出的加权和+ 节点偏移量
dInput=0;
for(k=0;k<m_lpHideNodes[m_lHideLayers-1];k++)
dInput+=m_pOutNode[j].pLink[k]*m_ppHideNode[m_lHideLayers-1][k].dOut;
dInput+=m_pOutNode[j].dOff;//偏移量
//节点输出
m_pOutNode[j].dOut=1.0/(1.0+exp(-dInput));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -