《BP神經網絡的MATLAB實現》

一. BP神經網絡實現(不使用MATLAB神經網絡工具箱)

1. 問題

公路運量主要包括公路客運量和公路貨運量兩方面。某個地區的公路運量主要與該地區的人數、機動車數量和公路面積有關,已知該地區20年(1990-2009)的公路運量相關數據如下:

人數/萬人

20.55 22.44 25.37 27.13 29.45 30.10 30.96 34.06 36.42 38.09 39.13 39.99 41.93 44.59 47.30 52.89 55.73 56.76 59.17 60.63

機動車數量/萬輛

0.6 0.75 0.85 0.9 1.05 1.35 1.45 1.6 1.7 1.85 2.15 2.2 2.25 2.35 2.5 2.6 2.7 2.85 2.95 3.1

公路面積/單位:萬平方公里

0.09 0.11 0.11 0.14 0.20 0.23 0.23 0.32 0.32 0.34 0.36 0.36 0.38 0.49 0.56 0.59 0.59 0.67 0.69 0.79

公路客運量/萬人

5126 6217 7730 9145 10460 11387 12353 15750 18304 19836 21024 19490 20433 22598 25107 33442 36836 40548 42927 43462

公路貨運量/萬噸

1237 1379 1385 1399 1663 1714 1834 4322 8132 8936 11099 11203 10524 11115 13320 16762 18673 20724 20803 21804



2. 分析

樣本數據較多,且已知影響數據的因素(三大因素:該地區的人數、機動車數量和公路面積),可考慮將其作爲BP神經網絡的訓練集,對該神經網絡進行訓練,然後對訓練好的神經網絡進行測試,最後使用測試合格的神經網絡進行預測工作。



3. MATLAB實現代碼

BP_road.m

numberOfSample = 20; %輸入樣本數量
%取測試樣本數量等於輸入(訓練集)樣本數量,因爲輸入樣本(訓練集)容量較少,否則一般必須用新鮮數據進行測試
numberOfTestSample = 20; 
numberOfForcastSample = 2; 
numberOfHiddenNeure = 8;
inputDimension = 3;
outputDimension = 2;


%準備好訓練集

%人數(單位:萬人)
numberOfPeople=[20.55 22.44 25.37 27.13 29.45 30.10 30.96 34.06 36.42 38.09 39.13 39.99 41.93 44.59 47.30 52.89 55.73 56.76 59.17 60.63];
%機動車數(單位:萬輛)
numberOfAutomobile=[0.6 0.75 0.85 0.9 1.05 1.35 1.45 1.6 1.7 1.85 2.15 2.2 2.25 2.35 2.5 2.6 2.7 2.85 2.95 3.1];
%公路面積(單位:萬平方公里)
roadArea=[0.09 0.11 0.11 0.14 0.20 0.23 0.23 0.32 0.32 0.34 0.36 0.36 0.38 0.49 0.56 0.59 0.59 0.67 0.69 0.79];
%公路客運量(單位:萬人)
passengerVolume = [5126 6217 7730 9145 10460 11387 12353 15750 18304 19836 21024 19490 20433 22598 25107 33442 36836 40548 42927 43462];
%公路貨運量(單位:萬噸)
freightVolume = [1237 1379 1385 1399 1663 1714 1834 4322 8132 8936 11099 11203 10524 11115 13320 16762 18673 20724 20803 21804];

%由系統時鐘種子產生隨機數
rand('state', sum(100*clock));

%輸入數據矩陣
input = [numberOfPeople; numberOfAutomobile; roadArea];
%目標(輸出)數據矩陣
output = [passengerVolume; freightVolume];

%對訓練集中的輸入數據矩陣和目標數據矩陣進行歸一化處理
[sampleInput, minp, maxp, tmp, mint, maxt] = premnmx(input, output);

%噪聲強度
noiseIntensity = 0.01;
%利用正態分佈產生噪聲
noise = noiseIntensity * randn(outputDimension, numberOfSample);
%給樣本輸出矩陣tmp添加噪聲,防止網絡過度擬合
sampleOutput = tmp + noise;

