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

📄 bpnn.cpp

📁 一个bp神经元网络的c++实现
💻 CPP
字号:
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop
#include <algorithm.h>
#include <vector.h>
#include <math.h>
#include <stdio.h>
#include <alloc.h>
#include "Bpnn.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
////
////
#define MAXLAYERS 5    //最大层数
#define MAXNNUM 20     //每层最大神经元数
#define MAXTrainDataNum 200 //135 // 9*15       iris.txt文件共150条数据
#define MAXTestDataNum 20 ///15   // 150/15
#define MAXLEARNNUM 2000 //最大学习次数


double W[MAXLAYERS][MAXLAYERS][MAXNNUM][MAXNNUM]; //权矩阵
double dW[MAXLAYERS][MAXLAYERS][MAXNNUM][MAXNNUM]; //dw矩阵
double d[MAXLAYERS][MAXNNUM]; //求dW时用到的一个中间变量
double TH[MAXLAYERS][MAXNNUM]; //阈值矩阵
double dTH[MAXLAYERS][MAXNNUM]; //dTH阈值
double learnRatio[MAXLAYERS];//学习率,注意位置


double Sum[MAXLAYERS][MAXNNUM];//各层输入和->激活值
double Out[MAXLAYERS][MAXNNUM];//各层输出和
//double FinalOut[MAXNNUM];//for 辨识
int    NNum[MAXLAYERS];//各层神经元数

double trainData[MAXTrainDataNum][MAXNNUM+MAXNNUM];// 训练数据:输入+ 期望输出
double testData[MAXTestDataNum][MAXNNUM+MAXNNUM];  //  测试数据:输入+ 期望输出
/////
double err[MAXLEARNNUM]; //全局误差
double ERR;//全局误差限
double singleErr;
int learnN;
double sum;


int i,j,k,t,n,pren,postn,randT;  //for circulate
int I,H,O,L;//for input ,hidden,output
int LAYERS=3;//层数
int trainDataNum=135;// iris.txt文件共150条数据
int testDataNum=15;  // iris.txt文件共150条数据
int randList[MAXTrainDataNum];//for 训练集随机抽取

/////
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::readBtnClick(TObject *Sender)
{
   char nouse;
   char outStr[15];
   FILE *inputFile;
   inputFile=fopen("iris.txt","rb");

   ///前45条为训练数据,后5条为测试数据
   for ( i=0;i<3;i++)
   {
      for( j=i*50;j<(i*50+45);j++)//trainData
      {
            for( k=0;k<4;k++)
            {
               fscanf(inputFile, "%lf", &trainData[j-i*5][k]);
               fread(&nouse, 1, 1, inputFile);
            }

            fscanf(inputFile, "%s", outStr);

            if(CompareStr(outStr,"Iris-setosa")==0)
              {trainData[j-i*5][4]=1;
               trainData[j-i*5][5]=0;
               trainData[j-i*5][6]=0;}
            if(CompareStr(outStr,"Iris-versicolor")==0)
              {trainData[j-i*5][4]=0;
               trainData[j-i*5][5]=1;
               trainData[j-i*5][6]=0;}
            if(CompareStr(outStr,"Iris-virginica")==0)
              {trainData[j-i*5][4]=0;
               trainData[j-i*5][5]=0;
               trainData[j-i*5][6]=1;}

      }

      for( j=i*50+45;j<(i*50+50);j++)//testData
      {
            for( k=0;k<4;k++)
            {
               fscanf(inputFile, "%lf", &testData[j-(i+1)*45][k]);
               fread(&nouse, 1, 1, inputFile);
            }

            fscanf(inputFile, "%s", outStr);
            //ListBox1->Items->Append(outStr);

            if(CompareStr(outStr,"Iris-setosa")==0)
              {testData[j-(i+1)*45][4]=1;
               testData[j-(i+1)*45][5]=0;
               testData[j-(i+1)*45][6]=0;}
            else if(CompareStr(outStr,"Iris-versicolor")==0)
              {testData[j-(i+1)*45][4]=0;
               testData[j-(i+1)*45][5]=1;
               testData[j-(i+1)*45][6]=0;}
            else if(CompareStr(outStr,"Iris-virginica")==0)
              {testData[j-(i+1)*45][4]=0;
               testData[j-(i+1)*45][5]=0;
               testData[j-(i+1)*45][6]=1;}
      }
   }

  fclose(inputFile);

  /* for( int j=0;j<135;j++)
     ListBox1->Items->Append(  IntToStr(j)
                         +" "+FloatToStr(trainData[j][0])
                         +" "+FloatToStr(trainData[j][1])
                         +" "+FloatToStr(trainData[j][2])
                         +" "+FloatToStr(trainData[j][3])
                         +" "+FloatToStr(trainData[j][4])
                         +" "+FloatToStr(trainData[j][5])
                         +" "+FloatToStr(trainData[j][6]));   */

}

//---------------------------------------------------------------------------
void __fastcall TForm1::init()
{
   I=0;
   H=1;
   O=2;
   NNum[I]=4; //input layer 神经元数
   NNum[H]=18; //hidden layer
   NNum[O]=3; //output layer
   
   learnN=0;
   sum=0;
   ERR=0.005;

   randomize();
   //begin 权、阈值 赋初值

   for(L=1;L<LAYERS;L++ )
   {
      for(n=0;n<NNum[L];n++)        //当前层
      {
           for( pren=0;pren<NNum[L-1];pren++ )  //前一层
           {
            W[L-1][L][pren][n]=myRand(); //rand[-0.1,0.1]
           }

           TH[L][n]=myRand(); //rand[-0.1,0.1]
      }

   }
   //end 权、阈值 赋初值
   //begin learRadio
   for(L=0;L<LAYERS;L++ )
     learnRatio[L]=0.006;//0.5? 学习率,注意位置
   //end learRadio


}
//---------------------------------------------------------------------------

void __fastcall TForm1::trainBtnClick(TObject *Sender)
{
   init();

   do
   {
         randListF();//for 训练集随机抽取,result is  randList[trainDataNum]

         for( t=0;t<trainDataNum;t++)
         {
             randT=randList[t];///随机选取的训练集

             forward(randT);   //use randT , notice t was used
             backward(randT);  //use randT

             //改进算法用于此
         }
         
         error();

         learnN=learnN+1;
    }
    while( (learnN<MAXLEARNNUM) & (err[learnN-1]>ERR) ) ;

}

//---------------------------------------------------------------------------
void __fastcall TForm1::forward(int trainID)
{ // notice t was used
   //输入层的输出
   for(n=0;n<NNum[0];n++)
     Out[0][n]=trainData[trainID][n];
   //begin 其他层的输出
   for(L=1;L<LAYERS;L++)   //哪一层
   {

       for(n=0;n<NNum[L];n++)  //哪一层哪个神经元
       {
          sum=0.0;

          for(pren=0;pren<NNum[L-1];pren++) //前一层哪个神经元
          {
            sum=sum+Out[L-1][pren]*W[L-1][L][pren][n];
          }

          Sum[L][n]=sum-TH[L][n];///减去阈值 ->激活值
          Out[L][n]=f(Sum[L][n]);//激活函数
       }

   }
   //end 其他层的输出
}
//---------------------------------------------------------------------------
void __fastcall TForm1::backward(int trainID)
{ // notice t was used
    //begin第LAYERS-1层
    for(n=0;n<NNum[LAYERS-1];n++)
       d[LAYERS-1][n]=( trainData[trainID][NNum[0]+n]  //期望输出
                   -Out[LAYERS-1][n] )*df(Sum[LAYERS-1][n]);
    for(n=0;n<NNum[LAYERS-1];n++)
    {
      dTH[LAYERS-1][n]=learnRatio[LAYERS-1]*d[LAYERS-1][n]*1;
      for(pren=0;pren<NNum[LAYERS-2];pren++)
      {
         dW[LAYERS-2][LAYERS-1][pren][n]=dTH[LAYERS-1][n]*Out[LAYERS-2][pren];
      }
    }
    //end第LAYERS-1层

    //begin第LAYERS-2 ->1层
    for(L=LAYERS-2;L>0;L--)
    {
        for( n=0;n<NNum[L];n++)
        {
           ///求 d[L][n]
           sum=0.0;
           for(postn=0;postn<NNum[L+1];postn++)
              sum+=d[L+1][postn]*W[L][L+1][n][postn];
           d[L][n]=sum*df(Sum[L][n]);
           //
           dTH[L][n]=learnRatio[L]*d[L][n];
           for(pren=0;pren<NNum[L-1];pren++)
           {
              dW[L-1][L][pren][n]=dTH[L][n]*Out[L-1][pren];
           }

        }
    }
    //end第LAYERS-2 ->1层

    //begin 赋予新W,TH, 第LAYERS-1到第1层
    for(L=LAYERS-1;L>0;L--)
    {
        for( n=0;n<NNum[L];n++)
        {
           for(pren=0;pren<NNum[L-1];pren++)
           {
             W[L-1][L][pren][n]+=dW[L-1][L][pren][n];
           }
           TH[L][n]+=dTH[L][n];
        }
    }
    //end 赋予新W,TH, 第LAYERS-1到第1层


}
//---------------------------------------------------------------------------
double __fastcall TForm1::f(double x)
{ //激活函数
   return( 1/(1+exp(-x)));
}
//---------------------------------------------------------------------------
double __fastcall TForm1::df(double x)
{ //激活函数
   return( f(x)*(1-f(x)) );
}
//---------------------------------------------------------------------------
void __fastcall TForm1::error()
{
    err[learnN]=0;

    for( t=0;t<trainDataNum;t++)
    {   //need not reandList
       forward(t); //get output

       singleErr=0;
       
       for (n=0;n<NNum[LAYERS-1];n++)
       {
          singleErr+=(Out[LAYERS-1][n]-trainData[t][NNum[0]+n])
                     *(Out[LAYERS-1][n]-trainData[t][NNum[0]+n])/2.0;
       }

       err[learnN]+=singleErr;

    }
   err[learnN]=err[learnN]/(trainDataNum+0.0+NNum[LAYERS-1]);
//
}

