參考:http://www.cnblogs.com/heaad/archive/2011/03/07/1976443.html
神經網路程式設計入門
本文主要內容包括: (1) 介紹神經網路基本原理,(2) AForge.NET實現前向神經網路的方法,(3) Matlab實現前向神經網路的方法 。
第0節、引例
本文以Fisher的Iris資料集作為神經網路程式的測試資料集。Iris資料集可以在http://en.wikipedia.org/wiki/Iris_flower_data_set 找到。這裡簡要介紹一下Iris資料集:
有一批Iris花,已知這批Iris花可分為3個品種,現需要對其進行分類。不同品種的Iris花的花萼長度、花萼寬度、花瓣長度、花瓣寬度會有差異。我們現有一批已知品種的Iris花的花萼長度、花萼寬度、花瓣長度、花瓣寬度的資料。
一種解決方法是用已有的資料訓練一個神經網路用作分類器。
如果你只想用C#或Matlab快速實現神經網路來解決你手頭上的問題,或者已經瞭解神經網路基本原理,請直接跳到第二節——神經網路實現。
第一節、神經網路基本原理
1. 人工神經元( Artificial Neuron )模型
人工神經元是神經網路的基本元素,其原理可以用下圖表示:
圖1. 人工神經元模型
圖中x1~xn是從其他神經元傳來的輸入訊號,wij表示表示從神經元j到神經元i的連線權值,θ表示一個閾值 ( threshold ),或稱為偏置( bias )。則神經元i的輸出與輸入的關係表示為:
圖中 yi表示神經元i的輸出,函式f稱為啟用函式 ( Activation Function )或轉移函式 ( Transfer Function ) ,net稱為淨啟用(net activation)。若將閾值看成是神經元i的一個輸入x0的權重wi0,則上面的式子可以簡化為:
若用X表示輸入向量,用W表示權重向量,即:
X = [ x0 , x1 , x2 , ....... , xn ]
則神經元的輸出可以表示為向量相乘的形式:
若神經元的淨啟用net為正,稱該神經元處於啟用狀態或興奮狀態(fire),若淨啟用net為負,則稱神經元處於抑制狀態。
圖1中的這種“閾值加權和”的神經元模型稱為M-P模型 ( McCulloch-Pitts Model ),也稱為神經網路的一個處理單元( PE, Processing Element )。
2. 常用啟用函式
啟用函式的選擇是構建神經網路過程中的重要環節,下面簡要介紹常用的啟用函式。
(1) 線性函式 ( Liner Function )
(2) 斜面函式 ( Ramp Function )
(3) 閾值函式 ( Threshold Function )
以上3個啟用函式都屬於線性函式,下面介紹兩個常用的非線性啟用函式。
(4) S形函式 ( Sigmoid Function )
該函式的導函式:
(5) 雙極S形函式
該函式的導函式:
S形函式與雙極S形函式的影象如下:
圖3. S形函式與雙極S形函式影象
雙極S形函式與S形函式主要區別在於函式的值域,雙極S形函式值域是(-1,1),而S形函式值域是(0,1)。
由於S形函式與雙極S形函式都是可導的(導函式是連續函式),因此適合用在BP神經網路中。(BP演算法要求啟用函式可導)
3. 神經網路模型
神經網路是由大量的神經元互聯而構成的網路。根據網路中神經元的互聯方式,常見網路結構主要可以分為下面3類:
(1) 前饋神經網路 ( Feedforward Neural Networks )
前饋網路也稱前向網路。這種網路只在訓練過程會有反饋訊號,而在分類過程中資料只能向前傳送,直到到達輸出層,層間沒有向後的反饋訊號,因此被稱為前饋網路。感知機( perceptron)與BP神經網路就屬於前饋網路。
圖4 中是一個3層的前饋神經網路,其中第一層是輸入單元,第二層稱為隱含層,第三層稱為輸出層(輸入單元不是神經元,因此圖中有2層神經元)。
圖4. 前饋神經網路
對於一個3層的前饋神經網路N,若用X表示網路的輸入向量,W1~W3表示網路各層的連線權向量,F1~F3表示神經網路3層的啟用函式。
那麼神經網路的第一層神經元的輸出為:
O1 = F1( XW1 )
第二層的輸出為:
O2 = F2 ( F1( XW1 ) W2 )
輸出層的輸出為:
O3 = F3( F2 ( F1( XW1 ) W2 ) W3 )
若啟用函式F1~F3都選用線性函式,那麼神經網路的輸出O3將是輸入X的線性函式。因此,若要做高次函式的逼近就應該選用適當的非線性函式作為啟用函式。
(2) 反饋神經網路 ( Feedback Neural Networks )
反饋型神經網路是一種從輸出到輸入具有反饋連線的神經網路,其結構比前饋網路要複雜得多。典型的反饋型神經網路有:Elman網路和Hopfield網路。
圖5. 反饋神經網路
(3) 自組織網路 ( SOM ,Self-Organizing Neural Networks )
自組織神經網路是一種無導師學習網路。它通過自動尋找樣本中的內在規律和本質屬性,自組織、自適應地改變網路引數與結構。
圖6. 自組織網路
4. 神經網路工作方式
神經網路運作過程分為學習和工作兩種狀態。
(1)神經網路的學習狀態
網路的學習主要是指使用學習演算法來調整神經元間的聯接權,使得網路輸出更符合實際。學習演算法分為有導師學習( Supervised Learning )與無導師學習( Unsupervised Learning )兩類。
有導師學習演算法將一組訓練集 ( training set )送入網路,根據網路的實際輸出與期望輸出間的差別來調整連線權。有導師學習演算法的主要步驟包括:
1) 從樣本集合中取一個樣本(Ai,Bi);
2) 計算網路的實際輸出O;
3) 求D=Bi-O;
4) 根據D調整權矩陣W;
5) 對每個樣本重複上述過程,直到對整個樣本集來說,誤差不超過規定範圍。
BP演算法就是一種出色的有導師學習演算法。
無導師學習抽取樣本集合中蘊含的統計特性,並以神經元之間的聯接權的形式存於網路中。
Hebb學習律是一種經典的無導師學習演算法。
(2) 神經網路的工作狀態
神經元間的連線權不變,神經網路作為分類器、預測器等使用。
下面簡要介紹一下Hebb學習率與Delta學習規則 。
(3) 無導師學習演算法:Hebb學習率
Hebb演算法核心思想是,當兩個神經元同時處於激發狀態時兩者間的連線權會被加強,否則被減弱。
為了理解Hebb演算法,有必要簡單介紹一下條件反射實驗。巴甫洛夫的條件反射實驗:每次給狗餵食前都先響鈴,時間一長,狗就會將鈴聲和食物聯絡起來。以後如果響鈴但是不給食物,狗也會流口水。
圖7. 巴甫洛夫的條件反射實驗
受該實驗的啟發,Hebb的理論認為在同一時間被激發的神經元間的聯絡會被強化。比如,鈴聲響時一個神經元被激發,在同一時間食物的出現會激發附近的另一個神經元,那麼這兩個神經元間的聯絡就會強化,從而記住這兩個事物之間存在著聯絡。相反,如果兩個神經元總是不能同步激發,那麼它們間的聯絡將會越來越弱。
Hebb學習律可表示為:
其中wij表示神經元j到神經元i的連線權,yi與yj為兩個神經元的輸出,a是表示學習速度的常數。若yi與yj同時被啟用,即yi與yj同時為正,那麼Wij將增大。若yi被啟用,而yj處於抑制狀態,即yi為正yj為負,那麼Wij將變小。
(4) 有導師學習演算法:Delta學習規則
Delta學習規則是一種簡單的有導師學習演算法,該演算法根據神經元的實際輸出與期望輸出差別來調整連線權,其數學表示如下:
其中Wij表示神經元j到神經元i的連線權,di是神經元i的期望輸出,yi是神經元i的實際輸出,xj表示神經元j狀態,若神經元j處於啟用態則xj為1,若處於抑制狀態則xj為0或-1(根據啟用函式而定)。a是表示學習速度的常數。假設xi為1,若di比yi大,那麼Wij將增大,若di比yi小,那麼Wij將變小。
Delta規則簡單講來就是:若神經元實際輸出比期望輸出大,則減小所有輸入為正的連線的權重,增大所有輸入為負的連線的權重。反之,若神經元實際輸出比期望輸出小,則增大所有輸入為正的連線的權重,減小所有輸入為負的連線的權重。這個增大或減小的幅度就根據上面的式子來計算。
(5)有導師學習演算法:BP演算法
採用BP學習演算法的前饋型神經網路通常被稱為BP網路。
圖8. 三層BP神經網路結構
BP網路具有很強的非線性對映能力,一個3層BP神經網路能夠實現對任意非線性函式進行逼近(根據Kolrnogorov定理)。一個典型的3層BP神經網路模型如圖7所示。
BP網路的學習演算法佔篇幅較大,我打算在下一篇文章中介紹。
第二節、神經網路實現
1. 資料預處理
在訓練神經網路前一般需要對資料進行預處理,一種重要的預處理手段是歸一化處理。下面簡要介紹歸一化處理的原理與方法。
(1) 什麼是歸一化?
資料歸一化,就是將資料對映到[0,1]或[-1,1]區間或更小的區間,比如(0.1,0.9) 。
(2) 為什麼要歸一化處理?
<1>輸入資料的單位不一樣,有些資料的範圍可能特別大,導致的結果是神經網路收斂慢、訓練時間長。
<2>資料範圍大的輸入在模式分類中的作用可能會偏大,而資料範圍小的輸入作用就可能會偏小。
<3>由於神經網路輸出層的啟用函式的值域是有限制的,因此需要將網路訓練的目標資料對映到啟用函式的值域。例如神經網路的輸出層若採用S形啟用函式,由於S形函式的值域限制在(0,1),也就是說神經網路的輸出只能限制在(0,1),所以訓練資料的輸出就要歸一化到[0,1]區間。
<4>S形啟用函式在(0,1)區間以外區域很平緩,區分度太小。例如S形函式f(X)在引數a=1時,f(100)與f(5)只相差0.0067。
(3) 歸一化演算法
一種簡單而快速的歸一化演算法是線性轉換演算法。線性轉換演算法常見有兩種形式:
<1>
y = ( x - min )/( max - min )
其中min為x的最小值,max為x的最大值,輸入向量為x,歸一化後的輸出向量為y 。上式將資料歸一化到 [ 0 , 1 ]區間,當啟用函式採用S形函式時(值域為(0,1))時這條式子適用。
<2>
y = 2 * ( x - min ) / ( max - min ) - 1
這條公式將資料歸一化到 [ -1 , 1 ] 區間。當啟用函式採用雙極S形函式(值域為(-1,1))時這條式子適用。
(4) Matlab資料歸一化處理函式
Matlab中歸一化處理資料可以採用premnmx , postmnmx , tramnmx 這3個函式。
<1> premnmx
語法:[pn,minp,maxp,tn,mint,maxt] = premnmx(p,t)
引數:
pn: p矩陣按行歸一化後的矩陣
minp,maxp:p矩陣每一行的最小值,最大值
tn:t矩陣按行歸一化後的矩陣
mint,maxt:t矩陣每一行的最小值,最大值
作用:將矩陣p,t歸一化到[-1,1] ,主要用於歸一化處理訓練資料集。
<2> tramnmx
語法:[pn] = tramnmx(p,minp,maxp)
引數:
minp,maxp:premnmx函式計算的矩陣的最小,最大值
pn:歸一化後的矩陣
作用:主要用於歸一化處理待分類的輸入資料。
<3> postmnmx
語法: [p,t] = postmnmx(pn,minp,maxp,tn,mint,maxt)
引數:
minp,maxp:premnmx函式計算的p矩陣每行的最小值,最大值
mint,maxt:premnmx函式計算的t矩陣每行的最小值,最大值
作用:將矩陣pn,tn對映回歸一化處理前的範圍。postmnmx函式主要用於將神經網路的輸出結果對映回歸一化前的資料範圍。
2. 使用Matlab實現神經網路
使用Matlab建立前饋神經網路主要會使用到下面3個函式:
newff :前饋網路建立函式
train:訓練一個神經網路
sim :使用網路進行模擬
下面簡要介紹這3個函式的用法。
(1) newff函式
<1>newff函式語法
newff函式引數列表有很多的可選引數,具體可以參考Matlab的幫助文件,這裡介紹newff函式的一種簡單的形式。
語法:net = newff ( A, B, {C} ,‘trainFun’)
引數:
A:一個n×2的矩陣,第i行元素為輸入訊號xi的最小值和最大值;
B:一個k維行向量,其元素為網路中各層節點數;
C:一個k維字串行向量,每一分量為對應層神經元的啟用函式;
trainFun :為學習規則採用的訓練演算法。
<2>常用的啟用函式
常用的啟用函式有:
a) 線性函式 (Linear transfer function)
f(x) = x
該函式的字串為’purelin’。
b) 對數S形轉移函式( Logarithmic sigmoid transfer function )
該函式的字串為’logsig’。
c) 雙曲正切S形函式 (Hyperbolic tangent sigmoid transfer function )
也就是上面所提到的雙極S形函式。
該函式的字串為’ tansig’。
Matlab的安裝目錄下的toolbox\nnet\nnet\nntransfer子目錄中有所有啟用函式的定義說明。
<3>常見的訓練函式
常見的訓練函式有:
traingd :梯度下降BP訓練函式(Gradient descent backpropagation)
traingdx :梯度下降自適應學習率訓練函式
<4>網路配置引數
一些重要的網路配置引數如下:
net.trainparam.goal :神經網路訓練的目標誤差
net.trainparam.show : 顯示中間結果的週期
net.trainparam.epochs :最大迭代次數
net.trainParam.lr : 學習率
(2) train函式
網路訓練學習函式。
語法:[ net, tr, Y1, E ] = train( net, X, Y )
引數:
X:網路實際輸入
Y:網路應有輸出
tr:訓練跟蹤資訊
Y1:網路實際輸出
E:誤差矩陣
(3) sim函式
語法:Y=sim(net,X)
引數:
net:網路
X:輸入給網路的K×N矩陣,其中K為網路輸入個數,N為資料樣本數
Y:輸出矩陣Q×N,其中Q為網路輸出個數
(4) Matlab BP網路例項
我將Iris資料集分為2組,每組各75個樣本,每組中每種花各有25個樣本。其中一組作為以上程式的訓練樣本,另外一組作為檢驗樣本。為了方便訓練,將3類花分別編號為1,2,3 。
使用這些資料訓練一個4輸入(分別對應4個特徵),3輸出(分別對應該樣本屬於某一品種的可能性大小)的前向網路。
Matlab程式如下:
%讀取訓練資料 [f1,f2,f3,f4,class] = textread('trainData.txt' , '%f%f%f%f%f',150); %特徵值歸一化 [input,minI,maxI] = premnmx( [f1 , f2 , f3 , f4 ]') ; %構造輸出矩陣 s = length( class) ; output = zeros( s , 3 ) ; for i = 1 : s output( i , class( i ) ) = 1 ; end %建立神經網路 net = newff( minmax(input) , [10 3] , { 'logsig' 'purelin' } , 'traingdx' ) ; %設定訓練引數 net.trainparam.show = 50 ; net.trainparam.epochs = 500 ; net.trainparam.goal = 0.01 ; net.trainParam.lr = 0.01 ; %開始訓練 net = train( net, input , output' ) ; %讀取測試資料 [t1 t2 t3 t4 c] = textread('testData.txt' , '%f%f%f%f%f',150); %測試資料歸一化 testInput = tramnmx ( [t1,t2,t3,t4]' , minI, maxI ) ; %模擬 Y = sim( net , testInput ) %統計識別正確率 [s1 , s2] = size( Y ) ; hitNum = 0 ; for i = 1 : s2 [m , Index] = max( Y( : , i ) ) ; if( Index == c(i) ) hitNum = hitNum + 1 ; end end sprintf('識別率是 %3.3f%%',100 * hitNum / s2 )
以上程式的識別率穩定在95%左右,訓練100次左右達到收斂,訓練曲線如下圖所示:
圖9. 訓練效能表現
(5)引數設定對神經網路效能的影響
我在實驗中通過調整隱含層節點數,選擇不通過的啟用函式,設定不同的學習率,
<1>隱含層節點個數
隱含層節點的個數對於識別率的影響並不大,但是節點個數過多會增加運算量,使得訓練較慢。
<2>啟用函式的選擇
啟用函式無論對於識別率或收斂速度都有顯著的影響。在逼近高次曲線時,S形函式精度比線性函式要高得多,但計算量也要大得多。
<3>學習率的選擇
學習率影響著網路收斂的速度,以及網路能否收斂。學習率設定偏小可以保證網路收斂,但是收斂較慢。相反,學習率設定偏大則有可能使網路訓練不收斂,影響識別效果。
3. 使用AForge.NET實現神經網路
(1) AForge.NET簡介
AForge.NET是一個C#實現的面向人工智慧、計算機視覺等領域的開源架構。AForge.NET原始碼下的Neuro目錄包含一個神經網路的類庫。
AForge.NET主頁:http://www.aforgenet.com/
AForge.NET程式碼下載:http://code.google.com/p/aforge/
Aforge.Neuro工程的類圖如下:
圖10. AForge.Neuro類庫類圖
下面介紹圖9中的幾個基本的類:
Neuron — 神經元的抽象基類
Layer — 層的抽象基類,由多個神經元組成
Network —神經網路的抽象基類,由多個層(Layer)組成
IActivationFunction - 啟用函式(activation function)的介面
IUnsupervisedLearning - 無導師學習(unsupervised learning)演算法的介面ISupervisedLearning - 有導師學習(supervised learning)演算法的介面
(2)使用Aforge建立BP神經網路
使用AForge建立BP神經網路會用到下面的幾個類:
<1> SigmoidFunction : S形神經網路
建構函式:public SigmoidFunction( double alpha )
引數alpha決定S形函式的陡峭程度。
<2> ActivationNetwork :神經網路類
建構函式:
public ActivationNetwork( IActivationFunction function, int inputsCount, params int[] neuronsCount )
: base( inputsCount, neuronsCount.Length )
public virtual double[] Compute( double[] input )
引數意義:
inputsCount:輸入個數
neuronsCount :表示各層神經元個數
<3> BackPropagationLearning:BP學習演算法
建構函式:
public BackPropagationLearning( ActivationNetwork network )
引數意義:
network :要訓練的神經網路物件
BackPropagationLearning類需要使用者設定的屬性有下面2個:
learningRate :學習率
momentum :衝量因子
下面給出一個用AForge構建BP網路的程式碼。
// 建立一個多層神經網路,採用S形啟用函式,各層分別有4,5,3個神經元 //(其中4是輸入個數,3是輸出個數,5是中間層結點個數) ActivationNetwork network = new ActivationNetwork(new SigmoidFunction(2), 4, 5, 3); // 建立訓練演算法物件 BackPropagationLearning teacher = new BackPropagationLearning(network); // 設定BP演算法的學習率與衝量係數 teacher.LearningRate = 0.1; teacher.Momentum = 0; int iteration = 1 ; // 迭代訓練500次 while( iteration < 500 ) { teacher.RunEpoch( trainInput , trainOutput ) ; ++iteration ; } //使用訓練出來的神經網路來分類,t為輸入資料向量 network.Compute(t)[0]
改程式對Iris 資料進行分類,識別率可達97%左右 。
文章來自:http://www.cnblogs.com/heaad/
轉載請保留出處,thx!
參考文獻
[1] Andrew Kirillov. Neural Networks on C#. [Online].
http://www.codeproject.com/KB/recipes/aforge_neuro.aspx 2006.10
[2] Sacha Barber. AI : Neural Network for beginners. [Online].
http://www.codeproject.com/KB/recipes/NeuralNetwork_1.aspx 2007.5
[3] Richard O. Duda, Peter E. Hart and David G. Stork. 模式分類. 機械工業出版社. 2010.4
[4] Wikipedia. Iris flower data set. [Online].