声振论坛

 找回密码
 我要加入

QQ登录

只需一步,快速开始

查看: 2524|回复: 1

[人工智能] VisualC++实现的BP神经网络类

[复制链接]
发表于 2006-11-15 09:48 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?我要加入

x
NeuroNet_BP.cpp

  1. #include "StdAfx.h"
  2. #include "neuronet_bp.h"
  3. #include "math.h"

  4. CNeuroNet_BP::CNeuroNet_BP()
  5. {
  6. }

  7. CNeuroNet_BP::CNeuroNet_BP(INT NumLayer, INT* pNumNodeInEachLayer, CString  MyFileName)
  8. {
  9.         Alpha = 0.9;
  10.         Eta = 0.45;
  11.         Gain = 5;
  12.         Error = 0;
  13.         nLayer = NumLayer;
  14.         pLayer = new NeuroLayer[nLayer];
  15.         this->TrainTimes =0;
  16.         fileName = MyFileName;

  17.         //构建网络
  18.         for(INT i=0; i<nLayer; i++)
  19.         {
  20.                 pLayer[i].nNode = pNumNodeInEachLayer[i];
  21.         }

  22.         this->nInput = pLayer[0].nNode;

  23.         //分配网络变量空间
  24.         this->GenerateNet();
  25.         //随机设定权值
  26.         this->RandomWeight();
  27. }

  28. CNeuroNet_BP::~CNeuroNet_BP(void)
  29. {
  30. }


  31. // 随机赋权值
  32. void CNeuroNet_BP::RandomWeight(void)
  33. {
  34.         srand(4567);
  35.         for(INT i=0; i<nLayer; i++)
  36.         {
  37.                 for(INT  j=0; j<pLayer[i].nNode; j++)
  38.                 {
  39.                         for(INT         k=0; k<pLayer[i].nInput; k++)
  40.                         {
  41.                                 pLayer[i].ppWeight[j][k] = (rand()%100-50)/100.0;                //随机赋权值(-0.5, 0.5);
  42.                                 pLayer[i].ppDWeight[j][k] = 0.0;
  43.                         }
  44.                 }
  45.         }

  46. }

  47. // 从文件中读取神经网络的权值
  48. BOOL CNeuroNet_BP::ReadNetFromFile(void)
  49. {

  50.         CFile        file;
  51.         if(file.Open(fileName, CFile::modeRead)==FALSE)
  52.         {
  53.                 return FALSE;
  54.         }

  55.         char        *pChar = new char[10];
  56.         file.Read((void*)pChar, 10);
  57.         //if(pChar != "NeuroBP")
  58.         //{
  59.         //        return FALSE;
  60.         //}
  61.         file.Read((void*)&this->TrainTimes, sizeof(DWORD));
  62.         file.Read((void*)&this->Error, sizeof(DOUBLE));
  63.         file.Read((void*)&this->Alpha, sizeof(DOUBLE));
  64.         file.Read((void*)&this->Eta, sizeof(DOUBLE));
  65.         file.Read((void*)&this->Gain, sizeof(DOUBLE));
  66.         file.Read((void*)&this->nInput, sizeof(INT));
  67.         file.Read((void*)&this->nLayer, sizeof(INT));

  68.         //读出每层节点数
  69.         INT*        pNumNode = new INT[nLayer];
  70.         for(INT i=0; i<nLayer; i++)
  71.         {
  72.                 file.Read((void*)&pNumNode[i], sizeof(INT));
  73.         }

  74.         ///
  75.         pLayer = new NeuroLayer[nLayer];
  76.         for(INT i=0; i<nLayer; i++)
  77.         {
  78.                 pLayer[i].nNode = pNumNode[i];
  79.         }       
  80.         this->GenerateNet();

  81.         //给每个神经元赋权值
  82.         for(INT i=0; i<nLayer; i++)
  83.         {
  84.                 for(INT j=0; j<pLayer[i].nNode; j++)
  85.                 {
  86.                         file.Read(pLayer[i].ppWeight[j], pLayer[i].nInput*sizeof(DOUBLE));        //读出每层的所有权值
  87.                         file.Read(pLayer[i].ppDWeight[j], pLayer[i].nInput*sizeof(DOUBLE));        //读出每层的所有权值
  88.                         //TRACE("pw[%d][%d][0]= %f", i, j, pLayer[i].ppWeight[j]);
  89.                 }
  90.         }
  91.    
  92.         return TRUE;
  93. }

  94. // 把权值保存到文件
  95. BOOL CNeuroNet_BP::SaveNetToFile(void)
  96. {
  97.         INT        nTemp = 0;

  98.         char        ID[10] = "NeuroBP";
  99.         //char        Memo[100] = "未说明";
  100.    
  101.         HANDLE hFile = CreateFile(_T(fileName),
  102.          GENERIC_WRITE, FILE_SHARE_READ,
  103.          NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

  104.    if (hFile == INVALID_HANDLE_VALUE)
  105.    {
  106.       AfxMessageBox(_T("Couldn't create the file!"));
  107.           return FALSE;
  108.    }

  109.     // Attach a CFile object to the handle we have.
  110.     CFile file(hFile);

  111.         file.Write((void*)ID, 10);                                //写入文件类型标记
  112.         //file.Write((void*)Memo, 100);                        //写入描述参数
  113.         file.Write((void*)&TrainTimes, sizeof(DWORD));                //写入已训练次数
  114.         file.Write((void*)&this->Error, sizeof(DOUBLE));        //写入最近的系统误差
  115.         file.Write((void*)&this->Alpha, sizeof(DOUBLE));
  116.         file.Write((void*)&this->Eta, sizeof(DOUBLE));
  117.         file.Write((void*)&this->Gain, sizeof(DOUBLE));
  118.         file.Write(&(this->nInput), sizeof(INT));                //写入输入数据宽度
  119.         file.Write(&(this->nLayer), sizeof(INT));       

  120.         //写入每层节点数
  121.         for(INT i=0; i<nLayer; i++)                               
  122.         {
  123.                 file.Write(&(pLayer[i].nNode), sizeof(INT));               
  124.         }       

  125.         //写入每层所有节点的权值
  126.         for(INT i=0; i<nLayer; i++)                               
  127.         {
  128.                 for(INT j=0; j<pLayer[i].nNode; j++)
  129.                 {
  130.                         file.Write(pLayer[i].ppWeight[j],  pLayer[i].nInput*sizeof(DOUBLE));
  131.                         file.Write(pLayer[i].ppDWeight[j],  pLayer[i].nInput*sizeof(DOUBLE));

  132.                         //TRACE("pw[%d][%d][0]= %f", i, j, pLayer[i].ppWeight[j]);
  133.                 }
  134.         }

  135.         file.Close();

  136.         return TRUE;
  137. }

  138. // 处理输入数据,产生输出
  139. BOOL CNeuroNet_BP::Propagate( DOUBLE*  pInput)
  140. {
  141.         this->pInput = pInput;

  142.         //计算输出结果
  143.         for(INT i=0; i<this->nLayer; i++)
  144.         {
  145.                 if(i==0)
  146.                 {
  147.                         pLayer[i].pInput = this->pInput;
  148.                 }
  149.                 else
  150.                 {
  151.                         pLayer[i].pInput = pLayer[i-1].pOutput;
  152.                 }

  153.                 for(INT j=0; j<pLayer[i].nNode; j++)
  154.                 {
  155.                         pLayer[i].pOutput[j] = func(i, j);
  156.                         TRACE("pOut[%d][%d]=\t%f\t", i, j, pLayer[i].pOutput[j]);
  157.         }
  158.         }

  159.         return TRUE;
  160. }

  161. // 节点转移函数
  162. DOUBLE  CNeuroNet_BP::func(INT i, INT j)
  163. {
  164.         DOUBLE        sigma = 0.0;
  165.         for(INT k=0; k<pLayer[i].nInput; k++)
  166.         {
  167.                 sigma = sigma + pLayer[i].pInput[k] * pLayer[i].ppWeight[j][k];
  168.         }
  169.        
  170.         sigma = 1.0/(1.0 + exp(-sigma*this->Gain));
  171.         return sigma;
  172. }

  173. //用样本数据进行训练
  174. void  CNeuroNet_BP::Train(DOUBLE* pInput, DOUBLE* pTeach)
  175. {
  176.         Propagate(pInput);                                //处理数据
  177.         ComputeOutputError(pTeach);                //计算误差
  178.         BackPropagate();                                //反向传播,调整权值
  179.         this->TrainTimes++;
  180. }

  181. //******************************************************************************
  182. //                  反 向 传 播   调 整 权 值
  183. // *****************************************************************************
  184. // 计算输出误差
  185. void  CNeuroNet_BP::ComputeOutputError(DOUBLE*        pTarget)
  186. {
  187.   DOUBLE        Out, Err;
  188.   this->Error=0;

  189.   for(INT i=0; i<pLayer[nLayer-1].nNode; i++)
  190.   {
  191.         Out = pLayer[nLayer-1].pOutput[i];
  192.         Err = pTarget[i] - Out;
  193.         //this->pLayer[nLayer-1].pError[i] = Gain*Out*(1-Out)*Err;
  194.         this->pLayer[nLayer-1].pError[i] = Out*(1-Out)*Err;
  195.         this->Error += 0.5*pow(Err, 2);
  196.   }
  197. }


  198. //反向传播误差
  199. void CNeuroNet_BP::BackPropagate(void)
  200. {
  201.         DOUBLE Out, Err;

  202.         //反向计算误差
  203.         for(INT i=nLayer-2; i>=0; i--)
  204.         {
  205.                 for(INT j=0; j<pLayer[i].nNode; j++)
  206.                 {
  207.                         Out = pLayer[i].pOutput[j];
  208.                         Err = 0;

  209.                         for(INT k=0; k<pLayer[i+1].nNode; k++)
  210.                         {
  211.                                 Err += pLayer[i+1].pError[k] * pLayer[i+1].ppWeight[k][j];
  212.                         }
  213.                        
  214.                         pLayer[i].pError[j] = Out * (1-Out) * Err;
  215.                 }
  216.         }

  217.         //调整权值
  218.         for(INT i=nLayer-1; i>=0; i--)                //层
  219.         {
  220.                 for(INT j=0; j<pLayer[i].nNode; j++)
  221.                 {
  222.                         for(INT k=0; k<pLayer[i].nInput; k++)
  223.                         {
  224.                                 //if(i==0)
  225.                                 //{
  226.                                 //        Out = pLayer[0].pInput[k];
  227.                                 //}
  228.                                 //else
  229.                                 //{
  230.                                         Out = pLayer[i].pInput[k];

  231.                                 //}

  232.                                 Err = pLayer[i].pError[j];
  233.                                 pLayer[i].ppWeight[j][k] += this->Eta *Out*Err + this->Alpha*pLayer[i].ppDWeight[j][k];
  234.                                 pLayer[i].ppDWeight[j][k] = this->Eta *Err * Out + this->Alpha*pLayer[i].ppDWeight[j][k];
  235.                         }
  236.                 }
  237.         }
  238. }



  239. // 构建网络,分配变量空间
  240. void CNeuroNet_BP::GenerateNet(void)
  241. {
  242.         for(INT i=0; i<nLayer; i++)
  243.         {
  244.                 if(i==0)
  245.                 {
  246.                         pLayer[i].nInput = this->nInput;
  247.                 }
  248.                 else
  249.                 {
  250.                         pLayer[i].nInput = pLayer[i-1].nNode;
  251.                 }

  252.                 pLayer[i].pOutput = new DOUBLE[pLayer[i].nNode];                //为输出数据分配空间
  253.                 pLayer[i].pError = new DOUBLE[pLayer[i].nNode];                        //为节点误差分配空间
  254.                 pLayer[i].ppWeight = new DOUBLE*[pLayer[i].nNode ];                //给权值的指针分配空间
  255.                 pLayer[i].ppDWeight = new DOUBLE*[pLayer[i].nNode ];        //给权值增量分配空间

  256.                 for(INT j=0; j<pLayer[i].nNode; j++)
  257.                 {
  258.                         pLayer[i].ppWeight[j] = new DOUBLE[pLayer[i].nInput];                //给每个节点的权值分配空间
  259.                         pLayer[i].ppDWeight[j] = new DOUBLE[pLayer[i].nInput];                //给每个权值增量分配空间
  260.                 }
  261.         }

  262.         this->pOutput = pLayer[nLayer-1].pOutput;
  263. }
复制代码
回复
分享到:

使用道具 举报

 楼主| 发表于 2006-11-15 09:49 | 显示全部楼层
NeuroNet_BP.h

  1. #pragma once
  2. //#include        "NeuroLayer.h"
  3. /////////////////////////////////////////////////////////
  4. typedef struct NeuroLayer
  5. {

  6.         INT                        nNode;                //节点数目
  7.         INT                        nInput;                //层的输入
  8.         DOUBLE                *pInput;        //层的输入
  9.     DOUBLE                *pOutput;        //层的输出
  10.         DOUBLE                *pError;        //层的误差
  11.         DOUBLE                **ppWeight;        //权值
  12.         DOUBLE                **ppDWeight;       
  13. } NeuroLayer;

  14. //////////////////////////////////////////////////////////

  15. class CNeuroNet_BP
  16. {
  17. public:
  18.         CNeuroNet_BP();
  19.         CNeuroNet_BP(INT NumLayer, INT* pNumNodeInEachLayer, CString  MyFileName);
  20.         ~CNeuroNet_BP(void);
  21.         INT                nInput;                                        //一个输入样本的数据数目
  22.         DOUBLE                *pInput;                        //系统的输入
  23.         DOUBLE                *pOutput;                        //系统的输出
  24.         INT                nLayer;                                        //网络的层数
  25.         NeuroLayer        *pLayer;                        //指向各层的指针
  26.         DOUBLE                Eta;                                //学习效率
  27.         DOUBLE                Alpha;                                //冲量因子
  28.         DOUBLE                Error;                                //系统总体误差
  29.         DOUBLE                Gain;                                //S形函数的增益
  30.         DWORD                TrainTimes;                        //训练次数
  31.         CString                fileName;

  32. private:
  33.        
  34.        

  35. public:
  36.         BOOL ReadNetFromFile(void);                // 从文件中读取神经网络
  37.         BOOL SaveNetToFile(void);                // 把神经网络保存到文件
  38. public:
  39.         // 处理输入数据,产生输出
  40.         BOOL        Propagate( DOUBLE*  pInput);
  41.         // 节点函数
  42.         DOUBLE  func(INT i, INT j);
  43.         void        Train(DOUBLE* pInput, DOUBLE* pTarget);
  44.         // 随机赋权值
  45.         void        RandomWeight(void);
  46.         void        BackPropagate(void);
  47.         // 计算输出误差
  48.         void        ComputeOutputError(DOUBLE*        pTarget);
  49.         // 构建网络,分配变量空间
  50.         void GenerateNet(void);
  51.         // 显示网络信息
  52. };
复制代码
您需要登录后才可以回帖 登录 | 我要加入

本版积分规则

QQ|小黑屋|Archiver|手机版|联系我们|声振论坛

GMT+8, 2024-9-21 01:50 , Processed in 0.061143 second(s), 17 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表