歡迎您光臨本站 註冊首頁

C++實現神經BP神經網絡

←手機掃碼閱讀     月球人 @ 2020-06-10 , reply:0

本文實例為大家分享了C++實現神經BP神經網絡的具體代碼,供大家參考,具體內容如下

BP.h

  #pragma once  #include#include#include#include#includeusing std::vector;  using std::exp;  using std::cout;  using std::endl;  class BP  {  private:   int studyNum;//允許學習次數   double h;//學習率   double allowError;//允許誤差   vectorlayerNum;//每層的節點數,不包括常量節點1   vector<vector<vector>> w;//權重   vector<vector<vector>> dw;//權重增量   vector<vector> b;//偏置   vector<vector> db;//偏置增量   vector<vector<vector>> a;//節點值   vector<vector> x;//輸入   vector<vector> y;//期望輸出     void iniwb();//初始化w與b   void inidwdb();//初始化dw與db   double sigmoid(double z);//激活函數   void forward();//前向傳播   void backward();//後向傳播   double Error();//計算誤差  public:   BP(vectorconst& layer_num, vector<vector>const & input_a0,   vector<vector> const & output_y, double hh = 0.5, double allerror = 0.001, int studynum = 1000);   BP();   void setLayerNumInput(vectorconst& layer_num, vector<vector> const & input);   void setOutputy(vector<vector> const & output_y);   void setHErrorStudyNum(double hh, double allerror,int studynum);   void run();//運行BP神經網絡   vectorpredict(vector& input);//使用已經學習好的神經網絡進行預測   ~BP();  };

 

BP.cpp

  #include "BP.h"  BP::BP(vectorconst& layer_num, vector<vector>const & input,   vector<vector> const & output_y, double hh, double allerror,int studynum)  {   layerNum = layer_num;   x = input;//輸入多少個節點的數據,每個節點有多少份數據   y = output_y;   h = hh;   allowError = allerror;   a.resize(layerNum.size());//有這麼多層網絡節點   for (int i = 0; i < layerNum.size(); i++)   {   a[i].resize(layerNum[i]);//每層網絡節點有這麼多個節點   for (int j = 0; j < layerNum[i]; j++)    a[i][j].resize(input[0].size());   }   a[0] = input;   studyNum = studynum;  }    BP::BP()  {   layerNum = {};   a = {};   y = {};   h = 0;   allowError = 0;  }    BP::~BP()  {  }    void BP::setLayerNumInput(vectorconst& layer_num, vector<vector> const & input)  {   layerNum = layer_num;   x = input;   a.resize(layerNum.size());//有這麼多層網絡節點   for (int i = 0; i < layerNum.size(); i++)   {   a[i].resize(layerNum[i]);//每層網絡節點有這麼多個節點   for (int j = 0; j < layerNum[i]; j++)    a[i][j].resize(input[0].size());   }   a[0] = input;  }      void BP::setOutputy(vector<vector> const & output_y)  {   y = output_y;  }    void BP::setHErrorStudyNum(double hh, double allerror,int studynum)  {   h = hh;   allowError = allerror;   studyNum = studynum;  }    //初始化權重矩陣  void BP::iniwb()  {   w.resize(layerNum.size() - 1);   b.resize(layerNum.size() - 1);   srand((unsigned)time(NULL));   //節點層數層數   for (int l = 0; l < layerNum.size() - 1; l++)   {   w[l].resize(layerNum[l + 1]);   b[l].resize(layerNum[l + 1]);   //對應後層的節點   for (int j = 0; j < layerNum[l + 1]; j++)   {    w[l][j].resize(layerNum[l]);    b[l][j] = -1 + 2 * (rand() / RAND_MAX);    //對應前層的節點    for (int k = 0; k < layerNum[l]; k++)    w[l][j][k] = -1 + 2 * (rand() / RAND_MAX);   }   }  }      void BP::inidwdb()  {   dw.resize(layerNum.size() - 1);   db.resize(layerNum.size() - 1);   //節點層數層數   for (int l = 0; l < layerNum.size() - 1; l++)   {   dw[l].resize(layerNum[l + 1]);   db[l].resize(layerNum[l + 1]);   //對應後層的節點   for (int j = 0; j < layerNum[l + 1]; j++)   {    dw[l][j].resize(layerNum[l]);    db[l][j] = 0;    //對應前層的節點    for (int k = 0; k < layerNum[l]; k++)    w[l][j][k] = 0;   }   }  }    //激活函數  double BP::sigmoid(double z)  {   return 1.0 / (1 + exp(-z));  }    void BP::forward()  {   for (int l = 1; l < layerNum.size(); l++)   {   for (int i = 0; i < layerNum[l]; i++)   {    for (int j = 0; j < x[0].size(); j++)    {      a[l][i][j] = 0;//第l層第i個節點第j個數據樣本    //計算變量節點乘權值的和    for (int k = 0; k < layerNum[l - 1]; k++)     a[l][i][j] += a[l - 1][k][j] * w[l - 1][i][k];    //加上節點偏置    a[l][i][j] += b[l - 1][i];    a[l][i][j] = sigmoid(a[l][i][j]);    }   }   }  }    void BP::backward()  {   int xNum = x[0].size();//樣本個數   //daP第l層da,daB第l+1層da   vectordaP, daB;        for (int j = 0; j < xNum; j++)   {   //處理最後一層的dw   daP.clear();   daP.resize(layerNum[layerNum.size() - 1]);   for (int i = 0, l = layerNum.size() - 1; i < layerNum[l]; i++)   {    daP[i] = a[l][i][j] - y[i][j];    for (int k = 0; k < layerNum[l - 1]; k++)    dw[l - 1][i][k] += daP[i] * a[l][i][j] * (1 - a[l][i][j])*a[l - 1][k][j];    db[l - 1][i] += daP[i] * a[l][i][j] * (1 - a[l][i][j]);   }     //處理剩下層的權重w的增量Dw   for (int l = layerNum.size() - 2; l > 0; l--)   {    daB = daP;    daP.clear();    daP.resize(layerNum[l]);    for (int k = 0; k < layerNum[l]; k++)    {    daP[k] = 0;    for (int i = 0; i < layerNum[l + 1]; i++)     daP[k] += daB[i] * a[l + 1][i][j] * (1 - a[l + 1][i][j])*w[l][i][k];    //dw    for (int i = 0; i < layerNum[l - 1]; i++)     dw[l - 1][k][i] += daP[k] * a[l][k][j] * (1 - a[l][k][j])*a[l - 1][i][j];    //db    db[l-1][k] += daP[k] * a[l][k][j] * (1 - a[l][k][j]);    }   }     }      //計算dw與db平均值   for (int l = 0; l < layerNum.size() - 1; l++)   {   //對應後層的節點   for (int j = 0; j < layerNum[l + 1]; j++)   {    db[l][j] = db[l][j] / xNum;    //對應前層的節點    for (int k = 0; k < layerNum[l]; k++)    w[l][j][k] = w[l][j][k] / xNum;   }   }     //更新參數w與b   for (int l = 0; l < layerNum.size() - 1; l++)   {   for (int j = 0; j < layerNum[l + 1]; j++)   {    b[l][j] = b[l][j] - h * db[l][j];    //對應前層的節點    for (int k = 0; k < layerNum[l]; k++)    w[l][j][k] = w[l][j][k] - h * dw[l][j][k];   }   }  }    double BP::Error()  {   int l = layerNum.size() - 1;   double temp = 0, error = 0;   for (int i = 0; i < layerNum[l]; i++)   for (int j = 0; j < x[0].size(); j++)   {    temp = a[l][i][j] - y[i][j];    error += temp * temp;   }   error = error / x[0].size();//求對每一組樣本的誤差平均   error = error / 2;   cout << error << endl;   return error;  }    //運行神經網絡  void BP::run()  {   iniwb();   inidwdb();   int i = 0;   for (; i < studyNum; i++)   {   forward();   if (Error() <= allowError)   {    cout << "Study Success!" << endl;    break;   }   backward();   }   if (i == 10000)   cout << "Study Failed!" << endl;  }    vectorBP::predict(vector& input)  {   vector<vector> a1;   a1.resize(layerNum.size());   for (int l = 0; l < layerNum.size(); l++)   a1[l].resize(layerNum[l]);   a1[0] = input;   for (int l = 1; l < layerNum.size(); l++)   for (int i = 0; i < layerNum[l]; i++)   {    a1[l][i] = 0;//第l層第i個節點第j個數據樣本    //計算變量節點乘權值的和    for (int k = 0; k < layerNum[l - 1]; k++)    a1[l][i] += a1[l - 1][k] * w[l - 1][i][k];    //加上節點偏置    a1[l][i] += b[l - 1][i];    a1[l][i] = sigmoid(a1[l][i]);   }   return a1[layerNum.size() - 1];  }

 

驗證程序:

  #include"BP.h"    int main()  {   vectorlayer_num = { 1, 10, 1 };   vector<vector> input_a0 = { { 1,2,3,4,5,6,7,8,9,10 } };   vector<vector> output_y = { {0,0,0,0,1,1,1,1,1,1} };     BP bp(layer_num, input_a0,output_y,0.6,0.001, 2000);   bp.run();   for (int j = 0; j < 30; j++)   {   vectorinput = { 0.5*j };   vectoroutput = bp.predict(input);   for (auto i : output)    cout << "j:" << 0.5*j <<" pridict:" << i << " ";   cout << endl;   }   system("pause");   return 0;  }

 

輸出:

                                                       

   


[月球人 ] C++實現神經BP神經網絡已經有245次圍觀

http://coctec.com/docs/c/language/show-post-237859.html