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

📄 visualc++实现的bp神经网络类.txt

📁 vc++6.0编写人工神经网络BP程序,C++源程序文件,有一个类CNeuroNet_BP::CNeuroNet_BP
💻 TXT
字号:
#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;
}



























































//////////////////////////////////////////////////////////////////////////////////////


#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, CString  MyFileName);
        ~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);
        // 节点函数
        DOUBLE  func(INT i, INT j);
        void        Train(DOUBLE* pInput, DOUBLE* pTarget);
        // 随机赋权值
        void        RandomWeight(void);
        void        BackPropagate(void);
        // 计算输出误差
        void        ComputeOutputError(DOUBLE*        pTarget);
        // 构建网络,分配变量空间
        void GenerateNet(void);
        // 显示网络信息
};


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -