1. 程式人生 > >感知器學習演算法----神經網路

感知器學習演算法----神經網路

Machine Learning---感知器學習演算法

引言

這裡開始介紹神經網路方面的知識(Neural Networks)。首先我們會介紹幾個監督式學習的演算法,隨後便是非監督式的學習。

一、感知器學習演算法基本介紹

1.神經網路

就像進化計算,神經網路又是一個類似的概念。神經網路由一個或者多個神經元組成。而一個神經元包括輸入、輸出和“內部處理器”。神經元從輸入端接受資訊,通過“內部處理器”將這些資訊進行一定的處理,最後通過輸出端輸出。

2.感知器

感知器(Perceptron),是神經網路中的一個概念,在1950s由Frank Rosenblatt第一次引入。

3.單層感知器

單層感知器(Single Layer Perceptron)是最簡單的神經網路。它包含輸入層和輸出層,而輸入層和輸出層是直接相連的。


圖1.1

圖1.1便是一個單層感知器,很簡單一個結構,輸入層和輸出層直接相連。

接下來介紹一下如何計算輸出端。


利用公式1計算輸出層,這個公式也是很好理解。首先計算輸入層中,每一個輸入端和其上的權值相乘,然後將這些乘機相加得到乘機和。對於這個乘機和做如下處理,如果乘機和大於臨界值(一般是0),輸入端就取1;如果小於臨界值,就取-1。

以下就給出一段單層感知器的程式碼。

[cpp] view plaincopyprint?
  1. //////////////////////////////////////////////////////////////////////////
  2. //singlelayer perceptrons(SLP)
  3. bool slp_calculate_output(constdouble * inputs,constdouble * weights,intnInputs,int & output)  
  4. {  
  5.     if(NULL ==inputs || NULL == weights)  
  6.         returnfalse;  
  7.     double sum =0.0;  
  8.     for (int i = 0 ; i < nInputs ; ++i)  
  9.     {  
  10.         sum += (weights[i] * inputs[i]);  
  11.     }  
  12. //這裡我們對乘機和的處理:如果大於0,則輸出值為1;其他情況,輸出值為-1
  13.     if(sum >0.0)  
  14.         output = 1;  
  15.     else
  16.         output = -1;  
  17. }  
  18. //////////////////////////////////////////////////////////////////////////

單層感知器其簡單的特性,可以提供快速的計算。它能夠實現邏輯計算中的NOT、OR、AND等簡單計算。

但是對於稍微複雜的異或就無能無力。下面介紹的多層感知器,就能解決這個問題。

4.多層感知器

多層感知器(Multi-Layer Perceptrons),包含多層計算。

相對於單層感知器,輸出端從一個變到了多個;輸入端和輸出端之間也不光只有一層,現在又兩層:輸出層和隱藏層。


圖2.2

圖2.2就是一個多層感知器。

對於多層感知器的計算也是比較簡單易懂的。首先利用公式1計算每一個。

看一下它程式碼,就能明白它的工作原理。

[cpp] view plaincopyprint?
  1. //////////////////////////////////////////////////////////////////////////
  2. //Multi-Layerperceptrons(MLP)
  3. const unsignedint nInputs  =4;  
  4. const unsignedint nOutputs = 3;  
  5. const unsignedint nHiddens = 4;  
  6. struct mlp  
  7. {  
  8.     doubleinputs[nInputs+1];//多一個,存放的bias,一般存放入1
  9.     doubleoutputs[nOutputs];  
  10.     doublehiddens[nHiddens+1]; //多一個,存放的bias,一般存放入1
  11.     doubleweight_hiddens_2_inputs[nHiddens+1][nInputs+1];  
  12.     doubleweight_outputs_2_hiddens[nOutputs][nHiddens+1];  
  13. };  
  14. //這裡我們對乘機和的處理:如果大於0,則輸出值為1;其他情況,輸出值為-1
  15. double sigmoid (double val)  
  16. {  
  17.     if(val >0.0)  
  18.         return1.0;  
  19.     else
  20.         return-1.0;  
  21. }  
  22. //計算輸出端
  23. bool mlp_calculate_outputs(mlp * pMlp)  
  24. {  
  25.     if(NULL ==pMlp)  
  26.         returnfalse;  
  27.     double sum =0.0;  
  28.     //首先計算隱藏層中的每一個結點的值
  29.     for (int h = 0 ; h < nHiddens ; ++h)  
  30.     {  
  31.         doublesum = 0.0;  
  32.         for (int i = 0 ; i < nInputs + 1 ; ++i)  
  33.         {  
  34.             sum += pMlp->weight_hiddens_2_inputs[h][i]*pMlp->inputs[i];  
  35.         }  
  36.        pMlp->hiddens[h] = sigmoid (sum);  
  37.     }  
  38.      //利用隱藏層作為“輸入層”,計算輸出層
  39.     for (int o = 0 ; o < nOutputs ; ++o)  
  40.     {  
  41.         doublesum = 0.0;  
  42.         for (int h = 0 ; h < nHiddens + 1 ; ++h)  
  43.         {  
  44.             sum += pMlp->weight_outputs_2_hiddens[o][h]*pMlp->hiddens[h];  
  45.         }  
  46.         pMlp->outputs[o] = sigmoid (sum);  
  47.     }  
  48.     returntrue;  
  49. }  
  50. //////////////////////////////////////////////////////////////////////////


