1. 程式人生 > >BP人工神經網路的C++實現

BP人工神經網路的C++實現

BP(Back Propagation)網路是1986年由Rumelhart和McCelland為首的科學家小組提出,是一種按誤差逆傳播演算法訓練的多層前饋網路,是目前應用最廣泛的神經網路模型之一。BP網路能學習和存貯大量的輸入輸出模式對映關係,而無需事前揭示描述這種對映關係的數學方程。它的學習規則是使用最速下降法(梯度法),通過反向傳播來不斷調整網路的權值和閾值,使網路的誤差平方和最小。BP神經網路模型拓撲結構包括輸入層(input layer)、隱層(hide layer)和輸出層(output layer)。

以下是我收集的一些關於神經網路的文章:

神經網路介紹——利用反向傳播演算法的模式學習
http://www.ibm.com/developerworks/cn/linux/other/l-neural/index.html

人工智慧 Java 坦克機器人系列: 神經網路,上部
http://www.ibm.com/developerworks/cn/java/j-lo-robocode3/index.html
人工智慧 Java 坦克機器人系列: 神經網路,下部
http://www.ibm.com/developerworks/cn/java/j-lo-robocode4/

使用 Python 構造神經網路--Hopfield 網路可以重構失真的圖案並消除噪聲
http://www.ibm.com/developerworks/cn/linux/l-neurnet/

提供一個Matlab的BP神經網路的基礎資料
http://www.cnblogs.com/galaxyprince/archive/2010/12/20/1911157.html

http://www.codeproject.com/KB/recipes/aforge_neuro.aspx
作者已經給出好幾種形式的應用例子

有歸一化處理的程式碼示例:

http://blog.csdn.net/han6771306/article/details/25476301

BP神經網路原理及C++實戰程式碼

http://www.tuicool.com/articles/2emMr2

以下C++程式碼實現了BP網路,通過8個3位二進位制樣本對應一個期望輸出,訓練BP網路,最後訓練好的網路可以將輸入的三位二進位制數對應輸出一位十進位制數。
  1. //將三位二進位制數轉為一位十進位制數
  2. #include<iostream>
  3. #include<cmath>
  4. usingnamespace std;  
  5. #define  innode 3  //輸入結點數
  6. #define  hidenode 10//隱含結點數
  7. #define  outnode 1 //輸出結點數
  8. #define  trainsample 8//BP訓練樣本數
  9. class BpNet  
  10. {  
  11. public:  
  12.     void train(double p[trainsample][innode ],double t[trainsample][outnode]);//Bp訓練
  13.     double p[trainsample][innode];     //輸入的樣本
  14.     double t[trainsample][outnode];    //樣本要輸出的
  15.     double *recognize(double *p);//Bp識別
  16.     void writetrain(); 
    //寫訓練完的權值
  17.     void readtrain(); //讀訓練好的權值,這使的不用每次去訓練了,只要把訓練最好的權值存下來就OK
  18.     BpNet();  
  19.     virtual ~BpNet();  
  20. public:  
  21.     void init();  
  22.     double w[innode][hidenode];//隱含結點權值
  23.     double w1[hidenode][outnode];//輸出結點權值
  24.     double b1[hidenode];//隱含結點閥值
  25.     double b2[outnode];//輸出結點閥值
  26.     double rate_w; //權值學習率(輸入層-隱含層)
  27.     double rate_w1;//權值學習率 (隱含層-輸出層)
  28.     double rate_b1;//隱含層閥值學習率
  29.     double rate_b2;//輸出層閥值學習率
  30.     double e;//誤差計算
  31.     double error;//允許的最大誤差
  32.     double result[outnode];// Bp輸出
  33. };  
  34. BpNet::BpNet()  
  35. {  
  36.     error=1.0;  
  37.     e=0.0;  
  38.     rate_w=0.9;  //權值學習率(輸入層--隱含層)
  39.     rate_w1=0.9; //權值學習率 (隱含層--輸出層)
  40.     rate_b1=0.9; //隱含層閥值學習率
  41.     rate_b2=0.9; //輸出層閥值學習率
  42. }  
  43. BpNet::~BpNet()  
  44. {  
  45. }  
  46. void winit(double w[],int n) //權值初始化
  47. {  
  48.   for(int i=0;i<n;i++)  
  49.     w[i]=(2.0*(double)rand()/RAND_MAX)-1;  
  50. }  
  51. void BpNet::init()  
  52. {  
  53.     winit((double*)w,innode*hidenode);  
  54.     winit((double*)w1,hidenode*outnode);  
  55.     winit(b1,hidenode);  
  56.     winit(b2,outnode);  
  57. }  
  58. void BpNet::train(double p[trainsample][innode],double t[trainsample][outnode])  
  59. {  
  60.     double pp[hidenode];//隱含結點的校正誤差
  61.     double qq[outnode];//希望輸出值與實際輸出值的偏差
  62.     double yd[outnode];//希望輸出值
  63.     double x[innode]; //輸入向量
  64.     double x1[hidenode];//隱含結點狀態值
  65.     double x2[outnode];//輸出結點狀態值
  66.     double o1[hidenode];//隱含層啟用值
  67.     double o2[hidenode];//輸出層啟用值
  68.     for(int isamp=0;isamp<trainsample;isamp++)//迴圈訓練一次樣品
  69.     {  
  70.         for(int i=0;i<innode;i++)  
  71.             x[i]=p[isamp][i]; //輸入的樣本
  72.         for(int i=0;i<outnode;i++)  
  73.             yd[i]=t[isamp][i]; //期望輸出的樣本
  74.         //構造每個樣品的輸入和輸出標準
  75.         for(int j=0;j<hidenode;j++)  
  76.         {  
  77.             o1[j]=0.0;  
  78.             for(int i=0;i<innode;i++)  
  79.                 o1[j]=o1[j]+w[i][j]*x[i];//隱含層各單元輸入啟用值
  80.             x1[j]=1.0/(1+exp(-o1[j]-b1[j]));//隱含層各單元的輸出
  81.             //    if(o1[j]+b1[j]>0) x1[j]=1;
  82.             //else x1[j]=0;
  83.         }  
  84.         for(int k=0;k<outnode;k++)  
  85.         {  
  86.             o2[k]=0.0;  
  87.             for(int j=0;j<hidenode;j++)  
  88.                 o2[k]=o2[k]+w1[j][k]*x1[j]; //輸出層各單元輸入啟用值
  89.             x2[k]=1.0/(1.0+exp(-o2[k]-b2[k])); //輸出層各單元輸出
  90.             //    if(o2[k]+b2[k]>0) x2[k]=1;
  91.             //    else x2[k]=0;
  92.         }  
  93.         for(int k=0;k<outnode;k++)  
  94.         {  
  95.             qq[k]=(yd[k]-x2[k])*x2[k]*(1-x2[k]); //希望輸出與實際輸出的偏差
  96.             for(int j=0;j<hidenode;j++)  
  97.                 w1[j][k]+=rate_w1*qq[k]*x1[j];