%取測試樣本輸入(輸出)與輸入樣本相同,因爲輸入樣本(訓練集)容量較少,否則一般必須用新鮮數據進行測試
testSampleInput = sampleInput;
testSampleOutput = sampleOutput;

%最大訓練次數
maxEpochs = 50000;

%網絡的學習速率
learningRate = 0.035;

%訓練網絡所要達到的目標誤差
error0 = 0.65*10^(-3);

%初始化輸入層與隱含層之間的權值
W1 = 0.5 * rand(numberOfHiddenNeure, inputDimension) - 0.1;
%初始化輸入層與隱含層之間的閾值
B1 = 0.5 * rand(numberOfHiddenNeure, 1) - 0.1;
%初始化輸出層與隱含層之間的權值
W2 = 0.5 * rand(outputDimension, numberOfHiddenNeure) - 0.1;
%初始化輸出層與隱含層之間的閾值
B2 = 0.5 * rand(outputDimension, 1) - 0.1;

%保存能量函數(誤差平方和)的歷史記錄
errorHistory = [];

for i = 1:maxEpochs
    %隱含層輸出
    hiddenOutput = logsig(W1 * sampleInput + repmat(B1, 1, numberOfSample));
    %輸出層輸出
    networkOutput = W2 * hiddenOutput + repmat(B2, 1, numberOfSample);
    %實際輸出與網絡輸出之差
    error = sampleOutput - networkOutput;
    %計算能量函數(誤差平方和)
    E = sumsqr(error);
    errorHistory = [errorHistory E];

    if E < error0
        break;
    end

    %以下依據能量函數的負梯度下降原理對權值和閾值進行調整
    delta2 = error;
    delta1 = W2' * delta2.*hiddenOutput.*(1 - hiddenOutput);

    dW2 = delta2 * hiddenOutput';
    dB2 = delta2 * ones(numberOfSample, 1);

    dW1 = delta1 * sampleInput';
    dB1 = delta1 * ones(numberOfSample, 1);

    W2 = W2 + learningRate * dW2;
    B2 = B2 + learningRate * dB2;

    W1 = W1 + learningRate * dW1;
    B1 = B1 + learningRate * dB1;
end

%下面對已經訓練好的網絡進行(仿真)測試

%對測試樣本進行處理
testHiddenOutput = logsig(W1 * testSampleInput + repmat(B1, 1, numberOfTestSample));
testNetworkOutput =  W2 * testHiddenOutput + repmat(B2, 1, numberOfTestSample);
%還原網絡輸出層的結果(反歸一化)
a = postmnmx(testNetworkOutput, mint, maxt);

%繪製測試樣本神經網絡輸出和實際樣本輸出的對比圖(figure(1))--------------------------------------
t = 1990:2009;

%測試樣本網絡輸出客運量
a1 = a(1,:); 
%測試樣本網絡輸出貨運量
a2 = a(2,:);

figure(1);
subplot(2, 1, 1); plot(t, a1, 'ro', t, passengerVolume, 'b+');
legend('網絡輸出客運量', '實際客運量');
xlabel('年份'); ylabel('客運量/萬人');
title('神經網絡客運量學習與測試對比圖');
grid on;

subplot(2, 1, 2); plot(t, a2, 'ro', t, freightVolume, 'b+');
legend('網絡輸出貨運量', '實際貨運量');
xlabel('年份'); ylabel('貨運量/萬噸');
title('神經網絡貨運量學習與測試對比圖');
grid on;

%使用訓練好的神經網絡對新輸入數據進行預測

%新輸入數據(2010年和2011年的相關數據)
newInput = [73.39 75.55; 3.9635 4.0975; 0.9880 1.0268]; 

%利用原始輸入數據(訓練集的輸入數據)的歸一化參數對新輸入數據進行歸一化
newInput = tramnmx(newInput, minp, maxp);

newHiddenOutput = logsig(W1 * newInput + repmat(B1, 1, numberOfForcastSample));
newOutput = W2 * newHiddenOutput + repmat(B2, 1, numberOfForcastSample);
newOutput = postmnmx(newOutput, mint, maxt);

