马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?我要加入
x
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, CString MyFileName)
- {
- Alpha = 0.9;
- Eta = 0.45;
- Gain = 5;
- Error = 0;
- nLayer = NumLayer;
- pLayer = new NeuroLayer[nLayer];
- this->TrainTimes =0;
- fileName = MyFileName;
- //构建网络
- for(INT i=0; i<nLayer; i++)
- {
- pLayer[i].nNode = pNumNodeInEachLayer[i];
- }
- this->nInput = pLayer[0].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(INT j=0; j<pLayer[i].nNode; j++)
- {
- for(INT k=0; k<pLayer[i].nInput; k++)
- {
- pLayer[i].ppWeight[j][k] = (rand()%100-50)/100.0; //随机赋权值(-0.5, 0.5);
- pLayer[i].ppDWeight[j][k] = 0.0;
- }
- }
- }
- }
- // 从文件中读取神经网络的权值
- BOOL CNeuroNet_BP::ReadNetFromFile(void)
- {
- CFile file;
- if(file.Open(fileName, CFile::modeRead)==FALSE)
- {
- return FALSE;
- }
- char *pChar = new char[10];
- 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[nLayer];
- for(INT i=0; i<nLayer; i++)
- {
- file.Read((void*)&pNumNode[i], sizeof(INT));
- }
- ///
- pLayer = new NeuroLayer[nLayer];
- for(INT i=0; i<nLayer; i++)
- {
- pLayer[i].nNode = pNumNode[i];
- }
- this->GenerateNet();
- //给每个神经元赋权值
- for(INT i=0; i<nLayer; i++)
- {
- for(INT j=0; j<pLayer[i].nNode; j++)
- {
- file.Read(pLayer[i].ppWeight[j], pLayer[i].nInput*sizeof(DOUBLE)); //读出每层的所有权值
- file.Read(pLayer[i].ppDWeight[j], pLayer[i].nInput*sizeof(DOUBLE)); //读出每层的所有权值
- //TRACE("pw[%d][%d][0]= %f", i, j, pLayer[i].ppWeight[j]);
- }
- }
-
- return TRUE;
- }
- // 把权值保存到文件
- BOOL CNeuroNet_BP::SaveNetToFile(void)
- {
- INT nTemp = 0;
- char ID[10] = "NeuroBP";
- //char Memo[100] = "未说明";
-
- 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[i].nNode), sizeof(INT));
- }
- //写入每层所有节点的权值
- for(INT i=0; i<nLayer; i++)
- {
- for(INT j=0; j<pLayer[i].nNode; j++)
- {
- file.Write(pLayer[i].ppWeight[j], pLayer[i].nInput*sizeof(DOUBLE));
- file.Write(pLayer[i].ppDWeight[j], pLayer[i].nInput*sizeof(DOUBLE));
- //TRACE("pw[%d][%d][0]= %f", i, j, pLayer[i].ppWeight[j]);
- }
- }
- 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[i].pInput = this->pInput;
- }
- else
- {
- pLayer[i].pInput = pLayer[i-1].pOutput;
- }
- for(INT j=0; j<pLayer[i].nNode; j++)
- {
- pLayer[i].pOutput[j] = func(i, j);
- TRACE("pOut[%d][%d]=\t%f\t", i, j, pLayer[i].pOutput[j]);
- }
- }
- return TRUE;
- }
- // 节点转移函数
- DOUBLE CNeuroNet_BP::func(INT i, INT j)
- {
- DOUBLE sigma = 0.0;
- for(INT k=0; k<pLayer[i].nInput; k++)
- {
- sigma = sigma + pLayer[i].pInput[k] * pLayer[i].ppWeight[j][k];
- }
-
- sigma = 1.0/(1.0 + exp(-sigma*this->Gain));
- return sigma;
- }
- //用样本数据进行训练
- void CNeuroNet_BP::Train(DOUBLE* pInput, DOUBLE* pTeach)
- {
- Propagate(pInput); //处理数据
- ComputeOutputError(pTeach); //计算误差
- BackPropagate(); //反向传播,调整权值
- this->TrainTimes++;
- }
- //******************************************************************************
- // 反 向 传 播 调 整 权 值
- // *****************************************************************************
- // 计算输出误差
- void CNeuroNet_BP::ComputeOutputError(DOUBLE* pTarget)
- {
- DOUBLE Out, Err;
- this->Error=0;
- for(INT i=0; i<pLayer[nLayer-1].nNode; i++)
- {
- Out = pLayer[nLayer-1].pOutput[i];
- Err = pTarget[i] - Out;
- //this->pLayer[nLayer-1].pError[i] = Gain*Out*(1-Out)*Err;
- this->pLayer[nLayer-1].pError[i] = 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[i].nNode; j++)
- {
- Out = pLayer[i].pOutput[j];
- Err = 0;
- for(INT k=0; k<pLayer[i+1].nNode; k++)
- {
- Err += pLayer[i+1].pError[k] * pLayer[i+1].ppWeight[k][j];
- }
-
- pLayer[i].pError[j] = Out * (1-Out) * Err;
- }
- }
- //调整权值
- for(INT i=nLayer-1; i>=0; i--) //层
- {
- for(INT j=0; j<pLayer[i].nNode; j++)
- {
- for(INT k=0; k<pLayer[i].nInput; k++)
- {
- //if(i==0)
- //{
- // Out = pLayer[0].pInput[k];
- //}
- //else
- //{
- Out = pLayer[i].pInput[k];
- //}
- Err = pLayer[i].pError[j];
- pLayer[i].ppWeight[j][k] += this->Eta *Out*Err + this->Alpha*pLayer[i].ppDWeight[j][k];
- pLayer[i].ppDWeight[j][k] = this->Eta *Err * Out + this->Alpha*pLayer[i].ppDWeight[j][k];
- }
- }
- }
- }
- // 构建网络,分配变量空间
- void CNeuroNet_BP::GenerateNet(void)
- {
- for(INT i=0; i<nLayer; i++)
- {
- if(i==0)
- {
- pLayer[i].nInput = this->nInput;
- }
- else
- {
- pLayer[i].nInput = pLayer[i-1].nNode;
- }
- pLayer[i].pOutput = new DOUBLE[pLayer[i].nNode]; //为输出数据分配空间
- pLayer[i].pError = new DOUBLE[pLayer[i].nNode]; //为节点误差分配空间
- pLayer[i].ppWeight = new DOUBLE*[pLayer[i].nNode ]; //给权值的指针分配空间
- pLayer[i].ppDWeight = new DOUBLE*[pLayer[i].nNode ]; //给权值增量分配空间
- for(INT j=0; j<pLayer[i].nNode; j++)
- {
- pLayer[i].ppWeight[j] = new DOUBLE[pLayer[i].nInput]; //给每个节点的权值分配空间
- pLayer[i].ppDWeight[j] = new DOUBLE[pLayer[i].nInput]; //给每个权值增量分配空间
- }
- }
- this->pOutput = pLayer[nLayer-1].pOutput;
- }
复制代码 |