BP神經網絡-- C語言實現 上


      在上一篇文章中,介紹了BP神經網絡的基本模型、模型中的一些術語並對模型進行了數學上的分析,對它的原理有了初步的認識。那么如何用程序語言來具體的實現它,將是我們下一步需要討論的問題。本文選取的是C語言來實現一個簡單的單隱藏層的BP神經網絡(默認大家了解了BP神經網絡的基本概念,本文中涉及到些術語參見上一篇  基本模型 ),因此對於其他C類語言(C#、JAVA等)只需對本文中的代碼稍作修改即可移植。

 

一些數據的定義

   首先,我們介紹些下文中描述的程序里面的一些重要數據的定義。

#define Data  820
#define In 2
#define Out 1
#define Neuron 45
#define TrainC 5500

      Data 用來表示已經知道的數據樣本的數量,也就是訓練樣本的數量。In 表示對於每個樣本有多少個輸入變量; Out 表示對於每個樣本有多少個輸出變量。Neuron 表示神經元的數量,TrainC 來表示訓練的次數。再來我們看對神經網絡描述的數據定義,來看下面這張圖里面的數據類型都是 double 型。

BP神經網絡

 

圖1

      d_in[Data][In] 存儲 Data 個樣本,每個樣本的 In 個輸入。d_out[Data][Out] 存儲 Data 個樣本,每個樣本的 Out 個輸出。我們用鄰接表法來表示 圖1 中的網絡,w[Neuron][In]  表示某個輸入對某個神經元的權重,v[Out][Neuron] 來表示某個神經元對某個輸出的權重;與之對應的保存它們兩個修正量的數組 dw[Neuron][In] 和 dv[Out][Neuron]。數組 o[Neuron] 記錄的是神經元通過激活函數對外的輸出,OutputData[Out]  存儲BP神經網絡的輸出。

 

程序的執行過程

         在這里,先不考慮具體函數的執行細節,從大體上來介紹程序的執行過程。用偽代碼來表示,具體的內容后面一步步介紹,如下:

主函數main{

    讀取樣本數據 readData();
       初始化BP神經網絡  initBPNework(){

            包括數據的歸一,神經元的初始化 w[Neuron][In]、v[Out][Neuron]等;
        }
        BP神經網絡訓練 trainNetwork(){
            do{
                for(i 小於 樣本容量 Data){
                    
            計算按照第 i 個樣本輸入,產生的BP神經網絡的輸出 computO(i);
                    累記誤差精度;
                    反饋調節BP神經網絡中的神經元,完成第 i 個樣本的學習 backUpdate(i);
                }
            }while(達到訓練次數 或者 符合誤差精度);
        }

        存儲訓練好的神經元信息  writeNeuron();
        用一些數據來測試,訓練出來的BP神經網絡的結果;
        return 0;
}

       以上是處理的流程,對於讀取數據、保存數據之類的處理本文將略去這方面內容,突出主干部分。

 

初始化BP神經網絡

      初始化主要是涉及兩個方面的功能,一方面是對讀取的訓練樣本數據進行歸一化處理,歸一化處理就是指的就是將數據轉換成0~1之間。在BP神經網絡理論里面,並沒有對這個進行要求,不過實際實踐過程中,歸一化處理是不可或缺的。因為理論模型沒考慮到,BP神經網絡收斂的速率問題,一般來說神經元的輸出對於0~1之間的數據非常敏感,歸一化能夠顯著提高訓練效率。可以用以下公式來對其進行歸一化,其中 加個常數A 是為了防止出現 0 的情況(0不能為分母)。

       y=(x-MinValue+A)/(MaxValue-MinValue+A)

      另一方面,就是對神經元的權重進行初始化了,數據歸一到了(0~1)之間,那么權重初始化為(-1~1)之間的數據,另外對修正量賦值為0。實現參考代碼如下:

void initBPNework(){

    int i,j;
   /*
    找到數據最小、最大值
   */
    for(i=0; i<In; i++){
        Minin[i]=Maxin[i]=d_in[0][i];
        for(j=0; j<Data; j++)
        {
            Maxin[i]=Maxin[i]>d_in[j][i]?Maxin[i]:d_in[j][i];
            Minin[i]=Minin[i]<d_in[j][i]?Minin[i]:d_in[j][i];
        }
    }
    for(i=0; i<Out; i++){
        Minout[i]=Maxout[i]=d_out[0][i];
        for(j=0; j<Data; j++)
        {
            Maxout[i]=Maxout[i]>d_out[j][i]?Maxout[i]:d_out[j][i];
            Minout[i]=Minout[i]<d_out[j][i]?Minout[i]:d_out[j][i];
        }
    }
    /*
    歸一化處理
    */
    for (i = 0; i < In; i++)
        for(j = 0; j < Data; j++)
            d_in[j][i]=(d_in[j][i]-Minin[i]+1)/(Maxin[i]-Minin[i]+1);
    for (i = 0; i < Out; i++)
        for(j = 0; j < Data; j++)
            d_out[j][i]=(d_out[j][i]-Minout[i]+1)/(Maxout[i]-Minout[i]+1);
    /*
    初始化神經元
  */
    for (i = 0; i < Neuron; ++i)    
        for (j = 0; j < In; ++j){    
            w[i][j]=(rand()*2.0/RAND_MAX-1)/2;
            dw[i][j]=0;
        }
    for (i = 0; i < Neuron; ++i)    
         for (j = 0; j < Out; ++j){
             v[j][i]=(rand()*2.0/RAND_MAX-1)/2;
              dv[j][i]=0;
         }
}

 

BP神經網絡訓練

      這部分應當說是整個BP神經網絡形成的引擎,驅動着樣本訓練過程的執行。由BP神經網絡的基本模型知道,反饋學習機制包括兩大部分,一是BP神經網絡產生預測的結果,二是通過預測的結果和樣本的准確結果進行比對,然后對神經元進行誤差量的修正。因此,我們用兩個函數來表示這樣的兩個過程,訓練過程中還對平均誤差 e 進行監控,如果達到了設定的精度即可完成訓練。由於不一定能夠到達預期設定的精度要求,我們添加一個訓練次數的參數,如果次數達到也退出訓練。實現參考代碼如下:

 

void  trainNetwork(){
    int i,c=0;
    do{
        e=0;
        for (i = 0; i < Data; ++i){
            computO(i);
            e+=fabs((OutputData[0]-d_out[i][0])/d_out[i][0]);
            backUpdate(i);
        }
        //printf("%d  %lf\n",c,e/Data);
        c++;
    }while(c<TrainC && e/Data>0.01);
}

 

        其中的函數,computO(i) (O是output縮寫)計算BP神經網絡預測第 i 個樣本的輸出也就是第一個過程。backUpdate(i) 是根據預測的第 i 個樣本輸出對神經網絡的權重進行更新,e用來監控誤差。

    到這里,我們整體回顧來看,BP神經網絡程序實現的骨架已經介紹完了,訓練過程中核心的兩個函數computO(i) 和 backUpdate(i) 的實現在下一篇再來分析,晚安。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM