感知器學習演算法----神經網路
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?-
//////////////////////////////////////////////////////////////////////////
- //singlelayer perceptrons(SLP)
- bool slp_calculate_output(constdouble * inputs,constdouble * weights,intnInputs,int & output)
- {
- if(NULL ==inputs || NULL == weights)
- returnfalse;
- double sum =0.0;
- for (int i = 0 ; i < nInputs ; ++i)
- {
-
sum += (weights[i] * inputs[i]);
- }
- //這裡我們對乘機和的處理:如果大於0,則輸出值為1;其他情況,輸出值為-1
- if(sum >0.0)
- output = 1;
- else
- output = -1;
- }
- //////////////////////////////////////////////////////////////////////////
單層感知器其簡單的特性,可以提供快速的計算。它能夠實現邏輯計算中的NOT、OR、AND等簡單計算。
但是對於稍微複雜的異或就無能無力。下面介紹的多層感知器,就能解決這個問題。
4.多層感知器
多層感知器(Multi-Layer Perceptrons),包含多層計算。
相對於單層感知器,輸出端從一個變到了多個;輸入端和輸出端之間也不光只有一層,現在又兩層:輸出層和隱藏層。
圖2.2
圖2.2就是一個多層感知器。
對於多層感知器的計算也是比較簡單易懂的。首先利用公式1計算每一個。
看一下它程式碼,就能明白它的工作原理。
[cpp] view plaincopyprint?- //////////////////////////////////////////////////////////////////////////
- //Multi-Layerperceptrons(MLP)
- const unsignedint nInputs =4;
- const unsignedint nOutputs = 3;
- const unsignedint nHiddens = 4;
- struct mlp
- {
- doubleinputs[nInputs+1];//多一個,存放的bias,一般存放入1
- doubleoutputs[nOutputs];
- doublehiddens[nHiddens+1]; //多一個,存放的bias,一般存放入1
- doubleweight_hiddens_2_inputs[nHiddens+1][nInputs+1];
- doubleweight_outputs_2_hiddens[nOutputs][nHiddens+1];
- };
- //這裡我們對乘機和的處理:如果大於0,則輸出值為1;其他情況,輸出值為-1
- double sigmoid (double val)
- {
- if(val >0.0)
- return1.0;
- else
- return-1.0;
- }
- //計算輸出端
- bool mlp_calculate_outputs(mlp * pMlp)
- {
- if(NULL ==pMlp)
- returnfalse;
- double sum =0.0;
- //首先計算隱藏層中的每一個結點的值
- for (int h = 0 ; h < nHiddens ; ++h)
- {
- doublesum = 0.0;
- for (int i = 0 ; i < nInputs + 1 ; ++i)
- {
- sum += pMlp->weight_hiddens_2_inputs[h][i]*pMlp->inputs[i];
- }
- pMlp->hiddens[h] = sigmoid (sum);
- }
- //利用隱藏層作為“輸入層”,計算輸出層
- for (int o = 0 ; o < nOutputs ; ++o)
- {
- doublesum = 0.0;
- for (int h = 0 ; h < nHiddens + 1 ; ++h)
- {
- sum += pMlp->weight_outputs_2_hiddens[o][h]*pMlp->hiddens[h];
- }
- pMlp->outputs[o] = sigmoid (sum);
- }
- returntrue;
- }
- //////////////////////////////////////////////////////////////////////////
二、感知器學習演算法
1.感知器學習
其實感知器學習演算法,就是利用第一節介紹的單層感知器。首先利用給的正確資料,計算得到輸出值,將輸出值和正確的值相比,由此來調整每一個輸出端上的權值。
公式2便是用來調整權值,首先 是一個“學習引數”,一般我將它設定成小於1的正數。T便是訓練資料中的正確結果, 便是第i個輸入端的輸入值,便是第i個輸入端上面的權值。
2.程式碼
對於其介紹,我還是附上程式碼。
[cpp] view plaincopyprint?- //////////////////////////////////////////////////////////////////////////
- //PerceptronLearning Algorithm(PLA)
- const unsignedint nTests =4; //訓練資料的數量
- const unsignedint nInputs =2; //輸入端的數量
- constdouble alpha =0.2; //學習引數
- struct slp
- {
- doubleinputs[nInputs];
- doubleoutput;
- }; //單層感知器
- //計算輸出值
- int compute(double *inputs,double * weights)
- {
- double sum =0.0;
- for (int i = 0 ; i < nInputs; ++i)
- {
- sum += weights[i]*inputs[i];
- }
- //bias
- sum += 1.0 * weights[nInputs];
- if(sum >0.0)
- return1;
- else
- return-1;
- }
- //
- int _tmain(int argc,_TCHAR* argv[])
- {
- //正確的訓練資料
- slp slps[nTests] = {
- {-1.0,-1.0,-1.0},
- {-1.0, 1.0, 1.0},
- { 1.0,-1.0, 1.0},
- { 1.0, 1.0, 1.0}
- };
- doubleweights[nInputs + 1] = {0.0};
- boolbLearningOK = false;
- //感知器學習演算法
- while(!bLearningOK)
- {
- bLearningOK = true;
- for (int i = 0 ; i < nTests ; ++i)
- {
- intoutput = compute(slps[i].inputs,weights);
- if(output!= (int)slps[i].output)
- {
- for(int w = 0 ; w < nInputs ; ++w)
- {
- weights[w] += alpha *slps[i].output * slps[i].inputs[w];
- }
- weights[nInputs] += alpha *slps[i].output ;
- bLearningOK = false;
- }
- }
- }
- for(int w = 0 ; w < nInputs + 1 ; ++w)
- {
- cout<<"weight"<<w<<":"<<weights[w] <<endl;
- }
- cout<<"\n";
- for (int i = 0 ;i < nTests ; ++i)
- {
- cout<<"rightresult:"<<slps[i].output<<"\t";
- cout<<"caculateresult:" << compute(slps[i].inputs,weights)<<endl;
- }
- //
- char temp ;