BP神經網絡學習及matlab實現

什麼是神經網絡?

神經網絡是由很多神經元組成的,首先我們看一下,什麼是神經元

上面這個圖表示的就是一個神經元,我們不管其它書上說的那些什麼樹突,軸突的。我用個比較粗淺的解釋,可能不太全面科學,但對初學者很容易理解:

1、我們把輸入信號看成你在matlab中需要輸入的數據,輸進去神經網絡後

2、這些數據的每一個都會被乘個數,即權值w,然後這些東東與閥值b相加後求和得到u,

3、上面只是線性變化,爲了達到能處理非線性的目的,u做了個變換,變換的規則和傳輸函數有關

可能還有人問,那麼那個閥值是什麼呢?簡單理解就是讓這些數據做了個平移,這就是神經元工作的過程。處理後的結果又作爲輸入,可輸給別的神經元,很多這樣的神經元,就組成了網絡。在matlab中具體用什麼算法實現這些,我們先不管,我們需要注意的是怎麼使用。比如使用BP的神經網絡newff()構建一個網絡,這些在後面的學習將提到。

BP網絡的特點

①網絡實質上實現了一個從輸入到輸出的映射功能,而數學理論已證明它具有實現任何複雜非線性映射的功能。這使得它特別適合於求解內部機制複雜的問題。我們無需建立模型,或瞭解其內部過程,只需輸入,獲得輸出。只要BPNN結構優秀,一般20個輸入函數以下的問題都能在50000次的學習以內收斂到最低誤差附近而且理論上,一個三層的神經網絡,能夠以任意精度逼近給定的函數,這是非常誘人的期望

②網絡能通過學習帶正確答案的實例集自動提取“合理的”求解規則,即具有自學習能力;

③網絡具有一定的推廣、概括能力。

bp主要應用

迴歸預測(可以進行擬合,數據處理分析,事物預測,控制等)、 分類識別(進行類型劃分,模式識別等),在後面的學習中,我都將給出實例程序。

但無論那種網絡,什麼方法,解決問題的精確度都無法打到100%的,但並不影響其使用,因爲現實中很多複雜的問題,精確的解釋是毫無意義的,有意義的解析必定會損失精度。

BP注意問題

1BP算法的學習速度很慢,其原因主要有:

a 由於BP算法本質上爲梯度下降法,而它所要優化的目標函數又非常複雜,因此,必然會出現“鋸齒形現象”,這使得BP算法低效;

b 存在麻痹現象,由於優化的目標函數很複雜,它必然會在神經元輸出接近0或1的情況下,出現一些平坦區,在這些區域內,權值誤差改變很小,使訓練過程幾乎停頓;

c 爲了使網絡執行BP算法,不能用傳統的一維搜索法求每次迭代的步長,而必須把步長的更新規則預先賦予網絡,這種方法將引起算法低效。

2、網絡訓練失敗的可能性較大,其原因有:

a 從數學角度看,BP算法爲一種局部搜索的優化方法,但它要解決的問題爲求解複雜非線性函數的全局極值,因此,算法很有可能陷入局部極值,使訓練失敗;

b 網絡的逼近、推廣能力同學習樣本的典型性密切相關,而從問題中選取典型樣本實例組成訓練集是一個很困難的問題。

3、網絡結構的選擇:

尚無一種統一而完整的理論指導,一般只能由經驗選定。爲此,有人稱神經網絡的結構選擇爲一種藝術。而網絡的結構直接影響網絡的逼近能力及推廣性質。因此,應用中如何選擇合適的網絡結構是一個重要的問題。

4、新加入的樣本要影響已學習成功的網絡,而且刻畫每個輸入樣本的特徵的數目也必須相同。

5、採用s型激活函數,由於輸出層各神經元的理想輸出值只能接近於1或0,而不能達到1或0,因此設置各訓練樣本的期望輸出分量Tkp時,不能設置爲1或0,設置0.9或0.1較爲適宜。

什麼是網絡的泛化能力?

一個神經網路是否優良,與傳統最小二乘之類的擬合評價不同(主要依據殘差,擬合優度等),不是體現在其對已有的數據擬合能力上,而是對後來的預測能力,既泛化能力。

網絡的預測能力(也稱泛化能力、推廣能力)與訓練能力(也稱逼近能力、學習能力)的矛盾。一般情況下,訓練能力差時,預測能力也差,並且一定程度上,隨訓練能力地提高,預測能力也提高。但這種趨勢有一個極限,當達到此極限時,隨訓練能力的提高,預測能力反而下降,即出現所謂“過擬合”現象。此時,網絡學習了過多的樣本細節,而不能反映樣本內含的規律。

過擬合是什麼,怎麼處理?

神經網絡計算不能一味地追求訓練誤差最小,這樣很容易出現“過擬合”現象,只要能夠實時檢測誤差率的變化就可以確定最佳的訓練次數,比如15000次左右的學習次數,如果你不觀察,設成500000次學習,不僅需要很長時間來跑,而且最後結果肯定令人大失所望。

避免過擬合的一種方法是:在數據輸入中,給訓練的數據分類,分爲正常訓練用、變量數據、測試數據,在後面節將講到如何進行這種分類。

其中變量數據,在網絡訓練中,起到的作用就是防止過擬合狀態。

學習速率有什麼作用?

學習速率這個參數可以控制能量函數的步幅,並且如果設爲自動調整的話,可以在誤差率經過快速下降後,將學習速率變慢,從而增加BPNN的穩定性。

此時訓練方法採用

 

net.trainFcn = 'traingda'; % 變學習率梯度下降算法
net.trainFcn = 'traingdx'; % 變學習率動量梯度下降算法
 
可以定義一個變動的學習速率,如
 
p = [-1 -1 2 2; 0 5 0 5];
 
t = [-1 -1 1 1];
 
net = newff(p,t,3,{},'traingda');
 
net.trainParam.lr = 0.05;
 
net.trainParam.lr_inc = 1.05;
 
net = train(net,p,t);
 
y = sim(net,p)


 

在後面的擬合例題中,我們也將用到學習速率這個參數。

神經網絡的權值和閾值分別是個什麼概念

第一節中,我們已經談到了權值和閥值的概念。這裏我們更深入的說明一下,因爲他們很重要,關係到網絡最後的結果。權值和閾值是神經元之間的連接,將數據輸入計算出一個輸出,然後與實際輸出比較,誤差反傳,不斷調整權值和閾值。

假如下面兩個點屬於不同的類,須設計分類器將他們分開

p1=[1 1 -1]';

p2=[1 -1 -1]';

這裏用單層神經元感知器,假設初始權值

w=[0.2 0.2 0.3]

同時假設初始閥值

b=-0.3

輸出 a1 a2

a1=hardlims(w*p1+b)

a2=hardlims(w*p2+b)

如果不能分開,還須不斷調整w,b

BP逼近非線性函數,如何提高訓練精度

(1)調整網絡結構

增加網絡的層數可以進一步降低誤差,提高精度但會使網絡複雜化,從而增加網絡的訓練時間。精度的提高實際上也可以通過增加隱層神經元的數目來獲得,其效果更容易觀察和掌握,所以應優先考慮。

(2)初始值選取

爲了使誤差儘可能小 ,需要合理選擇初始權重和偏置,如果太大就容易陷入飽和區,導致停頓 。一般應選爲均勻分佈的小數,介於 (-11)

(3)學習速率調整

學習速率的選取很重要 ,大了可能導致系統不穩定,小了會導致訓練週期過長、收斂慢,達不到要求的誤差。一般傾向於選取較小的學習速率以保持系統穩定,通過觀察誤差下降曲線來判斷。下降較快說明學習率比較合適,若有較大振盪則說明學習率偏大。同時,由於網絡規模大小的不同,學習率選擇應當針對其進行調整。採用變學習速率的方案,令學習速率隨學習進展而逐步減少,可收到良好的效果。

(4)期望誤差

期望誤差當然希望越小越好,但是也要有合適值。

爲了充分利用數據,得到最優的網絡訓練結果,在網絡建立前應該進行的基本數據處理問題,包括:

(1)BP神經網絡matlab實現的基本步驟

(2)數據歸一化問題和方法

(3)輸入訓練數據的亂序排法,以及分類方法

(4)如何查看和保存訓練的結果

(5)每次結果不一樣問題。

用matlab實現bp,其實很簡單,按下面步驟基本可以了

BP神經網絡matlab實現的基本步驟

1、數據歸一化

2、數據分類,主要包括打亂數據順序,抽取正常訓練用數據、變量數據、測試數據

3、建立神經網絡,包括設置多少層網絡(一般3層以內既可以,每層的節點數(具體節點數,尚無科學的模型和公式方法確定,可採用試湊法,但輸出層的節點數應和需要輸出的量個數相等),設置隱含層的傳輸函數等。關於網絡具體建立使用方法,在後幾節的例子中將會說到。

4、指定訓練參數進行訓練,這步非常重要,在例子中,將詳細進行說明

5、完成訓練後,就可以調用訓練結果,輸入測試數據,進行測試

6、數據進行反歸一化

7、誤差分析、結果預測或分類,作圖等

數據歸一化問題

歸一化的意義:

首先說一下,在工程應用領域中,應用BP網絡的好壞最關鍵的仍然是輸入特徵選擇和訓練樣本集的準備,若樣本集代表性差、矛盾樣本多、數據歸一化存在問題,那麼,使用多複雜的綜合算法、多精緻的網絡結構,建立起來的模型預測效果不會多好。若想取得實際有價值的應用效果,從最基礎的數據整理工作做起吧,會少走彎路的。

歸一化是爲了加快訓練網絡的收斂性,具體做法是:

1 把數變爲(01)之間的小數

主要是爲了數據處理方便提出來的,把數據映射到0~1範圍之內處理,更加便捷快速,應該歸到數字信號處理範疇之內。

2 把有量綱表達式變爲無量綱表達式

歸一化是一種簡化計算的方式,即將有量綱的表達式,經過變換,化爲無量綱的表達式,成爲純量

比如,複數阻抗可以歸一化書寫:Z = R + jωL = R(1 + jωL/R) ,複數部分變成了純數量了,沒有量綱。另外,微波之中也就是電路分析、信號系統、電磁波傳輸等,有很多運算都可以如此處理,既保證了運算的便捷,又能凸現出物理量的本質含義。

神經網絡歸一化方法:

由於採集的各數據單位不一致,因而須對數據進行[-1,1]歸一化處理,歸一化方法主要有如下幾種,供大家參考:

1、線性函數轉換,表達式如下:

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

說明:x、y分別爲轉換前、後的值,MaxValue、MinValue分別爲樣本的最大值和最小值。

2、對數函數轉換,表達式如下:

y=log10(x)

說明:以10爲底的對數函數轉換。

3、反餘切函數轉換,表達式如下:

y=atan(x)*2/PI

matlab中歸一化的實現:

matlab中的歸一化處理有五種方法,只會其中一種就可以了,我喜歡用第4種,因爲習慣和方便

注意:第一組和第二組歸一化函數在Matlab7.0以上已遺棄,他們的用法相似,pre**是歸一化,post**是反歸一化,tram**是使用同樣的設置歸一化另外一組數據

1. 內部函數premnmxpostmnmxtramnmx,將數據歸一化到(-1,1)

premnmx的語法格式是

:[Pn,minp,maxp,Tn,mint,maxt]=premnmx(P,T)

其中P,T分別爲原始輸入和輸出數據,minp和maxp分別爲P中的最小值和最大值。mint和maxt分別爲T的最小值和最大值。

我們在訓練網絡時,如果所用的是經過歸一化的樣本數據,那麼以後使用網絡時所用的新數據也應該和樣本數據接受相同的預處理,這就要用到tramnmx,換句話說使用同一個歸一化設置(setting)歸一化另外一組數據。如下所示:

[Pn]=tramnmx(P,minp,maxp)

其中P和Pn分別爲變換前、後的輸入數據,maxp和minp分別爲premnmx函返回的最大值maxp和最小值minp。

2prestdpoststdtrastd歸化數據到(0,1)

用法與1差不多。詳細可以help prestd。

上述兩種方法是可以相互轉化的,比如,第一種歸化後的數據爲p,則(1+p)./2的結果就是第二種了

3mapminmax()將數據歸一化到(-1,1),是6.5**mnmx系列的替換函數

該函數同時可以執行歸一化、反歸一化和歸一化其他數據的功能,具體看幫助和後面的實例

% 歸一化數據輸入爲p,輸出爲t
 
[normInput,ps] = mapminmax(p);
 
[normTarget,ts] = mapminmax(t);
 
% 反歸一化
 
trainOutput = mapminmax('reverse',normTrainOutput,ts);
 
trainInsect = mapminmax('reverse',trainSamples.T,ts);
 
validateOutput = mapminmax('reverse',normValidateOutput,ts);
 
validateInsect = mapminmax('reverse',validateSamples.T,ts);
 
testOutput = mapminmax('reverse',normTestOutput,ts);
 
testInsect = mapminmax('reverse',testSamples.T,ts);
 
%例子:
 
x1 = [1 2 4; 1 1 1; 3 2 2; 0 0 0]
 
[y1,PS] = mapminmax(x1,0,1)% 歸化到 [0,1],若不填,則默認爲[-1,1]
 
%還原:
 
x1_again = mapminmax('reverse',y1,PS)


 

4mapstd()將數據歸一化到(0,1),是6.5**std系列的替代函數

同理,3和4兩種方法是可以相互轉化的,比如,第一種歸化後的數據爲p,則(1+p)./2的結果就是第二種了。

5、自己寫歸一化函數,這個網上很多,大家可以百度下

輸入訓練數據的亂序排法,以及分類

注意:dividevec()函數在7.6版本還可以使用

把數據重新打亂順序,進行輸入,可以讓數據更加具備典型性和更優良的泛化能力!

把數據進行打亂,並分類爲:訓練輸入數據、變量數據、測試數據的方法

我用百度搜了一下,發現有些方法,但居然很少看到使用matlab內部函數直接進行的,其實matlab自帶的內部函數dividevec,完全能勝任上述工作,推薦!

但這個存在一個問題是,因爲打亂了,最後分析結果的時候,數據重新排列困難,因爲丟失了數據在數組中的位置參數。具體用法可以參見下面我的bp交通預測的例子。

因爲我用的7.0版本,Neural Network Toolbox Version 5.0.2  (R2007a)

昨天,我去mathworks公司查看了一下nnet的新手冊,上述問題得到了解決,裏面視乎沒有介紹dividverc這個函數了,但增加了新的函數來完成上述功能,並返回標號(手頭沒裝新版本Neural Network Toolbox  Version 6.0  (R2008a)),看guide大概是這個意思(有新版本的,可以試一下,這個函數是不是這個意思):

divideblock,divideind,divideint和dividerand

上述函數,用法和功能基本相同,只是打亂的方法不一樣,分別是block方法抽取、按數組標號自定義抽取、交錯索引抽取和隨機抽。

下面以divideblock爲例,講解其基本用法:

[trainV,valV,testV,trainInd,valInd,testInd] =divideblock(allV,trainRatio,valRatio,testRatio)

[訓練數據,變量數據,測試數據,訓練數據矩陣的標號,變量數據標號,測試數據標號] =divideblock(所有數據,訓練數據百分比,變量數據百分比,測試數據百分比)

其實dividevec和後面四個分類函數的區別在於,dividevec一般直接在Matlab代碼中調用。

而後面四個函數是通過設置網絡的divideFcn函數來實現,比如,net.divideFcn='divideblock',但不是說不可以在代碼中像dividevec直接調用

如何查看和保存結果

訓練好的權值、閾值的輸出方法是:

輸入到隱層權值

w1=net.iw{1,1}

隱層閾值

theta1=net.b{1}

隱層到輸出層權值

w2=net.lw{2,1};

輸出層閾值

theta2=net.b{2}

訓練好的BP神經網絡保存:

%保存

save file_name net_name%Matlab自動將網絡保存爲mat數據文件,下次使用時可以直接載入

%載入

load file_name

每次結果不一樣問題

因爲每次初始化網絡時都是隨機的,而且訓練終止時的誤差也不完全相同,結果訓練後的權植和閥也不完全相同(大致是一樣的),所以每次訓練後的結果也略有不同。

找到比較好的結果後,用命令save filen_ame net_name保存網絡,可使預測的結果不會變化,在需要的調用時用命令load filename載入。

關於如何找到比較好的結果,進行保存,可以設置誤差,在循環中保存,具體使用可以參看bp交通預測優化後的例子

%bp神經網絡進行交通預測的Matlab源代碼
 
% BP 神經網絡用於預測
 
% 使用平臺 - Matlab7.0
 
% 數據爲1986年到2000年的交通量 ,網絡爲3輸入,1輸出
 
% 15組數據,其中9組爲正常訓練數據,3組爲變量數據,3組爲測試數據
 
%by akjuan
 
%all rights preserved by www.4math.cn
 
%2008.11
 
clc
 
clear
 
%---------------------------------------------------
 
%原始數據
 
%---------------------------------------------------
 
year=1986:2000;%數據是從1986到2000年的
 
 
 
p=[493 372 445;372 445 176;445 176 235;176 235 378;235 378 429;...
 
   378 429 561;429 561 651;561 651 467;651 467 527;467 527 668;...
 
   527 668 841; 668 841 526;841 526 480;526 480 567;480 567 685]';%輸入數據,共15組,每組3個輸入
 
t=[176 235 378 429 561 651 467 527 668 841 526 480 567 685 507];%輸出數據,共15組,每組1個輸出
 
 
 
 
 
%---------------------------------------------------
 
%數據歸一化處理
 
%mapminmax函數默認將數據歸一化到[-1,1],調用形式如下
 
%[y,ps] =%mapminmax(x,ymin,ymax)
 
%x需歸化的數據輸入
 
%ymin,ymax爲需歸化到的範圍,不填默認爲歸化到[-1,1]
 
%y歸一化後的樣本數據
 
%ps處理設置,ps主要在結果反歸一化中需要調用,或者使用同樣的settings歸一化另外一組數據
 
%---------------------------------------------------
 
[normInput,ps] = mapminmax(p);
 
[normTarget,ts] = mapminmax(t);
 
 
 
 
 
%---------------------------------------------------
 
%數據亂序,及分類處理
 
%將輸入的15組數據的20%,即3組,用來作爲測試數據;
 
% 樣本的20%,即3組,用來作爲變化數據;
 
%另外9組用來正常輸入,用來訓練;
 
%dividevec()用來重新隨機抽取上述三種分類的數據,原來的順序被打亂
 
%函數調用的語法
 
%[trainV,valV,testV] = dividevec(p,t,valPercent,testPercent)
 
%輸入p爲輸入數據,t爲輸出數據
 
%valPercent爲訓練用的變化數據在總輸入中的百分比
 
%testPercent爲訓練用的測試數據在總輸入中的百分比
 
%輸出trainV,valV,testV分別爲按亂序及相應百分比,抽取得到的數據
 
%另外,打亂後的數據,p和t都是對應的,請放心使用
 
%---------------------------------------------------
 
testPercent = 0.20;  % Adjust as desired
 
validatePercent = 0.20;  % Adust as desired
 
[trainSamples,validateSamples,testSamples] = dividevec(normInput,normTarget,validatePercent,testPercent);
 
 
 
 
 
%---------------------------------------------------
 
% 設置網絡參數
 
%---------------------------------------------------   

NodeNum1 = 20; % 隱層第一層節點數
 
NodeNum2 = 40;   % 隱層第二層節點數
 
TypeNum = 1;   % 輸出維數
 
 
 
TF1 = 'tansig';TF2 = 'tansig'; TF3 = 'tansig';%各層傳輸函數,TF3爲輸出層傳輸函數
 
%如果訓練結果不理想,可以嘗試更改傳輸函數,以下這些是各類傳輸函數
 
%TF1 = 'tansig';TF2 = 'logsig';
 
%TF1 = 'logsig';TF2 = 'purelin';
 
%TF1 = 'tansig';TF2 = 'tansig';
 
%TF1 = 'logsig';TF2 = 'logsig';
 
%TF1 = 'purelin';TF2 = 'purelin'; 

 
 
%注意創建BP網絡函數newff()的參數調用,在新版本(7.6)中已改變
 
net=newff(minmax(normInput),[NodeNum1,NodeNum2,TypeNum],{TF1 TF2 TF3},'traingdx');%創建四層BP網絡
 
 
 
 
 
 
 
%---------------------------------------------------
 
% 設置訓練參數
 
%---------------------------------------------------   

net.trainParam.epochs=10000;%訓練次數設置
 
net.trainParam.goal=1e-6;%訓練目標設置
 
net.trainParam.lr=0.01;%學習率設置,應設置爲較少值,太大雖然會在開始加快收斂速度,但臨近最佳點時,會產生動盪,而致使無法收斂
 
%---------------------------------------------------
 
% 指定訓練函數
 
%---------------------------------------------------
 
% net.trainFcn = 'traingd'; % 梯度下降算法
 
% net.trainFcn = 'traingdm'; % 動量梯度下降算法
 
%
 
% net.trainFcn = 'traingda'; % 變學習率梯度下降算法
 
% net.trainFcn = 'traingdx'; % 變學習率動量梯度下降算法
 
%
 
% (大型網絡的首選算法)
 
% net.trainFcn = 'trainrp'; % RPROP(彈性BP)算法,內存需求最小
 
%
 
% (共軛梯度算法)
 
% net.trainFcn = 'traincgf'; % Fletcher-Reeves修正算法
 
% net.trainFcn = 'traincgp'; % Polak-Ribiere修正算法,內存需求比Fletcher-Reeves修正算法略大
 
% net.trainFcn = 'traincgb'; % Powell-Beal復位算法,內存需求比Polak-Ribiere修正算法略大
 
%
 
% (大型網絡的首選算法)
 
%net.trainFcn = 'trainscg'; % Scaled Conjugate Gradient算法,內存需求與Fletcher-Reeves修正算法相同,計算量比上面三種算法都小很多
 
% net.trainFcn = 'trainbfg'; % Quasi-Newton Algorithms - BFGS Algorithm,計算量和內存需求均比共軛梯度算法大,但收斂比較快
 
% net.trainFcn = 'trainoss'; % One Step Secant Algorithm,計算量和內存需求均比BFGS算法小,比共軛梯度算法略大
 
%
 
% (中型網絡的首選算法)
 
%net.trainFcn = 'trainlm'; % Levenberg-Marquardt算法,內存需求最大,收斂速度最快
 
% net.trainFcn = 'trainbr'; % 貝葉斯正則化算法
 
%
 
% 有代表性的五種算法爲:'traingdx','trainrp','trainscg','trainoss', 'trainlm'
 
 
 
net.trainfcn='traingdm';
 
[net,tr] = train(net,trainSamples.P,trainSamples.T,[],[],validateSamples,testSamples);
 
 
 
%---------------------------------------------------
 
% 訓練完成後,就可以調用sim()函數,進行仿真了
 
%---------------------------------------------------   

[normTrainOutput,Pf,Af,E,trainPerf] = sim(net,trainSamples.P,[],[],trainSamples.T);%正常輸入的9組p數據,BP得到的結果t
 
[normValidateOutput,Pf,Af,E,validatePerf] = sim(net,validateSamples.P,[],[],validateSamples.T);%用作變量3的數據p,BP得到的結果t
 
[normTestOutput,Pf,Af,E,testPerf] = sim(net,testSamples.P,[],[],testSamples.T);%用作測試的3組數據p,BP得到的結果t
 
 
 
 
 
%---------------------------------------------------
 
% 仿真後結果數據反歸一化,如果需要預測,只需將預測的數據P填入
 
% 將獲得預測結果t
 
%---------------------------------------------------  

trainOutput = mapminmax('reverse',normTrainOutput,ts);%正常輸入的9組p數據,BP得到的歸一化後的結果t
 
trainInsect = mapminmax('reverse',trainSamples.T,ts);%正常輸入的9組數據t
 
validateOutput = mapminmax('reverse',normValidateOutput,ts);%用作變量3的數據p,BP得到的歸一化的結果t
 
validateInsect = mapminmax('reverse',validateSamples.T,ts);%用作變量3的數據t
 
testOutput = mapminmax('reverse',normTestOutput,ts);%用作變量3組數據p,BP得到的歸一化的結果t
 
testInsect = mapminmax('reverse',testSamples.T,ts);%用作變量3組數據t
 
 
 
 
 
%---------------------------------------------------
 
% 數據分析和繪圖
 
%---------------------------------------------------  

figure
 
plot(1:12,[trainOutput validateOutput],'b-',1:12,[trainInsect validateInsect],'g--',13:15,testOutput,'m*',13:15,testInsect,'ro');
 
title('o爲真實值,*爲預測值')
 
xlabel('年份');
 
ylabel('交通量(輛次/晝夜)');


 

但通過程序運行後,可以看出,預測效果並不理想,如何得到理想的預測訓練結果,下面是基本思路及matlab的實現:

1、設置一個誤差項,爲測試數據的網絡仿真結果和實際結果偏差,並設置一個自己能接受的精度值

2、每次訓練網絡後,將這個誤差和設置值比較,也可通過測試獲得網絡能給出的最高預測精度

3、得到滿意訓練網絡後,保存BP結果,以便下次調用

下面這個程序是在第四節程序基礎上優化而來,可以運行前面的程序和這個程序,比較兩者的差別,可以通過修改eps來控制預測的誤差!

 

%bp神經網絡進行交通預測的Matlab源代碼
 
% BP 神經網絡用於預測
 
% 使用平臺 - Matlab7.0
 
% 數據爲1986年到2000年的交通量 ,網絡爲3輸入,1輸出
 
% 15組數據,其中9組爲正常訓練數據,3組爲變量數據,3組爲測試數據
 
%by akjuan
 
%all rights preserved by www.matlabsky.cn
 
%2008.11
 
 
 
clc
 
clear
 
All_error=[];%所有誤差存儲
 
 
 
%---------------------------------------------------
 
%原始數據
 
%---------------------------------------------------
 
year=1986:2000;%數據是從1986到2000年的
 
 
 
p=[493 372 445;372 445 176;445 176 235;176 235 378;235 378 429;...
 
   378 429 561;429 561 651;561 651 467;651 467 527;467 527 668;...
 
   527 668 841; 668 841 526;841 526 480;526 480 567;480 567 685]';%輸入數據,共15組,每組3個輸入
 
t=[176 235 378 429 561 651 467 527 668 841 526 480 567 685 507];%輸出數據,共15組,每組1個輸出
 
 
 
%---------------------------------------------------
 
%數據歸一化處理
 
%mapminmax函數默認將數據歸一化到[-1,1],調用形式如下
 
%[y,ps] =%mapminmax(x,ymin,ymax)
 
%x需歸化的數據輸入
 
%ymin,ymax爲需歸化到的範圍,不填默認爲歸化到[-1,1]
 
%y歸一化後的樣本數據
 
%ps處理設置,ps主要在結果反歸一化中需要調用,或者使用同樣的settings歸一化另外一組數據
 
%---------------------------------------------------
 
[normInput,ps] = mapminmax(p);
 
[normTarget,ts] = mapminmax(t);
 
 
 
%---------------------------------------------------
 
%數據亂序,及分類處理
 
%將輸入的15組數據的20%,即3組,用來作爲測試數據;
 
% 樣本的20%,即3組,用來作爲變化數據;
 
%另外9組用來正常輸入,用來訓練;
 
%dividevec()用來重新隨機抽取上述三種分類的數據,原來的順序被打亂
 
%函數調用的語法
 
%[trainV,valV,testV] = dividevec(p,t,valPercent,testPercent)
 
%輸入p爲輸入數據,t爲輸出數據
 
%valPercent爲訓練用的變化數據在總輸入中的百分比
 
%testPercent爲訓練用的測試數據在總輸入中的百分比
 
%輸出trainV,valV,testV分別爲按亂序及相應百分比,抽取得到的數據
 
%另外,打亂後的數據,p和t都是對應的,請放心使用
 
%---------------------------------------------------
 
testPercent = 0.20;  % Adjust as desired
 
validatePercent = 0.20;  % Adust as desired
 
[trainSamples,validateSamples,testSamples] = dividevec(normInput,normTarget,validatePercent,testPercent);
 
 
 
for j=1:200
 
%---------------------------------------------------
 
% 設置網絡參數
 
%---------------------------------------------------   

NodeNum1 = 20; % 隱層第一層節點數
 
NodeNum2=40;   % 隱層第二層節點數
 
TypeNum = 1;   % 輸出維數
 
 
 
TF1 = 'tansig';TF2 = 'tansig'; TF3 = 'tansig';%各層傳輸函數,TF3爲輸出層傳輸函數
 
%如果訓練結果不理想,可以嘗試更改傳輸函數,以下這些是各類傳輸函數
 
%TF1 = 'tansig';TF2 = 'logsig';
 
%TF1 = 'logsig';TF2 = 'purelin';
 
%TF1 = 'tansig';TF2 = 'tansig';
 
%TF1 = 'logsig';TF2 = 'logsig';
 
%TF1 = 'purelin';TF2 = 'purelin'; 

 
 
 
 
net=newff(minmax(normInput),[NodeNum1,NodeNum2,TypeNum],{TF1 TF2 TF3},'traingdx');%網絡創建
 
 
 
 
 
%---------------------------------------------------
 
% 設置訓練參數
 
%---------------------------------------------------   

net.trainParam.epochs=10000;%訓練次數設置
 
net.trainParam.goal=1e-6;%訓練目標設置
 
net.trainParam.lr=0.01;%學習率設置,應設置爲較少值,太大雖然會在開始加快收斂速度,但臨近最佳點時,會產生動盪,而致使無法收斂
 
%---------------------------------------------------
 
% 指定訓練參數
 
%---------------------------------------------------
 
% net.trainFcn = 'traingd'; % 梯度下降算法
 
% net.trainFcn = 'traingdm'; % 動量梯度下降算法
 
%
 
% net.trainFcn = 'traingda'; % 變學習率梯度下降算法
 
% net.trainFcn = 'traingdx'; % 變學習率動量梯度下降算法
 
%
 
% (大型網絡的首選算法)
 
% net.trainFcn = 'trainrp'; % RPROP(彈性BP)算法,內存需求最小
 
%
 
% (共軛梯度算法)
 
% net.trainFcn = 'traincgf'; % Fletcher-Reeves修正算法
 
% net.trainFcn = 'traincgp'; % Polak-Ribiere修正算法,內存需求比Fletcher-Reeves修正算法略大
 
% net.trainFcn = 'traincgb'; % Powell-Beal復位算法,內存需求比Polak-Ribiere修正算法略大
 
%
 
% (大型網絡的首選算法)
 
%net.trainFcn = 'trainscg'; % Scaled Conjugate Gradient算法,內存需求與Fletcher-Reeves修正算法相同,計算量比上面三種算法都小很多
 
% net.trainFcn = 'trainbfg'; % Quasi-Newton Algorithms - BFGS Algorithm,計算量和內存需求均比共軛梯度算法大,但收斂比較快
 
% net.trainFcn = 'trainoss'; % One Step Secant Algorithm,計算量和內存需求均比BFGS算法小,比共軛梯度算法略大
 
%
 
% (中型網絡的首選算法)
 
%net.trainFcn = 'trainlm'; % Levenberg-Marquardt算法,內存需求最大,收斂速度最快
 
% net.trainFcn = 'trainbr'; % 貝葉斯正則化算法
 
%
 
% 有代表性的五種算法爲:'traingdx','trainrp','trainscg','trainoss', 'trainlm'
 
 
 
net.trainfcn='traingdm';
 
[net,tr] = train(net,trainSamples.P,trainSamples.T,[],[],validateSamples,testSamples);
 
 
 
%---------------------------------------------------
 
% 訓練完成後,就可以調用sim()函數,進行仿真了
 
%---------------------------------------------------   

[normTrainOutput,Pf,Af,E,trainPerf] = sim(net,trainSamples.P,[],[],trainSamples.T);%正常輸入的9組p數據,BP得到的結果t
 
[normValidateOutput,Pf,Af,E,validatePerf] = sim(net,validateSamples.P,[],[],validateSamples.T);%用作變量3的數據p,BP得到的結果t
 
[normTestOutput,Pf,Af,E,testPerf] = sim(net,testSamples.P,[],[],testSamples.T);%用作測試的3組數據p,BP得到的結果t
 
 
 
 
 
%---------------------------------------------------
 
% 仿真後結果數據反歸一化,如果需要預測,只需將預測的數據P填入
 
% 將獲得預測結果t
 
%---------------------------------------------------  

trainOutput = mapminmax('reverse',normTrainOutput,ts);%正常輸入的9組p數據,BP得到的歸一化後的結果t
 
trainInsect = mapminmax('reverse',trainSamples.T,ts);%正常輸入的9組數據t
 
validateOutput = mapminmax('reverse',normValidateOutput,ts);%用作變量3的數據p,BP得到的歸一化的結果t
 
validateInsect = mapminmax('reverse',validateSamples.T,ts);%用作變量3的數據t
 
testOutput = mapminmax('reverse',normTestOutput,ts);%用作變量3組數據p,BP得到的歸一化的結果t
 
testInsect = mapminmax('reverse',testSamples.T,ts);%用作變量3組數據t
 
 
 
%絕對誤差計算
 
absTrainError = trainOutput-trainInsect;
 
absTestError = testOutput-testInsect;
 
error_sum=sqrt(absTestError(1).^2+absTestError(2).^2+absTestError(3).^2);
 
All_error=[All_error error_sum];
 
eps=90;%其爲3組測試數據的標準差,或者每個數據偏差在一定範圍內而判別
 
if ((abs(absTestError(1))<=30 )&(abs(absTestError(2))<=30)&(abs(absTestError(3))<=30)|(error_sum<=eps))
 
save mynetdata net
 
     break
 
end
 
j
 
end
 
j
 
Min_error_sqrt=min(All_error)
 
 
 
testOutput
 
testInsect
 
 
 
%---------------------------------------------------
 
% 數據分析和繪圖
 
%---------------------------------------------------  

figure
 
plot(1:12,[trainOutput validateOutput],'b-',1:12,[trainInsect validateInsect],'g--',13:15,testOutput,'m*',13:15,testInsect,'ro');
 
title('o爲真實值,*爲預測值')
 
xlabel('年份');
 
ylabel('交通量(輛次/晝夜)');
 
figure
 
xx=1:length(All_error);
 
plot(xx,All_error)
 
title('誤差變化圖')


 

 

from:http://www.matlabsky.com/thread-2553-1-1.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章