disp('預測2010和2011年的公路客運量分別爲(單位:萬人):');
newOutput(1,:)
disp('預測2010和2011年的公路貨運量分別爲(單位:萬噸):');
newOutput(2,:)

%在figure(1)的基礎上繪製2010和2011年的預測情況-------------------------------------------------
figure(2);
t1 = 1990:2011;

subplot(2, 1, 1); plot(t1, [a1 newOutput(1,:)], 'ro', t, passengerVolume, 'b+');
legend('網絡輸出客運量', '實際客運量');
xlabel('年份'); ylabel('客運量/萬人');
title('神經網絡客運量學習與測試對比圖(添加了預測數據)');
grid on;

subplot(2, 1, 2); plot(t1, [a2 newOutput(2,:)], 'ro', t, freightVolume, 'b+');
legend('網絡輸出貨運量', '實際貨運量');
xlabel('年份'); ylabel('貨運量/萬噸');
title('神經網絡貨運量學習與測試對比圖(添加了預測數據)');
grid on;

%觀察能量函數(誤差平方和)在訓練神經網絡過程中的變化情況------------------------------------------
figure(3);

n = length(errorHistory);
t3 = 1:n;
plot(t3, errorHistory, 'r-');

%爲了更加清楚地觀察出能量函數值的變化情況,這裏我只繪製前100次的訓練情況
xlim([1 100]);
xlabel('訓練過程');
ylabel('能量函數值');
title('能量函數(誤差平方和)在訓練神經網絡過程中的變化圖');
grid on;



4. 運行結果

預測2010和2011年的公路客運量分別爲(單位:萬人):

ans =

1.0e+04 *

4.6188 4.6601

預測2010和2011年的公路貨運量分別爲(單位:萬噸):

ans =

1.0e+04 *

2.1521 2.1519



5. 繪製的圖像

  1. figure(1)
    1



2. figure(2)
2


3. figure(3)
3

可以看出,使用BP網絡中的負梯度下降原理之後,效果顯著。





二. 使用MATLAB的神經網絡工具箱簡易實現BP網絡

1. 問題

同<一>



2. 分析

同<一>



3. 工具箱中的相關函數(一些參考了MATLAB自帶的英文手冊)

mapminmax函數

  • 功能:通過將原矩陣每行的最小值和最大值映射到[YMIN,YMAX]來得到規範化的矩陣。
  • 算法:y = ( ymax - ymin ) * ( x - xmin ) / ( xmax - xmin ) + ymin

(注:當xmax與xmin相等時,則對原矩陣使用mapminmax函數仍得到原矩陣)

  • 默認算法:

(默認情況下,mapminmax函數的YMIN和YMAX分別是-1和1)

y = 2 * ( x - xmin ) / ( xmax - xmin ) - 1

  • [Y,PS] = mapminmax(X)

    • X:原矩陣
    • Y:對矩陣X進行規範化得到的矩陣
    • PS:存放關於原矩陣規範化過程中的相關映射數據的結構體
  • [Y,PS] = mapminmax(X,FP)

    • X:原矩陣

    • FP:含有字段FP.ymin和FP.ymax的結構體

    • Y:對矩陣X進行規範化得到的矩陣(使用在FP的ymin和ymax規定下的算法)

    • PS:存放關於原矩陣規範化過程中的相關映射數據的結構體

  • Y = mapminmax(‘apply’,X,PS)

    • ’apply’:必寫
    • X:原矩陣
    • PS:存放關於某個矩陣規範化過程中的相關映射數據的結構體
    • Y:對矩陣X進行規範化得到的矩陣(使用PS中的規範化方式)
  • X = mapminmax(‘reverse’,Y,PS)

    • ’reverse’:必寫
    • Y:某個矩陣
    • PS:存放關於某個矩陣規範化過程中的相關映射數據的結構體
    • X:將矩陣Y反規範化得到的矩陣(使用PS中的規範化方式,這裏指將矩陣X轉換爲矩陣Y的規範化方式)


