VisualC++实现的BP神经网络类
NeuroNet_BP.cpp#include "StdAfx.h"
#include "neuronet_bp.h"
#include "math.h"
CNeuroNet_BP::CNeuroNet_BP()
{
}
CNeuroNet_BP::CNeuroNet_BP(INT NumLayer, INT* pNumNodeInEachLayer, CStringMyFileName)
{
Alpha = 0.9;
Eta = 0.45;
Gain = 5;
Error = 0;
nLayer = NumLayer;
pLayer = new NeuroLayer;
this->TrainTimes =0;
fileName = MyFileName;
//构建网络
for(INT i=0; i<nLayer; i++)
{
pLayer.nNode = pNumNodeInEachLayer;
}
this->nInput = pLayer.nNode;
//分配网络变量空间
this->GenerateNet();
//随机设定权值
this->RandomWeight();
}
CNeuroNet_BP::~CNeuroNet_BP(void)
{
}
// 随机赋权值
void CNeuroNet_BP::RandomWeight(void)
{
srand(4567);
for(INT i=0; i<nLayer; i++)
{
for(INTj=0; j<pLayer.nNode; j++)
{
for(INT k=0; k<pLayer.nInput; k++)
{
pLayer.ppWeight = (rand()%100-50)/100.0; //随机赋权值(-0.5, 0.5);
pLayer.ppDWeight = 0.0;
}
}
}
}
// 从文件中读取神经网络的权值
BOOL CNeuroNet_BP::ReadNetFromFile(void)
{
CFile file;
if(file.Open(fileName, CFile::modeRead)==FALSE)
{
return FALSE;
}
char *pChar = new char;
file.Read((void*)pChar, 10);
//if(pChar != "NeuroBP")
//{
// return FALSE;
//}
file.Read((void*)&this->TrainTimes, sizeof(DWORD));
file.Read((void*)&this->Error, sizeof(DOUBLE));
file.Read((void*)&this->Alpha, sizeof(DOUBLE));
file.Read((void*)&this->Eta, sizeof(DOUBLE));
file.Read((void*)&this->Gain, sizeof(DOUBLE));
file.Read((void*)&this->nInput, sizeof(INT));
file.Read((void*)&this->nLayer, sizeof(INT));
//读出每层节点数
INT* pNumNode = new INT;
for(INT i=0; i<nLayer; i++)
{
file.Read((void*)&pNumNode, sizeof(INT));
}
///
pLayer = new NeuroLayer;
for(INT i=0; i<nLayer; i++)
{
pLayer.nNode = pNumNode;
}
this->GenerateNet();
//给每个神经元赋权值
for(INT i=0; i<nLayer; i++)
{
for(INT j=0; j<pLayer.nNode; j++)
{
file.Read(pLayer.ppWeight, pLayer.nInput*sizeof(DOUBLE)); //读出每层的所有权值
file.Read(pLayer.ppDWeight, pLayer.nInput*sizeof(DOUBLE)); //读出每层的所有权值
//TRACE("pw[%d][%d]= %f", i, j, pLayer.ppWeight);
}
}
return TRUE;
}
// 把权值保存到文件
BOOL CNeuroNet_BP::SaveNetToFile(void)
{
INT nTemp = 0;
char ID = "NeuroBP";
//char Memo = "未说明";
HANDLE hFile = CreateFile(_T(fileName),
GENERIC_WRITE, FILE_SHARE_READ,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
AfxMessageBox(_T("Couldn't create the file!"));
return FALSE;
}
// Attach a CFile object to the handle we have.
CFile file(hFile);
file.Write((void*)ID, 10); //写入文件类型标记
//file.Write((void*)Memo, 100); //写入描述参数
file.Write((void*)&TrainTimes, sizeof(DWORD)); //写入已训练次数
file.Write((void*)&this->Error, sizeof(DOUBLE)); //写入最近的系统误差
file.Write((void*)&this->Alpha, sizeof(DOUBLE));
file.Write((void*)&this->Eta, sizeof(DOUBLE));
file.Write((void*)&this->Gain, sizeof(DOUBLE));
file.Write(&(this->nInput), sizeof(INT)); //写入输入数据宽度
file.Write(&(this->nLayer), sizeof(INT));
//写入每层节点数
for(INT i=0; i<nLayer; i++)
{
file.Write(&(pLayer.nNode), sizeof(INT));
}
//写入每层所有节点的权值
for(INT i=0; i<nLayer; i++)
{
for(INT j=0; j<pLayer.nNode; j++)
{
file.Write(pLayer.ppWeight,pLayer.nInput*sizeof(DOUBLE));
file.Write(pLayer.ppDWeight,pLayer.nInput*sizeof(DOUBLE));
//TRACE("pw[%d][%d]= %f", i, j, pLayer.ppWeight);
}
}
file.Close();
return TRUE;
}
// 处理输入数据,产生输出
BOOL CNeuroNet_BP::Propagate( DOUBLE*pInput)
{
this->pInput = pInput;
//计算输出结果
for(INT i=0; i<this->nLayer; i++)
{
if(i==0)
{
pLayer.pInput = this->pInput;
}
else
{
pLayer.pInput = pLayer.pOutput;
}
for(INT j=0; j<pLayer.nNode; j++)
{
pLayer.pOutput = func(i, j);
TRACE("pOut[%d][%d]=\t%f\t", i, j, pLayer.pOutput);
}
}
return TRUE;
}
// 节点转移函数
DOUBLECNeuroNet_BP::func(INT i, INT j)
{
DOUBLE sigma = 0.0;
for(INT k=0; k<pLayer.nInput; k++)
{
sigma = sigma + pLayer.pInput * pLayer.ppWeight;
}
sigma = 1.0/(1.0 + exp(-sigma*this->Gain));
return sigma;
}
//用样本数据进行训练
voidCNeuroNet_BP::Train(DOUBLE* pInput, DOUBLE* pTeach)
{
Propagate(pInput); //处理数据
ComputeOutputError(pTeach); //计算误差
BackPropagate(); //反向传播,调整权值
this->TrainTimes++;
}
//******************************************************************************
// 反 向 传 播 调 整 权 值
// *****************************************************************************
// 计算输出误差
voidCNeuroNet_BP::ComputeOutputError(DOUBLE* pTarget)
{
DOUBLE Out, Err;
this->Error=0;
for(INT i=0; i<pLayer.nNode; i++)
{
Out = pLayer.pOutput;
Err = pTarget - Out;
//this->pLayer.pError = Gain*Out*(1-Out)*Err;
this->pLayer.pError = Out*(1-Out)*Err;
this->Error += 0.5*pow(Err, 2);
}
}
//反向传播误差
void CNeuroNet_BP::BackPropagate(void)
{
DOUBLE Out, Err;
//反向计算误差
for(INT i=nLayer-2; i>=0; i--)
{
for(INT j=0; j<pLayer.nNode; j++)
{
Out = pLayer.pOutput;
Err = 0;
for(INT k=0; k<pLayer.nNode; k++)
{
Err += pLayer.pError * pLayer.ppWeight;
}
pLayer.pError = Out * (1-Out) * Err;
}
}
//调整权值
for(INT i=nLayer-1; i>=0; i--) //层
{
for(INT j=0; j<pLayer.nNode; j++)
{
for(INT k=0; k<pLayer.nInput; k++)
{
//if(i==0)
//{
// Out = pLayer.pInput;
//}
//else
//{
Out = pLayer.pInput;
//}
Err = pLayer.pError;
pLayer.ppWeight += this->Eta *Out*Err + this->Alpha*pLayer.ppDWeight;
pLayer.ppDWeight = this->Eta *Err * Out + this->Alpha*pLayer.ppDWeight;
}
}
}
}
// 构建网络,分配变量空间
void CNeuroNet_BP::GenerateNet(void)
{
for(INT i=0; i<nLayer; i++)
{
if(i==0)
{
pLayer.nInput = this->nInput;
}
else
{
pLayer.nInput = pLayer.nNode;
}
pLayer.pOutput = new DOUBLE.nNode]; //为输出数据分配空间
pLayer.pError = new DOUBLE.nNode]; //为节点误差分配空间
pLayer.ppWeight = new DOUBLE*.nNode ]; //给权值的指针分配空间
pLayer.ppDWeight = new DOUBLE*.nNode ]; //给权值增量分配空间
for(INT j=0; j<pLayer.nNode; j++)
{
pLayer.ppWeight = new DOUBLE.nInput]; //给每个节点的权值分配空间
pLayer.ppDWeight = new DOUBLE.nInput]; //给每个权值增量分配空间
}
}
this->pOutput = pLayer.pOutput;
} NeuroNet_BP.h
#pragma once
//#include "NeuroLayer.h"
/////////////////////////////////////////////////////////
typedef struct NeuroLayer
{
INT nNode; //节点数目
INT nInput; //层的输入
DOUBLE *pInput; //层的输入
DOUBLE *pOutput; //层的输出
DOUBLE *pError; //层的误差
DOUBLE **ppWeight; //权值
DOUBLE **ppDWeight;
} NeuroLayer;
//////////////////////////////////////////////////////////
class CNeuroNet_BP
{
public:
CNeuroNet_BP();
CNeuroNet_BP(INT NumLayer, INT* pNumNodeInEachLayer, CStringMyFileName);
~CNeuroNet_BP(void);
INT nInput; //一个输入样本的数据数目
DOUBLE *pInput; //系统的输入
DOUBLE *pOutput; //系统的输出
INT nLayer; //网络的层数
NeuroLayer *pLayer; //指向各层的指针
DOUBLE Eta; //学习效率
DOUBLE Alpha; //冲量因子
DOUBLE Error; //系统总体误差
DOUBLE Gain; //S形函数的增益
DWORD TrainTimes; //训练次数
CString fileName;
private:
public:
BOOL ReadNetFromFile(void); // 从文件中读取神经网络
BOOL SaveNetToFile(void); // 把神经网络保存到文件
public:
// 处理输入数据,产生输出
BOOL Propagate( DOUBLE*pInput);
// 节点函数
DOUBLEfunc(INT i, INT j);
void Train(DOUBLE* pInput, DOUBLE* pTarget);
// 随机赋权值
void RandomWeight(void);
void BackPropagate(void);
// 计算输出误差
void ComputeOutputError(DOUBLE* pTarget);
// 构建网络,分配变量空间
void GenerateNet(void);
// 显示网络信息
};
页:
[1]