//---------------------------------------------------------------------------

double __fastcall TForm1::myRand()
{
  return( (rand()+0.0)/0x7FFFU/5-0.1 );//rand[-0.1,0.1]
}
//---------------------------------------------------------------------------
void __fastcall TForm1::randListF() //randListF function
{
    //randList从0-TrainDataNum从新排序
    for(i=0;i<trainDataNum;i++)
       randList[i]=i;

    vector<int> v(randList, randList+trainDataNum);
    random_shuffle(v.begin(), v.end());

    for(i=0;i<trainDataNum;i++)
      randList[i]=v.at(i);
 /*  int arr[10] = {0,1,2,3,4,5,6,7,8,9};
   vector<int> v(arr, arr+10);
   random_shuffle(v.begin(), v.end());
  for(i=0;i<10;i++)
  ListBox1->Items->Append(IntToStr(v.at(i)));
  */
}
//---------------------------------------------------------------------------

void __fastcall TForm1::showErrorClick(TObject *Sender)
{
 DecisionGraph1->Legend->Visible=false;
 Series1->Clear();

 for(i=0;i<learnN-1;i++)
   Series1->Add(err[i]+1,"",clRed);
  //  Series1->Add(0.99,"",clRed);

 //Series1->AddArray(err,learnN-1);
}
//---------------------------------------------------------------------------


void __fastcall TForm1::testBtnClick(TObject *Sender)
{
   //use testData

   String str;
   double tmpOut;//for辨识
   int flag;//for辨识
   int count=0;

   ListBox1->Clear();

   for(t=0;t<testDataNum;t++)
   {
      flag=1;
      str="";
      //输入层的输出
      for(n=0;n<NNum[0];n++)
         Out[0][n]=testData[t][n];
      //begin 其他层的输出
      for(L=1;L<LAYERS;L++)   //哪一层
      {

        for(n=0;n<NNum[L];n++)  //哪一层哪个神经元
        {
            sum=0.0;

            for(pren=0;pren<NNum[L-1];pren++) //前一层哪个神经元
            {
              sum=sum+Out[L-1][pren]*W[L-1][L][pren][n];
            }

             Sum[L][n]=sum-TH[L][n];///减去阈值 ->激活值
             Out[L][n]=f(Sum[L][n]);//激活函数
        }

     }
     //end 其他层的输出

     //begin 辨识
     for(n=0;n<NNum[LAYERS-1];n++)
     {
       if(Out[LAYERS-1][n]>=0.5)
         tmpOut=1;
       else
         tmpOut=0;
       /////
       if( tmpOut==testData[t][NNum[0]+n] )
         flag=flag*1;
       else
         flag=flag*0;

       str+=FloatToStrF(Out[LAYERS-1][n],ffFixed,7,2)+" ";
       //(FloatToStr(Out[LAYERS-1][n])).SubString(1,3)+" ";
     }

     str+="->";
     for(n=0;n<NNum[LAYERS-1];n++)
     {
      str+=FloatToStr(testData[t][NNum[0]+n])+" ";
     }
     if(flag==1) {str+="   R";count++;}
     else  str+="   W";

     ListBox1->Items->Append(IntToStr(t+1)

                        +":   "+str);
     //end 辨识
   }

   if(count==testDataNum) str="100";
   else str=(FloatToStr((count)/(testDataNum+0.0))).SubString(3,2);

   ListBox1->Items->Append(" ");
   ListBox1->Items->Append("      正确率:"
         +str
         +"%");

}
//---------------------------------------------------------------------------

⌨️ 快捷键说明

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