用LSTM進行時間序列預測(單步,多步,單變量,多變量)

0. LSTM用於時間序列預測

LSTM因其具有記憶的功能,可以利用很長的序列信息來建立學習模型,所以用它來進行時間序列的預測會很有優勢。

在實際工程中用LSTM進行時間序列的預測主要有兩個難點:一是前期對數據的處理,二是初始模型的搭建。對數據的處理無論是單步、多步、單變量還是多變量都會用到滑動窗口來處理數據,具體處理的方法後面會進行闡述;而對模型的搭建則要根據要解決的問題,原始數據的情況等,對模型的參數做相應的設定,如果單純的LSTM無法滿足要求,一般會加入全連接層來解決。

1. 單變量單步

單變量單步的預測是最簡單的,比如說有一組數據爲:
[1,2,3,4,5,6,7,8,9,10],然後要求利用這組數據訓練一個模型,使其能對後面提供的數據做一個單步的預測。

我們先來對數據進行處理,處理的時候要根據不同框架所要求的LSTM的輸入形式來處理,比如我們用Pytorch框架的時候輸入要求是(seq_len, batch, input_size)。

因爲是單變量的數據,我們令input_size=3,然後設seq_len=7,然後batch爲1,
處理後的數據變爲:
[[1,2,3], =====> [4]
[2,3,4], =====> [5]
[3,4,5], =====> [6]
[4,5,6], =====> [7]
[5,6,7], =====> [8]
[6,7,8], =====> [9]
[7,8,9]] =====> [10]
前半部分是輸入,箭頭指向輸出。也就是說將數據分批輸入LSTM,沒三個數據對應一個單步的預測目標。

數據處理好之後就是模型的搭建了,我們根據輸入輸出的形式來反推模型的結構。我們知道LSTM的結構是lstm = nn.LSTM(input_size, hidden_size, num_layers),由上面給出的輸入的形式可以確定input_size=3, hidden_size, num_layers這兩個參數要自己設置,也就是隱藏層的大小和層數。我們的預計輸出的形式爲(7,1),但是LSTM的標準輸出形式爲:
output=(seq_len,batch,num_directionshidden_size)=(7,1,num_directionshidden_size),
當num_directionshidden_size不爲1時我們需要在LSTM的後面加一個全連接層,並令全連接層的輸入形式爲num_directionshidden_size,輸出爲1 。這樣我們的輸出就變爲了output=(7,1,1) ,然後用reshape方法(當out爲numpy array時)或者view方法(當out爲tensor時)將output整形爲(7,1)。這樣就可以用在後面的訓練中了,即計算損失函數和反向傳播。

2. 多變量多步

比如一組數據爲:
[[1,11],[2,12],[3,13],[4,14],[5,15],[6,16],[7,17],[8,18],[9,19],[10,20]]
要求對其進行兩步預測,則我們對其進行處理:
[[[1,11],[2,12],[3,13]], ======>[[4,14],[5,15]]
[[2,12],[3,13],[4,14]], ======>[[5,15],[6,16]]
[[3,13],[4,14],[5,15]], ======>[[6,16],[7,17]]
[[4,14],[5,15],[6,16]], ======>[[7,17],[8,18]]
[[5,15],[6,16],[7,17]], ======>[[8,18],[9,19]]
[[6,16],[7,17],[8,18]], ======>[[9,19],[10,20]]
前半部分是輸入,箭頭指向輸出。seq_len=6,batch=3,input_size=2

搭建模型的部分跟上面的分析是一樣的,output的形狀跟target一樣爲(6,2,2),而輸入的形狀爲(6,3,2),所以還是需要一個全連接層使其輸入爲(6,3,2)輸出爲(6,2,2),這樣才能用在後面的訓練中。

最後如果要畫出輸出的圖像的話可以取out[:3, 0, :]和out[:,1,:]在axis=0上拼接出來。

下面是模型的建立:

class LSTM(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers):
        super(LSTM, self).__init__()
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
        self.fc = nn.Linear(hidden_size, 2)  # 2 for bidirection

    def forward(self, x):
        # Set initial states
        h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(device)  # 2 for bidirection
        c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(device)

        # Forward propagate LSTM
        out, _ = self.lstm(x, (h0, c0))  # out: tensor of shape (batch_size, seq_length, hidden_size*2)
        # print("output_in=", out.shape)
        # print("fc_in_shape=", out[:, -1, :].shape)
        # Decode the hidden state of the last time step
        # out = torch.cat((out[:, 0, :], out[-1, :, :]), axis=0)
        # out = self.fc(out[:, -1, :])  # 取最後一列爲out
        out = self.fc(out)
        return out

3. 其餘情況

單變量多步和多變量單步的情況的處理方法跟上面兩個是類似的。

基於LSTM的時間序列數據(多步)預測
如何進行多變量LSTM時間序列預測未來一週的數據?
用LSTM預測未來一個月航班數
多維多步預測

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