參考學(xué)習(xí)b站資源:
數(shù)學(xué)建模學(xué)習(xí)交流
bp神經(jīng)網(wǎng)絡(luò)預(yù)測matlab代碼實現(xiàn)過程
神經(jīng)網(wǎng)絡(luò)簡介
1.項目源碼
可在github下載(含原始樣品數(shù)據(jù)):
https://github.com/chenshunpeng/BP-neural-network
2.神經(jīng)網(wǎng)絡(luò)介紹
最早的神經(jīng)網(wǎng)絡(luò)模型, 單層感知器perceptron,結(jié)構(gòu)如下:
這是一個兩層的神經(jīng)網(wǎng)絡(luò),第一層為輸入層,第二層為輸出層。因為只有在輸出層需要進(jìn)行計算,就是說只有一層計算層,所以稱之為單層感知器。從形式上看,僅僅是將MP模型中的輸入信號當(dāng)作了獨立的一層神經(jīng)元,但是本質(zhì)上卻有很大差別。
感知器模型中權(quán)重和閾值不再是固定的了,而是計算機"學(xué)習(xí)"出來的結(jié)果。引入了損失函數(shù)的概念,通過迭代不斷調(diào)整權(quán)重和閾值,使得損失函數(shù)最小,以此來尋找最佳的權(quán)重和閾值。
單層感知器只可以解決線性可分的問題,在單層感知器的基礎(chǔ)上,再引入一層神經(jīng)元,構(gòu)成一個2層的神經(jīng)網(wǎng)絡(luò)(要刨去輸入層),結(jié)構(gòu)如下:
這樣的一個神經(jīng)網(wǎng)絡(luò)模型,適用范圍更廣,涵蓋了線性和非線性可分的場景。其中的每一層稱之為layer, 除了輸出層和輸出層之外,還有中間的隱藏層。這樣的神經(jīng)網(wǎng)絡(luò)模型,通過反向傳播算法來求解。
增加一層的好處在于更好的數(shù)據(jù)表示和函數(shù)擬合的能力,在3層的基礎(chǔ)上,再引入更多的隱藏層,就變成了深度神經(jīng)網(wǎng)絡(luò),圖示如下:
可以看到,每增加一層,模型的參數(shù)數(shù)量急劇增加,所以深度學(xué)習(xí)對計算資源的要求特別高,在實際使用中,模型訓(xùn)練時間非常的久。
雖然耗費計算資源,但是深度學(xué)習(xí)的優(yōu)點也很突出,相比機器學(xué)習(xí),模型自動完成特征提取,不需要人工的特征工程,這一點對于高維數(shù)據(jù)的處理特別重要
3.辛烷值的預(yù)測
【改編】辛烷值是汽油最重要的品質(zhì)指標(biāo),傳統(tǒng)的實驗室檢測方法存在樣品用量大,測試周期長和費用高等問題,不適用于生產(chǎn)控制,特別是在線測試。近年發(fā)展起來的近紅外光譜分析方法(NIR),作為一種快速分析方法,已廣泛應(yīng)用于農(nóng)業(yè)、制藥、生物化工、石油產(chǎn)品等領(lǐng)域。其優(yōu)越性是無損檢測、低成本、無污染,能在線分析,更適合于生產(chǎn)和控制的需要。
實驗采集得到50組汽油樣品(辛烷值已通過其他方法測量),并利用傅里葉近紅外變換光譜儀對其進(jìn)行掃描,掃描范圍900~1700nm,掃描間隔為2nm,即每個樣品的光譜曲線共含401個波長點,每個波長點對應(yīng)一個吸光度。
- 請利用這50組樣品的數(shù)據(jù),建立這401個吸光度和辛烷值之間的模型。
- 現(xiàn)給你10組新的樣本,這10組樣本均已經(jīng)過近紅外變換光譜儀掃描,請預(yù)測這10組新樣本的辛烷值。
Excel截圖:
3.1.原始樣品數(shù)據(jù)
因為數(shù)據(jù)太多,博客只放了一部分,完整Excel可以在github項目中下載:
https://github.com/chenshunpeng/BP-neural-network
首先導(dǎo)入數(shù)據(jù):
new_X:需要預(yù)測的輸入層數(shù)據(jù)
X:樣品的輸入層數(shù)據(jù)
Y:樣品的輸出層數(shù)據(jù)
3.2.matlab代碼實現(xiàn)
%% 此程序為matlab編程實現(xiàn)的BP神經(jīng)網(wǎng)絡(luò)
% 清空環(huán)境變量
% clear
close all %關(guān)閉所有圖形窗口
clc
%%第一步 讀取數(shù)據(jù)
input=X; %載入輸入數(shù)據(jù)
output=Y; %載入輸出數(shù)據(jù)
%% 第二步 設(shè)置訓(xùn)練數(shù)據(jù)和預(yù)測數(shù)據(jù)
% 注意要將指標(biāo)變?yōu)榱邢蛄?input_train = input(1:40,:)';
output_train =output(1:40,:)';
input_test = input(41:50,:)';
output_test =output(41:50,:)';
%節(jié)點個數(shù)
inputnum=401; % 輸入層節(jié)點數(shù)量
hiddennum=10; % 隱含層節(jié)點數(shù)量
outputnum=1; % 輸出層節(jié)點數(shù)量
%% 第三本 訓(xùn)練樣本數(shù)據(jù)歸一化
[inputn,inputps]=mapminmax(input_train);%歸一化到[-1,1]之間,inputps用來作下一次同樣的歸一化
[outputn,outputps]=mapminmax(output_train);
%% 第四步 構(gòu)建BP神經(jīng)網(wǎng)絡(luò)
net=newff(inputn,outputn,hiddennum,{'tansig','purelin'},'trainlm');% 建立模型,傳遞函數(shù)使用purelin,采用梯度下降法訓(xùn)練
W1= net. iw{1, 1}; %輸入層到中間層的權(quán)值
B1 = net.b{1}; %中間各層神經(jīng)元閾值
W2 = net.lw{2,1}; %中間層到輸出層的權(quán)值
B2 = net. b{2}; %輸出層各神經(jīng)元閾值
%% 第五步 網(wǎng)絡(luò)參數(shù)配置( 訓(xùn)練次數(shù),學(xué)習(xí)速率,訓(xùn)練目標(biāo)最小誤差等)
net.trainParam.epochs=1000; % 訓(xùn)練次數(shù),這里設(shè)置為1000次
net.trainParam.lr=0.01; % 學(xué)習(xí)速率,這里設(shè)置為0.01
net.trainParam.goal=0.00001; % 訓(xùn)練目標(biāo)最小誤差,這里設(shè)置為0.00001
%% 第六步 BP神經(jīng)網(wǎng)絡(luò)訓(xùn)練
net=train(net,inputn,outputn);%開始訓(xùn)練,其中inputn,outputn分別為輸入輸出樣本
%% 第七步 測試樣本歸一化
inputn_test=mapminmax('apply',input_test,inputps); % 對樣本數(shù)據(jù)進(jìn)行歸一化
%% 第八步 BP神經(jīng)網(wǎng)絡(luò)預(yù)測
an=sim(net,inputn_test); %用訓(xùn)練好的模型進(jìn)行仿真
%% 第九步 預(yù)測結(jié)果反歸一化與誤差計算
test_simu=mapminmax('reverse',an,outputps); %把仿真得到的數(shù)據(jù)還原為原始的數(shù)量級
error=test_simu-output_test; %預(yù)測值和真實值的誤差
%%第十步 真實值與預(yù)測值誤差比較
figure('units','normalized','position',[0.119 0.2 0.38 0.5])
plot(output_test,'bo-')
hold on
plot(test_simu,'r*-')
hold on
plot(error,'square','MarkerFaceColor','b')
legend('期望值','預(yù)測值','誤差')
xlabel('數(shù)據(jù)組數(shù)')
ylabel('樣本值')
title('BP神經(jīng)網(wǎng)絡(luò)測試集的預(yù)測值與實際值對比圖')
[c,l]=size(output_test);
MAE1=sum(abs(error))/l;
MSE1=error*error'/l;
RMSE1=MSE1^(1/2);
disp(['-----------------------誤差計算--------------------------'])
disp(['隱含層節(jié)點數(shù)為',num2str(hiddennum),'時的誤差結(jié)果如下:'])
disp(['平均絕對誤差MAE為:',num2str(MAE1)])
disp(['均方誤差MSE為: ',num2str(MSE1)])
disp(['均方根誤差RMSE為: ',num2str(RMSE1)])
關(guān)于隱含層數(shù)的確定(這里是10),需要注意的是:
- 如果不用公式的話,可以逐步試驗得到隱層節(jié)點數(shù),就是先設(shè)置一個初始值,然后在這個值的基礎(chǔ)上逐漸增加,比較每次網(wǎng)絡(luò)的預(yù)測性能,選擇性能最好的對應(yīng)的節(jié)點數(shù)作為隱含層神經(jīng)元節(jié)點數(shù)(逐步增加是因為確定隱含層節(jié)點數(shù)的基本原則是:在滿足精度的前提下,取盡可能緊湊的結(jié)構(gòu),即取盡可能少的隱含層節(jié)點數(shù))
- 如果用公式的話,一般有幾個經(jīng)驗公式(建議了解一下神經(jīng)網(wǎng)絡(luò)的數(shù)學(xué)/理論部分),帶入看哪個效果好,就取哪個為基準(zhǔn),再結(jié)合逐步試驗法確定隱層節(jié)點數(shù),但因為權(quán)值和閾值是每訓(xùn)練一次,調(diào)整一次,所以只能盡量趨于最優(yōu)(好像也可以通過遺傳算法、粒子群算法這樣的優(yōu)化算法來確定,就比較高深了)
訓(xùn)練結(jié)果:
-----------------------誤差計算--------------------------
隱含層節(jié)點數(shù)為10時的誤差結(jié)果如下:
平均絕對誤差MAE為:0.30444
均方誤差MSE為: 0.14714
均方根誤差RMSE為: 0.38359
進(jìn)行預(yù)測:
predict_y = zeros(10,1); % 初始化predict_y
pre_test=mapminmax('apply',new_X(:,:)',inputps);% 對預(yù)測數(shù)據(jù)進(jìn)行歸一化
for i = 1: 10
result = sim(net, pre_test(:,i));
predict_y(i) = result;
end
disp('預(yù)測值為:')
predict_y=mapminmax('reverse',predict_y,outputps); %把預(yù)測結(jié)果還原
disp(predict_y)
結(jié)果:
預(yù)測值為:
87.9633
87.8581
88.8067
85.4666
85.3155
83.1005
86.3266
86.7106
89.1940
87.0632
需要注意的是,不同的神經(jīng)網(wǎng)絡(luò)模型參數(shù)會對預(yù)測值有影響,比如隱含層的個數(shù)(默認(rèn)為10),測試集比例,訓(xùn)練方法等,另一方面,樣本數(shù)量的局限或是模型的質(zhì)量也都有可能對結(jié)果有很大的影響
3.3.工具箱實現(xiàn)
3.3.1.萊文貝格-馬夸特方法
在Matlab的菜單欄點擊APP,再點擊Neural Fitting app(神經(jīng)網(wǎng)絡(luò)工具箱):
注意到左下角有一個模塊:
點擊后出現(xiàn):
我們可以在這里看到對它的介紹:
可以簡單了解一下:
之后接著進(jìn)行操作:
注意選擇樣本在行上面(Matrix rows),也就是說每一行對應(yīng)一個樣本的所有數(shù)據(jù)
之后出現(xiàn):
解釋:
訓(xùn)練集(Training set) —— 用于模型擬合的數(shù)據(jù)樣本。
驗證集(Validation set)—— 是模型訓(xùn)練過程中單獨留出的樣本集,它可以用于調(diào)整模型的超參數(shù)和用于對模型的能力進(jìn)行初步評估。在神經(jīng)網(wǎng)絡(luò)中,我們用驗證數(shù)據(jù)集去尋找最優(yōu)的網(wǎng)絡(luò)深度,或者決定反向傳播算法的停止點或者在神經(jīng)網(wǎng)絡(luò)中選擇隱藏層神經(jīng)元的數(shù)量;
測試集(Testing set) —— 用來評估模最終模型的泛化能力。但不能作為調(diào)參、選擇特征等算法相關(guān)的選擇的依據(jù)。
之后默認(rèn)選擇隱含層的個數(shù)為10(就是說有10個神經(jīng)元進(jìn)行預(yù)測,即output部分有10個):
之后選擇訓(xùn)練方法:
解釋:
三種訓(xùn)練方法:
萊文貝格-馬夸特方法(Levenberg–Marquardt algorithm)
貝葉斯正則化方法(Bayesian‐regularization)
量化共軛梯度法(Scaled Conjugate Gradient )
選擇合適的進(jìn)行訓(xùn)練即可
訓(xùn)練結(jié)果:
在時刻9(訓(xùn)練了9次)驗證集valiadation出現(xiàn)了最低的均方誤差,選擇時刻9的模型為最佳模型:
橫坐標(biāo):訓(xùn)練結(jié)束時的epochs數(shù)(神經(jīng)網(wǎng)絡(luò)一次前向傳播+一次反向傳播=一個epoch)
縱坐標(biāo):均方誤差
這三條線分別是:訓(xùn)練集(train)、驗證集(validation)和測試集(test)
訓(xùn)練集(藍(lán)線所用數(shù)據(jù)集):訓(xùn)練模型,得到模型參數(shù)
驗證集(綠線所用數(shù)據(jù)集):評估模型,得到的最優(yōu)網(wǎng)絡(luò)
測試集(紅線所用數(shù)據(jù)集):用之前得到的最優(yōu)網(wǎng)絡(luò)來評估模最終模型的泛化能力
解釋一下為什么最佳模型的標(biāo)注在綠線上:
首先使用訓(xùn)練集訓(xùn)練多個網(wǎng)絡(luò)模型(假設(shè)為t1,t2,t3 … tn),再使用驗證集測試這些網(wǎng)絡(luò),找到得分最高的那個網(wǎng)絡(luò)(假設(shè)為t9)作為我們選擇的最佳網(wǎng)絡(luò),所以最佳模型的標(biāo)注在綠線上,紅線則是網(wǎng)絡(luò)模型將訓(xùn)練集和驗證集合并訓(xùn)練而產(chǎn)生的(其實,綠線類似Kaggle中的Private Testing Set)
將擬合值對真實值回歸,擬合優(yōu)度越高,說明擬合的的效果越好:
對應(yīng)的神經(jīng)網(wǎng)絡(luò)圖:
最后保存訓(xùn)練出來的神經(jīng)網(wǎng)絡(luò)模型:
其中 net 即訓(xùn)練出來的神經(jīng)網(wǎng)絡(luò)模型
進(jìn)行預(yù)測:
% 寫一個循環(huán),預(yù)測接下來的十個樣本的辛烷值
% 注意要將指標(biāo)變?yōu)榱邢蛄?,然后再用sim函數(shù)預(yù)測
predict_y = zeros(10,1); % 初始化predict_y
for i = 1: 10
result = sim(net, new_X(i,:)');
predict_y(i) = result;
end
disp('預(yù)測值為:')
disp(predict_y)
結(jié)果:
預(yù)測值為:
87.3547
87.1239
88.1194
84.9958
84.5796
85.4275
87.8986
86.4921
89.0483
87.4444
3.3.2.貝葉斯正則化方法
之后我們換一種訓(xùn)練方法(從 萊文貝格-馬夸特方法 換到 貝葉斯正則化方法),發(fā)現(xiàn)訓(xùn)練了391次還沒有結(jié)束,于是我就手動停止了(訓(xùn)練了長達(dá)19min):
我們點擊 (trainbr) 可以看到對貝葉斯正則化方法的詳細(xì)介紹,及其局限性:
該函數(shù)使用雅可比矩陣進(jìn)行計算,該函數(shù)假設(shè)性能是誤差的平均值或平方和。
因此,使用該函數(shù)訓(xùn)練的網(wǎng)絡(luò)必須使用mse或sse性能函數(shù)。
我們看訓(xùn)練的表現(xiàn):
訓(xùn)練的MSE圖(左圖),回歸圖(右圖):
MSE圖(左圖)
橫坐標(biāo): 訓(xùn)練結(jié)束時的epochs數(shù)【神經(jīng)網(wǎng)絡(luò)一次前向傳播+一次反向傳播=一個epoch】
縱坐標(biāo): 均方誤差
從圖中可以發(fā)現(xiàn)訓(xùn)練集最小均方誤差一直在變小,測試集略微輕微增大,趨于穩(wěn)定(但誤差其實都已經(jīng)非常非常小了)
回歸圖(右圖)
橫坐標(biāo): 樣本原目標(biāo)值
縱坐標(biāo): 神經(jīng)網(wǎng)絡(luò)輸出預(yù)測值
可以得到原目標(biāo)值和預(yù)測值的相關(guān)度;用系數(shù)R表示,若R越接近1,則表示線性化程度越高,結(jié)果越好
我們驚奇的發(fā)現(xiàn)沒有validation
,訓(xùn)檢查了一下訓(xùn)練集(train)、驗證集(validation)和測試集(test)在matlab工具箱中分別是70%,15%,15%的比例,沒有問題,仔細(xì)看了一下原來是因為均方誤差MSE和R指標(biāo)在精度范圍內(nèi)已經(jīng)為0,所以都不需要考慮它了!
訓(xùn)練的狀態(tài)圖(左圖),誤差直方圖(右圖):
狀態(tài)圖(左圖)
可以觀察網(wǎng)絡(luò)訓(xùn)練狀態(tài),判斷是否終止訓(xùn)練
橫坐標(biāo): epoch
縱坐標(biāo):
gradient:梯度,若梯度為0,則為圖像最低點,即最優(yōu)位置
mu:超參數(shù)
μ
\mu
μ(具體待研究)
val fail:可以理解為誤差值(具體待研究)
validation check=0, at epoch 391
:代表到第391次訓(xùn)練時,訓(xùn)練誤差的 連續(xù)增大epoch數(shù) 為0(其實就是第390次訓(xùn)練時訓(xùn)練誤差比第391次大),設(shè)置 validation checks
是為了防止被訓(xùn)練的網(wǎng)絡(luò)過擬合的
狀態(tài)圖的詳細(xì)介紹可看幫助文檔:
誤差直方圖(右圖)
可以得到神經(jīng)網(wǎng)絡(luò)的輸出值與樣本原目標(biāo)值的誤差
橫坐標(biāo): 誤差區(qū)間的中位數(shù);
縱坐標(biāo): 位于該誤差區(qū)間的樣本個數(shù)
之后可以通過這2個看訓(xùn)練的matlab代碼:
可以在這里體驗神經(jīng)網(wǎng)絡(luò)的模擬部署:
大概是這樣(具體功能可以自己了解)
可以看到神經(jīng)網(wǎng)絡(luò)圖:
如下:
我們可以生成腳本,方便以后解決相同的問題:
代碼:
% Solve an Input-Output Fitting problem with a Neural Network
% Script generated by Neural Fitting app
% Created 23-Jul-2022 19:10:11
%
% This script assumes these variables are defined:
%
% X - input data.
% Y - target data.
x = X';
t = Y';
% Choose a Training Function
% For a list of all training functions type: help nntrain
% 'trainlm' is usually fastest.
% 'trainbr' takes longer but may be better for challenging problems.
% 'trainscg' uses less memory. Suitable in low memory situations.
trainFcn = 'trainbr'; % Bayesian Regularization backpropagation.
% Create a Fitting Network
hiddenLayerSize = 10;
net = fitnet(hiddenLayerSize,trainFcn);
% Choose Input and Output Pre/Post-Processing Functions
% For a list of all processing functions type: help nnprocess
net.input.processFcns = {'removeconstantrows','mapminmax'};
net.output.processFcns = {'removeconstantrows','mapminmax'};
% Setup Division of Data for Training, Validation, Testing
% For a list of all data division functions type: help nndivision
net.divideFcn = 'dividerand'; % Divide data randomly
net.divideMode = 'sample'; % Divide up every sample
net.divideParam.trainRatio = 70/100;
net.divideParam.valRatio = 15/100;
net.divideParam.testRatio = 15/100;
% Choose a Performance Function
% For a list of all performance functions type: help nnperformance
net.performFcn = 'mse'; % Mean Squared Error
% Choose Plot Functions
% For a list of all plot functions type: help nnplot
net.plotFcns = {'plotperform','plottrainstate','ploterrhist', ...
'plotregression', 'plotfit'};
% Train the Network
[net,tr] = train(net,x,t);
% Test the Network
y = net(x);
e = gsubtract(t,y);
performance = perform(net,t,y)
% Recalculate Training, Validation and Test Performance
trainTargets = t .* tr.trainMask{1};
valTargets = t .* tr.valMask{1};
testTargets = t .* tr.testMask{1};
trainPerformance = perform(net,trainTargets,y)
valPerformance = perform(net,valTargets,y)
testPerformance = perform(net,testTargets,y)
% View the Network
view(net)
% Plots
% Uncomment these lines to enable various plots.
%figure, plotperform(tr)
%figure, plottrainstate(tr)
%figure, ploterrhist(e)
%figure, plotregression(t,y)
%figure, plotfit(net,x,t)
% Deployment
% Change the (false) values to (true) to enable the following code blocks.
% See the help for each generation function for more information.
if (false)
% Generate MATLAB function for neural network for application
% deployment in MATLAB scripts or with MATLAB Compiler and Builder
% tools, or simply to examine the calculations your trained neural
% network performs.
genFunction(net,'myNeuralNetworkFunction');
y = myNeuralNetworkFunction(x);
end
if (false)
% Generate a matrix-only MATLAB function for neural network code
% generation with MATLAB Coder tools.
genFunction(net,'myNeuralNetworkFunction','MatrixOnly','yes');
y = myNeuralNetworkFunction(x);
end
if (false)
% Generate a Simulink diagram for simulation or deployment with.
% Simulink Coder tools.
gensim(net);
end
之后保存數(shù)據(jù):
進(jìn)行預(yù)測:
% 寫一個循環(huán),預(yù)測接下來的十個樣本的辛烷值
% 注意要將指標(biāo)變?yōu)榱邢蛄浚缓笤儆胹im函數(shù)預(yù)測
predict_y = zeros(10,1); % 初始化predict_y
for i = 1: 10
result = sim(net, new_X(i,:)');
predict_y(i) = result;
end
disp('預(yù)測值為:')
disp(predict_y)
結(jié)果:
預(yù)測值為:
87.1550
86.8867
87.9137
84.8865
85.3341
84.0724
86.5032
86.1383
88.8628
86.9989
4.辛烷值的預(yù)測(進(jìn)階版,預(yù)測辛烷值區(qū)間)
因為有人進(jìn)行了提問:bp神經(jīng)網(wǎng)絡(luò)預(yù)測的問題,討論區(qū)也有類似的問題,所以對辛烷值的預(yù)測進(jìn)行了深入的討論
上一個是預(yù)測一個辛烷值,這次我們將上一次的辛烷值做一個運算,生成一個辛烷值區(qū)間(其實就是想生成個一個區(qū)間的兩個端點),自定義公式:
[
α
,
β
]
=
[
x
?
∣
x
r
a
n
d
i
(
[
9
,
11
]
)
∣
,
x
+
∣
x
r
a
n
d
i
(
[
11
,
13
]
)
∣
]
\left[ \alpha ,\beta \right] =\left[ x-\left| \dfrac{x}{randi([9,11])}\right| ,x+\left| \dfrac{x}{randi([11,13])}\right| \right]
[α,β]=[x?∣
∣?randi([9,11])x?∣
∣?,x+∣
∣?randi([11,13])x?∣
∣?]
我們生成 [ α , β ] \left[ \alpha ,\beta \right] [α,β]:
%init(1)是初始辛烷值,init(2)是α,init(3)是β
for i = 1: 50
init(i,2) = init(1)-init(1)/randi([9,11]);
init(i,3) = init(1)+init(1)/randi([11,13]);
end
數(shù)據(jù)如下(均保存2位小數(shù)):
辛烷值 α β
85.3 76.77 92.41
85.25 77.55 92.41
88.45 76.77 91.86
83.4 77.55 92.41
87.9 76.77 92.41
85.5 75.82 93.05
88.9 76.77 93.05
88.3 77.55 93.05
88.7 75.82 93.05
88.45 75.82 92.41
88.75 75.82 91.86
88.25 76.77 93.05
87.3 77.55 91.86
88 76.77 93.05
88.7 75.82 92.41
85.5 76.77 93.05
88.65 76.77 91.86
88.75 75.82 93.05
85.4 75.82 93.05
88.6 76.77 92.41
87 75.82 93.05
87.15 77.55 93.05
87.05 77.55 91.86
87.25 76.77 92.41
86.85 75.82 92.41
88.65 77.55 92.41
86.6 76.77 93.05
86 76.77 92.41
86.1 77.55 92.41
86.5 76.77 91.86
86.3 75.82 91.86
84.4 77.55 91.86
84.7 75.82 93.05
84.6 76.77 91.86
84.5 75.82 91.86
88.1 75.82 92.41
85.25 76.77 91.86
88.4 77.55 91.86
88.2 77.55 92.41
88.4 77.55 93.05
88.55 75.82 91.86
88.35 76.77 92.41
88.2 77.55 92.41
85.3 76.77 91.86
88.5 77.55 92.41
88.25 75.82 93.05
88 77.55 93.05
88.85 76.77 93.05
88.45 77.55 91.86
88.7 76.77 92.41
現(xiàn)在我們開始愉快的預(yù)測:
首先導(dǎo)入數(shù)據(jù):
new_X:需要預(yù)測的輸入層數(shù)據(jù)
X:樣品的輸入層數(shù)據(jù)
Y:樣品的輸出層數(shù)據(jù)
其實就是把Y多增加1列:
4.1.matlab代碼實現(xiàn)
%% 此程序為matlab編程實現(xiàn)的BP神經(jīng)網(wǎng)絡(luò)
% 清空環(huán)境變量
% clear
close all %關(guān)閉所有圖形窗口
clc
%%第一步 讀取數(shù)據(jù)
input=X; %載入輸入數(shù)據(jù)
output=Y; %載入輸出數(shù)據(jù)
%% 第二步 設(shè)置訓(xùn)練數(shù)據(jù)和預(yù)測數(shù)據(jù)
% 注意要將指標(biāo)變?yōu)榱邢蛄?input_train = input(1:40,:)';
output_train =output(1:40,:)';
input_test = input(41:50,:)';
output_test =output(41:50,:)';
%節(jié)點個數(shù)
inputnum=401; % 輸入層節(jié)點數(shù)量
hiddennum=10; % 隱含層節(jié)點數(shù)量
outputnum=2; % 輸出層節(jié)點數(shù)量
%% 第三本 訓(xùn)練樣本數(shù)據(jù)歸一化
[inputn,inputps]=mapminmax(input_train);%歸一化到[-1,1]之間,inputps用來作下一次同樣的歸一化
[outputn,outputps]=mapminmax(output_train);
%% 第四步 構(gòu)建BP神經(jīng)網(wǎng)絡(luò)
net=newff(inputn,outputn,hiddennum,{'tansig','purelin'},'trainlm');% 建立模型,傳遞函數(shù)使用purelin,采用梯度下降法訓(xùn)練
W1= net. iw{1, 1}; %輸入層到中間層的權(quán)值
B1 = net.b{1}; %中間各層神經(jīng)元閾值
W2 = net.lw{2,1}; %中間層到輸出層的權(quán)值
B2 = net. b{2}; %輸出層各神經(jīng)元閾值
%% 第五步 網(wǎng)絡(luò)參數(shù)配置( 訓(xùn)練次數(shù),學(xué)習(xí)速率,訓(xùn)練目標(biāo)最小誤差等)
net.trainParam.epochs=1000; % 訓(xùn)練次數(shù),這里設(shè)置為1000次
net.trainParam.lr=0.01; % 學(xué)習(xí)速率,這里設(shè)置為0.01
net.trainParam.goal=0.00001; % 訓(xùn)練目標(biāo)最小誤差,這里設(shè)置為0.00001
%% 第六步 BP神經(jīng)網(wǎng)絡(luò)訓(xùn)練
net=train(net,inputn,outputn);%開始訓(xùn)練,其中inputn,outputn分別為輸入輸出樣本
%% 第七步 測試樣本歸一化
inputn_test=mapminmax('apply',input_test,inputps); % 對樣本數(shù)據(jù)進(jìn)行歸一化
%% 第八步 BP神經(jīng)網(wǎng)絡(luò)預(yù)測
an=sim(net,inputn_test); %用訓(xùn)練好的模型進(jìn)行仿真
%% 第九步 預(yù)測結(jié)果反歸一化與誤差計算
test_simu=mapminmax('reverse',an,outputps); %把仿真得到的數(shù)據(jù)還原為原始的數(shù)量級
error=test_simu-output_test; %預(yù)測值和真實值的誤差
%%第十步 真實值與預(yù)測值誤差比較
figure('units','normalized','position',[0.119 0.2 0.38 0.5])
plot(output_test,'bo-')
hold on
plot(test_simu,'r*-')
hold on
plot(error,'square','MarkerFaceColor','b')
legend('期望值','預(yù)測值','誤差')
xlabel('數(shù)據(jù)組數(shù)')
ylabel('樣本值')
title('BP神經(jīng)網(wǎng)絡(luò)測試集的預(yù)測值與實際值對比圖')
[c,l]=size(output_test);
MAE1=sum(abs(error))/l;
MSE1=error*error'/l;
RMSE1=MSE1^(1/2);
disp(['-----------------------誤差計算--------------------------'])
disp(['隱含層節(jié)點數(shù)為',num2str(hiddennum),'時的誤差結(jié)果如下:'])
disp(['平均絕對誤差MAE為:',num2str(MAE1)])
disp(['α的均方誤差MSE為: ',num2str(MSE1(1,:))])
disp(['β的均方誤差MSE為: ',num2str(MSE1(2,:))])
disp(['α的均方根誤差RMSE為: ',num2str(RMSE1(1,:))])
disp(['β的均方根誤差RMSE為: ',num2str(RMSE1(2,:))])
之后開始訓(xùn)練:
訓(xùn)練結(jié)果為:
訓(xùn)練中間階段:
回歸結(jié)果(數(shù)據(jù)雖然是瞎生成的,但結(jié)果好像還不錯呢 ):
輸出結(jié)果(圖像有些小問題,應(yīng)該是多條曲線的對比,有空會將它優(yōu)化的QAQ ,但是整體思路都沒問題):
-----------------------誤差計算--------------------------
隱含層節(jié)點數(shù)為10時的誤差結(jié)果如下:
平均絕對誤差MAE為:0.28223 0.28882 0.16351 0.17373 0.078239 0.15954 0.045716 0.11022 0.16083 0.16366
α的均方誤差MSE為: 1.8212 -0.021202
β的均方誤差MSE為: -0.021202 0.42378
α的均方根誤差RMSE為: 1.3495 -0.010599
β的均方根誤差RMSE為: -0.010599 0.6509
進(jìn)行預(yù)測,竟然報錯了:
錯誤代碼(就當(dāng)教訓(xùn)了):
clc;
predict_y = zeros(10,2); % 初始化predict_y
pre_test=mapminmax('apply',new_X(:,:)',inputps);% 對預(yù)測數(shù)據(jù)進(jìn)行歸一化
for i = 1: 10
result = sim(net, pre_test(:,i));
predict_y(i,1) = result(1);
predict_y(i,2) = result(2);
end
disp('預(yù)測值為:')
predict_y=mapminmax('reverse',predict_y,outputps); %把預(yù)測結(jié)果還原
disp(predict_y)
我們查看predict_y,沒問題:
那么就是mapminmax
函數(shù)的問題,修改如下:
clc;
predict_y = zeros(10,2); % 初始化predict_y
pre_test=mapminmax('apply',new_X(:,:)',inputps);% 對預(yù)測數(shù)據(jù)進(jìn)行歸一化
for i = 1: 10
result = sim(net, pre_test(:,i));
predict_y(i,1) = result(1);
predict_y(i,2) = result(2);
end
disp('預(yù)測值為:')
predict_y=predict_y';
predict_y=mapminmax('reverse',predict_y,outputps); %把預(yù)測結(jié)果還原
disp(predict_y)
結(jié)果:
預(yù)測值為:
77.9596 80.1580 78.4421 77.6802 79.4339 79.4779 77.8803 79.3454 78.7957 77.8469
92.1225 91.6629 93.0518 92.4459 92.6326 92.3652 93.6457 93.1900 93.0095 93.6050
看一下predict_y,也沒問題:
我們再轉(zhuǎn)置回來得到正確結(jié)果:
那么為啥要這么修改呢,我們細(xì)細(xì)品(#^.^#) ,這要回到神經(jīng)網(wǎng)絡(luò)構(gòu)建的時候了:
這兩部分要對應(yīng)上哇,哈哈,完結(jié)撒花
4.2.工具箱實現(xiàn)
類比之前實現(xiàn)的方法,其實是不難實現(xiàn)的,讀者可以自行完成文章來源:http://www.zghlxwxcb.cn/news/detail-516964.html
目前課業(yè)壓力較大,這段時間大概率會忽略博客評論,敬請諒解文章來源地址http://www.zghlxwxcb.cn/news/detail-516964.html
到了這里,關(guān)于BP神經(jīng)網(wǎng)絡(luò)預(yù)測實例(matlab代碼,神經(jīng)網(wǎng)絡(luò)工具箱)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!