newff函數(新版本)

  • a. 功能:建立一個前饋反向傳播(BP)網絡。

  • b. net=newff(P,T,S)

    • P: 輸入數據矩陣。(RxQ1),其中Q1代表R元的輸入向量。其數據意義是矩陣P有Q1列,每一列都是一個樣本,而每個樣本有R個屬性(特徵)。一般矩陣P需要事先歸一化好,即P的每一行都歸一化到[0 1]或者[-1 1]。
    • T:目標數據矩陣。(SNxQ2),其中Q2代表SN元的目標向量。數據意義參考上面,矩陣T也是事先歸一化好的。
    • S:第i層的神經元個數。(新版本中可以省略輸出層的神經元個數不寫,因爲輸出層的神經元個數已經取決於T)
  • ​c. net = newff(P,T,S,TF,BTF,BLF,PF,IPF,OPF,DDF)(提供了可選擇的參數)

    • TF:相關層的傳遞函數,默認隱含層使用tansig函數,輸出層使用purelin函數。
    • BTF:BP神經網絡學習訓練函數,默認值爲trainlm函數。
    • BLF:權重學習函數,默認值爲learngdm。
    • PF:性能函數,默認值爲mse。
    • PF,OPF,DDF均爲默認值即可。
  • d. 常用的傳遞函數:

    • purelin:線性傳遞函數
    • tansig:正切 S 型傳遞函數
    • logsig: 對數 S 型傳遞函數

(注意:隱含層和輸出層函數的選擇對BP神經網絡預測精度有較大影響,一般隱含層節點傳遞函數選用tansig函數或logsig函數,輸出層節點轉移函數選用tansig函數或purelin函數。)


關於net.trainParam的常用屬性

(假定已經定義了一個BP網絡net)
* net.trainParam.show: 兩次顯示之間的訓練次數
* net.trainParam.epochs: 最大訓練次數
* net.trainParam.lr: 網絡的學習速率
* net.trainParam.goal: 訓練網絡所要達到的目標誤差
* net.trainParam.time: 最長訓練時間(秒)


train函數

  • 功能:訓練一個神經網絡

  • [NET2,TR] = train(NET1,X,T)(也可[NET2] = train(NET1,X,T) )

    • NET1:待訓練的網絡
    • X: 輸入數據矩陣(已歸一化)
    • T:目標數據矩陣(已歸一化)
    • NET2:訓練得到的網絡TR:存放有關訓練過程的數據的結構體


sim函數

  • 功能:模擬Simulink模型

  • SimOut = sim(‘MODEL’, PARAMETERS)

    • (見名知意,不必再解釋)



4. MATLAB實現代碼

BP_toolbox_road.m

%準備好訓練集

%人數(單位:萬人)
numberOfPeople=[20.55 22.44 25.37 27.13 29.45 30.10 30.96 34.06 36.42 38.09 39.13 39.99 41.93 44.59 47.30 52.89 55.73 56.76 59.17 60.63];
%機動車數(單位:萬輛)
numberOfAutomobile=[0.6 0.75 0.85 0.9 1.05 1.35 1.45 1.6 1.7 1.85 2.15 2.2 2.25 2.35 2.5 2.6 2.7 2.85 2.95 3.1];
%公路面積(單位:萬平方公里)
roadArea=[0.09 0.11 0.11 0.14 0.20 0.23 0.23 0.32 0.32 0.34 0.36 0.36 0.38 0.49 0.56 0.59 0.59 0.67 0.69 0.79];
%公路客運量(單位:萬人)
passengerVolume = [5126 6217 7730 9145 10460 11387 12353 15750 18304 19836 21024 19490 20433 22598 25107 33442 36836 40548 42927 43462];
%公路貨運量(單位:萬噸)
freightVolume = [1237 1379 1385 1399 1663 1714 1834 4322 8132 8936 11099 11203 10524 11115 13320 16762 18673 20724 20803 21804];

