⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bpnn_simulate.cpp

📁 这是我自己花了很多时间写的一个BP神经网络类
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 + -