二、感知器學習演算法

1.感知器學習

其實感知器學習演算法,就是利用第一節介紹的單層感知器。首先利用給的正確資料,計算得到輸出值,將輸出值和正確的值相比,由此來調整每一個輸出端上的權值。


公式2便是用來調整權值,首先 是一個“學習引數”,一般我將它設定成小於1的正數。T便是訓練資料中的正確結果, 便是第i個輸入端的輸入值,便是第i個輸入端上面的權值。

2.程式碼

對於其介紹,我還是附上程式碼。

[cpp] view plaincopyprint?
  1. //////////////////////////////////////////////////////////////////////////
  2. //PerceptronLearning Algorithm(PLA)
  3. const unsignedint nTests   =4; //訓練資料的數量
  4. const unsignedint nInputs  =2; //輸入端的數量
  5. constdouble alpha =0.2;       //學習引數
  6. struct slp  
  7. {  
  8.     doubleinputs[nInputs];  
  9.     doubleoutput;  
  10. }; //單層感知器
  11. //計算輸出值
  12. int compute(double *inputs,double * weights)  
  13. {  
  14.     double sum =0.0;  
  15.     for (int i = 0 ; i < nInputs; ++i)  
  16.     {  
  17.         sum += weights[i]*inputs[i];  
  18.     }  
  19.     //bias
  20.     sum += 1.0 * weights[nInputs];  
  21.     if(sum >0.0)  
  22.         return1;  
  23.     else
  24.         return-1;  
  25. }  
  26. //
  27. int _tmain(int argc,_TCHAR* argv[])  
  28. {  
  29. //正確的訓練資料
  30.     slp slps[nTests] = {  
  31.         {-1.0,-1.0,-1.0},  
  32.         {-1.0, 1.0, 1.0},  
  33.         { 1.0,-1.0, 1.0},  
  34.         { 1.0, 1.0, 1.0}  
  35.     };  
  36.     doubleweights[nInputs + 1] = {0.0};  
  37.     boolbLearningOK = false;  
  38.   //感知器學習演算法
  39.     while(!bLearningOK)  
  40.     {  
  41.         bLearningOK = true;  
  42.         for (int i = 0 ; i < nTests ; ++i)  
  43.         {  
  44.             intoutput = compute(slps[i].inputs,weights);  
  45.             if(output!= (int)slps[i].output)  
  46.             {  
  47.                 for(int w = 0 ; w < nInputs ; ++w)  
  48.                 {  
  49.                     weights[w] += alpha *slps[i].output * slps[i].inputs[w];  
  50.                 }  
  51.                 weights[nInputs] += alpha *slps[i].output ;  
  52.                 bLearningOK = false;  
  53.             }  
  54.         }  
  55.     }  
  56.     for(int w = 0 ; w < nInputs + 1 ; ++w)  
  57.     {  
  58.         cout<<"weight"<<w<<":"<<weights[w] <<endl;  
  59.     }  
  60.     cout<<"\n";  
  61.     for (int i = 0 ;i < nTests ; ++i)  
  62.     {  
  63.         cout<<"rightresult:"<<slps[i].output<<"\t";  
  64.         cout<<"caculateresult:" << compute(slps[i].inputs,weights)<<endl;  
  65.     }  
  66.     //
  67.     char temp ;  
  68.