%輸入數據矩陣
p = [numberOfPeople; numberOfAutomobile; roadArea];
%目標(輸出)數據矩陣
t = [passengerVolume; freightVolume];

%對訓練集中的輸入數據矩陣和目標數據矩陣進行歸一化處理
[pn, inputStr] = mapminmax(p);
[tn, outputStr] = mapminmax(t);

%建立BP神經網絡
net = newff(pn, tn, [3 7 2], {'purelin', 'logsig', 'purelin'});

%每10輪迴顯示一次結果
net.trainParam.show = 10;

%最大訓練次數
net.trainParam.epochs = 5000;

%網絡的學習速率
net.trainParam.lr = 0.05;

%訓練網絡所要達到的目標誤差
net.trainParam.goal = 0.65 * 10^(-3);

%網絡誤差如果連續6次迭代都沒變化,則matlab會默認終止訓練。爲了讓程序繼續運行,用以下命令取消這條設置
net.divideFcn = '';

%開始訓練網絡
net = train(net, pn, tn);

%使用訓練好的網絡,基於訓練集的數據對BP網絡進行仿真得到網絡輸出結果
%(因爲輸入樣本(訓練集)容量較少,否則一般必須用新鮮數據進行仿真測試)
answer = sim(net, pn);

%反歸一化
answer1 = mapminmax('reverse', answer, outputStr);

%繪製測試樣本神經網絡輸出和實際樣本輸出的對比圖(figure(1))-------------------------------------------
t = 1990:2009;

%測試樣本網絡輸出客運量
a1 = answer1(1,:); 
%測試樣本網絡輸出貨運量
a2 = answer1(2,:);

figure(1);
subplot(2, 1, 1); plot(t, a1, 'ro', t, passengerVolume, 'b+');
legend('網絡輸出客運量', '實際客運量');
xlabel('年份'); ylabel('客運量/萬人');
title('神經網絡客運量學習與測試對比圖');
grid on;

subplot(2, 1, 2); plot(t, a2, 'ro', t, freightVolume, 'b+');
legend('網絡輸出貨運量', '實際貨運量');
xlabel('年份'); ylabel('貨運量/萬噸');
title('神經網絡貨運量學習與測試對比圖');
grid on;

%使用訓練好的神經網絡對新輸入數據進行預測

%新輸入數據(2010年和2011年的相關數據)
newInput = [73.39 75.55; 3.9635 4.0975; 0.9880 1.0268]; 

%利用原始輸入數據(訓練集的輸入數據)的歸一化參數對新輸入數據進行歸一化
newInput = mapminmax('apply', newInput, inputStr);

%進行仿真
newOutput = sim(net, newInput);

%反歸一化
newOutput = mapminmax('reverse',newOutput, outputStr);

disp('預測2010和2011年的公路客運量分別爲(單位:萬人):');
newOutput(1,:)
disp('預測2010和2011年的公路貨運量分別爲(單位:萬噸):');
newOutput(2,:)

%在figure(1)的基礎上繪製2010和2011年的預測情況-------------------------------------------------------
figure(2);
t1 = 1990:2011;

subplot(2, 1, 1); plot(t1, [a1 newOutput(1,:)], 'ro', t, passengerVolume, 'b+');
legend('網絡輸出客運量', '實際客運量');
xlabel('年份'); ylabel('客運量/萬人');
title('神經網絡客運量學習與測試對比圖(添加了預測數據)');
grid on;

subplot(2, 1, 2); plot(t1, [a2 newOutput(2,:)], 'ro', t, freightVolume, 'b+');
legend('網絡輸出貨運量', '實際貨運量');
xlabel('年份'); ylabel('貨運量/萬噸');
title('神經網絡貨運量學習與測試對比圖(添加了預測數據)');
grid on;



5. 運行結果

預測2010和2011年的公路客運量分別爲(單位:萬人):

ans =

1.0e+04 *

4.4384 4.4656

預測2010和2011年的公路貨運量分別爲(單位:萬噸):

ans =

1.0e+04 *

2.1042 2.1139



6. 繪製的圖像

  1. figure(1)
    11

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