1. 程式人生 > >BP神經網路學習及matlab實現

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