🔗?運行環境:Matlab
🚩?撰寫作者:左手の明天
🥇?精選專欄:《python》
🔥??推薦專欄:《算法研究》
🔐####?防偽水印——左手の明天?####🔐
💗 大家好🤗🤗🤗,我是左手の明天!好久不見💗
💗今天分享Matlab深度學習?——?時間序列預測💗
📆? 最近更新:2024 年 03 月 03日,左手の明天的第?316?篇原創博客
📚?更新于專欄:機器學習
🔐####?防偽水印——左手の明天?####🔐
一、LSTM 網絡
LSTM 網絡是一種循環神經網絡 (RNN),它通過遍歷時間步并更新 RNN 狀態來處理輸入數據。RNN 狀態包含在所有先前時間步中記住的信息。可以使用 LSTM 神經網絡,通過將先前的時間步作為輸入來預測時間序列或序列的后續值。要為時間序列預測訓練 LSTM 神經網絡,訓練具有序列輸出的回歸 LSTM 神經網絡,其中響應(目標)是將值移位了一個時間步的訓練序列。也就是說,在輸入序列的每個時間步,LSTM 神經網絡都學習預測下一個時間步的值。
有兩種預測方法:開環預測和閉環預測。
-
開環預測僅使用輸入數據預測序列中的下一個時間步。對后續時間步進行預測時,需要從數據源中收集真實值并將其用作輸入。例如,假設要使用時間步 1 到?t?1?中收集的數據來預測序列的時間步?t?的值。要對時間步?t+1?進行預測,等到記錄下時間步?t?的真實值,并將其用作輸入進行下一次預測。在進行下一次預測之前,如果有可以提供給 RNN 的真實值,則請使用開環預測。
-
閉環預測通過使用先前的預測作為輸入來預測序列中的后續時間步。在這種情況下,模型不需要真實值便可進行預測。例如,假設要僅使用在時間步 1 至?t?1?中收集的數據來預測序列的時間步?t?至?t+k?的值。要對時間步?i?進行預測,使用時間步?i?1?的預測值作為輸入。使用閉環預測來預測多個后續時間步,或在進行下一次預測之前沒有真實值可提供給 RNN 時使用閉環預測。
此圖顯示使用閉環預測的預測值的序列示例。
此示例使用 Waveform 數據集,它包含生成的 2000 個不同長度的合成波形,有三個通道。該示例訓練一個 LSTM 神經網絡,以同時使用閉環和開環預測根據先前時間步提供的值來預測波形的將來值。
二、matlab時間序列預測
2.1 加載數據
從?WaveformData.mat
?加載示例數據。數據是序列的?numObservations
×1 元胞數組,其中?numObservations
?是序列數。每個序列都是一個?numChannels
×-numTimeSteps
?數值數組,其中?numChannels
?是序列的通道數,numTimeSteps
?是序列的時間步數。
load WaveformData
查看前幾個序列的大小。
data(1:5)
ans=5×1 cell array{3×103 double}{3×136 double}{3×140 double}{3×124 double}{3×127 double}
查看通道數。為了訓練 LSTM 神經網絡,每個序列必須具有相同數量的通道。
numChannels = size(data{1},1)
numChannels = 3
可視化繪圖中的前幾個序列。
figure
tiledlayout(2,2)
for i = 1:4nexttilestackedplot(data{i}')xlabel("Time Step")
end
將數據劃分為訓練集和測試集。將 90% 的觀測值用于訓練,其余的用于測試。
numObservations = numel(data);
idxTrain = 1:floor(0.9*numObservations);
idxTest = floor(0.9*numObservations)+1:numObservations;
dataTrain = data(idxTrain);
dataTest = data(idxTest);
2.2 準備要訓練的數據
要預測序列在將來時間步的值,請將目標指定為將值移位了一個時間步的訓練序列。也就是說,在輸入序列的每個時間步,LSTM 神經網絡都學習預測下一個時間步的值。預測變量是沒有最終時間步的訓練序列。
for n = 1:numel(dataTrain)X = dataTrain{n};XTrain{n} = X(:,1:end-1);TTrain{n} = X(:,2:end);
end
為了更好地擬合并防止訓練發散,請將預測變量和目標值歸一化為零均值和單位方差。在進行預測時,還必須使用與訓練數據相同的統計量對測試數據進行歸一化。要輕松計算所有序列的均值和標準差,請在時間維度中串聯這些序列。
muX = mean(cat(2,XTrain{:}),2);
sigmaX = std(cat(2,XTrain{:}),0,2);muT = mean(cat(2,TTrain{:}),2);
sigmaT = std(cat(2,TTrain{:}),0,2);for n = 1:numel(XTrain)XTrain{n} = (XTrain{n} - muX) ./ sigmaX;TTrain{n} = (TTrain{n} - muT) ./ sigmaT;
end
2.3 定義 LSTM 神經網絡架構
創建一個 LSTM 回歸神經網絡。
-
使用輸入大小與輸入數據的通道數匹配的序列輸入層。
-
接下來,使用一個具有 128 個隱藏單元的 LSTM 層。隱藏單元的數量確定該層學習了多少信息。使用更多隱藏單元可以產生更準確的結果,但也更有可能導致訓練數據過擬合。
-
要輸出通道數與輸入數據相同的序列,請包含一個輸出大小與輸入數據通道數匹配的全連接層。
-
最后,包括一個回歸層。
layers = [sequenceInputLayer(numChannels)lstmLayer(128)fullyConnectedLayer(numChannels)regressionLayer];
2.4 指定訓練選項
指定訓練選項。
-
使用 Adam 優化進行訓練。
-
進行 200 輪訓練。對于較大的數據集,您可能不需要像良好擬合那樣進行這么多輪訓練。
-
在每個小批量中,對序列進行左填充,使它們具有相同的長度。左填充可以防止 RNN 預測序列末尾的填充值。
-
每輪訓練都會打亂數據。
-
在繪圖中顯示訓練進度。
-
禁用詳盡輸出。
options = trainingOptions("adam", ...MaxEpochs=200, ...SequencePaddingDirection="left", ...Shuffle="every-epoch", ...Plots="training-progress", ...Verbose=0);
2.5 訓練循環神經網絡
使用?trainNetwork
?函數以指定的訓練選項訓練 LSTM 神經網絡。
net = trainNetwork(XTrain,TTrain,layers,options);
2.6 測試循環神經網絡
使用與訓練數據相同的步驟準備用于預測的測試數據。
使用從訓練數據計算出的統計量來歸一化測試數據。將目標指定為值移位了一個時間步的測試序列,將預測變量值指定為沒有最終時間步的測試序列。
for n = 1:size(dataTest,1)X = dataTest{n};XTest{n} = (X(:,1:end-1) - muX) ./ sigmaX;TTest{n} = (X(:,2:end) - muT) ./ sigmaT;
end
使用測試數據進行預測。指定與訓練相同的填充選項。
YTest = predict(net,XTest,SequencePaddingDirection="left");
為了計算準確度,對于每個測試序列,請計算預測和目標之間的均方根誤差 (RMSE)。
for i = 1:size(YTest,1)rmse(i) = sqrt(mean((YTest{i} - TTest{i}).^2,"all"));
end
在直方圖中可視化誤差。值越低,表示準確度越高。
figure
histogram(rmse)
xlabel("RMSE")
ylabel("Frequency")
計算所有測試觀測值的 RMSE 均值。
mean(rmse)
ans = single0.5080
2.7 預測將來時間步
給定輸入時間序列或序列,要預測多個將來時間步的值,請使用?predictAndUpdateState
?函數一次預測一個時間步,并在每次預測時更新 RNN 狀態。對于每次預測,使用前一次預測作為函數的輸入。
在繪圖中可視化其中一個測試序列。
idx = 2;
X = XTest{idx};
T = TTest{idx};figure
stackedplot(X',DisplayLabels="Channel " + (1:numChannels))
xlabel("Time Step")
title("Test Observation " + idx)
開環預測
開環預測僅使用輸入數據預測序列中的下一個時間步。對后續時間步進行預測時,需要從數據源中收集真實值并將其用作輸入。例如,假設您要使用時間步 1 到?t?1?中收集的數據來預測序列的時間步?t?的值。要對時間步?t+1?進行預測,請等到記錄下時間步?t?的真實值,并將其用作輸入進行下一次預測。在進行下一次預測之前,如果有可以提供給 RNN 的真實值,則請使用開環預測。
首先使用?resetState
?函數重置狀態來初始化 RNN 狀態,然后使用輸入數據的前幾個時間步進行初始預測。使用輸入數據的前 75 個時間步更新 RNN 狀態。
net = resetState(net);
offset = 75;
[net,~] = predictAndUpdateState(net,X(:,1:offset));
要進行進一步的預測,請遍歷時間步并使用?predictAndUpdateState
?函數更新 RNN 狀態。通過遍歷輸入數據的時間步并將其用作 RNN 的輸入,預測測試觀測值的其余時間步的值。第一個預測是對應于時間步?offset + 1
?的值。
numTimeSteps = size(X,2);
numPredictionTimeSteps = numTimeSteps - offset;
Y = zeros(numChannels,numPredictionTimeSteps);for t = 1:numPredictionTimeStepsXt = X(:,offset+t);[net,Y(:,t)] = predictAndUpdateState(net,Xt);
end
將預測值與目標值進行比較。
figure
t = tiledlayout(numChannels,1);
title(t,"Open Loop Forecasting")for i = 1:numChannelsnexttileplot(T(i,:))hold onplot(offset:numTimeSteps,[T(i,offset) Y(i,:)],'--')ylabel("Channel " + i)
endxlabel("Time Step")
nexttile(1)
legend(["Input" "Forecasted"])
閉環預測
閉環預測通過使用先前的預測作為輸入來預測序列中的后續時間步。在這種情況下,模型不需要真實值便可進行預測。例如,假設您要僅使用在時間步 1 至?t?1?中收集的數據來預測序列的時間步?t?至?t+k?的值。要對時間步?i?進行預測,請使用時間步?i?1?的預測值作為輸入。使用閉環預測來預測多個后續時間步,或在進行下一次預測之前沒有真實值可提供給 RNN 時使用閉環預測。
首先使用?resetState
?函數重置狀態來初始化 RNN 狀態,然后使用輸入數據的前幾個時間步進行初始預測?Z
。使用輸入數據的所有時間步更新 RNN 狀態。
net = resetState(net);
offset = size(X,2);
[net,Z] = predictAndUpdateState(net,X);
要進行進一步的預測,請遍歷時間步并使用?predictAndUpdateState
?函數更新 RNN 狀態。通過將先前的預測值迭代傳遞給 RNN 來預測接下來的 200 個時間步。由于 RNN 不需要輸入數據來進行任何進一步的預測,因此可以指定任意數量的時間步來進行預測。
numPredictionTimeSteps = 200;
Xt = Z(:,end);
Y = zeros(numChannels,numPredictionTimeSteps);for t = 1:numPredictionTimeSteps[net,Y(:,t)] = predictAndUpdateState(net,Xt);Xt = Y(:,t);
end
在繪圖中可視化預測值。
numTimeSteps = offset + numPredictionTimeSteps;figure
t = tiledlayout(numChannels,1);
title(t,"Closed Loop Forecasting")for i = 1:numChannelsnexttileplot(T(i,1:offset))hold onplot(offset:numTimeSteps,[T(i,offset) Y(i,:)],'--')ylabel("Channel " + i)
endxlabel("Time Step")
nexttile(1)
legend(["Input" "Forecasted"])
閉環預測允許您預測任意數量的時間步,但與開環預測相比,其準確度可能會降低,因為 RNN 在預測過程中不會訪問真實值。