LSTM:在Python中使用PyTorch使用LSTM進行時間序列預測


原文鏈接:

https://stackabuse.com/time-series-prediction-using-lstm-with-pytorch-in-python/

 

時間序列數據,顧名思義是一種隨時間變化的數據類型。例如,24小時時間段內的溫度,一個月內各種產品的價格,一個特定公司一年的股票價格。高級的深度學習模型,如長短期記憶網絡(LSTM),能夠捕捉時間序列數據中的模式,因此可以用來預測數據的未來趨勢。在本文中,您將看到如何使用LSTM算法使用時間序列數據進行未來預測。

 

Dataset and Problem Definition

我們將使用的數據集內置在Python Seaborn庫中。讓我們先導入所需的庫,然后再導入數據集:

1 import torch
2 import torch.nn as nn
3 
4 import seaborn as sns
5 import numpy as np
6 import pandas as pd
7 import matplotlib.pyplot as plt
8 %matplotlib inline

 讀入數據

 

1 import pandas as pd 
2 flight_data = pd.read_csv('./data/flights.csv') #或者flight_data = sns.load_datasets("flights")
3 flight_data.head()

輸出:

 

 flight_data.shape

#輸出: (144,3) 

數據集有三列:year、month以及passengers,包含了12年的乘客出行紀錄;

 

任務:

根據面132個月的出行數據預測后12個月的出行數據;

 

繪制每個月的乘客出行頻率:

1 plt.plot(flight_data['passengers'])
2 plt.grid(True)
3 plt.title("Month vs passenger")
4 plt.ylabel("Total passengers")
5 plt.xlabel("Months")
6 plt.autoscale(axis='x',tight=True)

 

 從輸出結果中可以看出,每年的乘客數量是在逐漸遞增的;

在同一年內,乘客的數量是波動的,這是符合常識的,因為在節假日的時候,乘客的數量相較於一年中的其他日子是會變多的;

 

數據預處理:

首先,看一下數據集中的列的數據類型:

 1 flight_data.columns 

輸出:

Index(['year ', 'month ', 'passengers'], dtype='object')
需要將passengers列的類型轉換為float類型:
all_data = flight_data['passengers'].values.astype(float)

接下來,將數據集划分為訓練數據集和驗證數據集:

test_data_size = 12

train_data = all_data[:-test_data_size] #size=132
test_data = all_data[-test_data_size:] #size=12

此時,數據集並沒有經過標准化處理;

但是乘客數量在剛開始的年份要遠小於近兩年的數量;

我們將使用Min/max進行標准化;

1 from sklearn.preprocessing import MinMaxScaler
2 
3 scaler = MinMaxScaler(feature_range=(-1,1))
4 train_data_normalized = scaler.fit_transform(train_data.reshape(-1,1))

之后,將其轉化為tensor的數據形式:

train_data_normalized = torch.FloatTensor(train_data_normalized).view(-1)

#轉換成1維張量

最后,就是將數據處理成sequences和對應標簽的形式;

在這里,我們取時間窗口為12,因為一年有12個月,這個是比較合理的;

 

 1 train_window=12
 2 
 3 def create_inout_sequences(input_data,tw):
 4     inout_seq = []
 5     L = len(input_data)
 6     for i in range(L-tw):
 7         train_seq = input_data[i:i+tw]
 8         train_label = input_data[i+tw:i+tw+1]
 9         inout_seq.append((train_seq,train_label))
10     return inout_seq
11 
12 train_inout_seq = create_inout_sequences(train_data_normalized,train_window)
#一共有120個樣本 132-12=120

 

創建LSTM模型:

 1 class LSTM(nn.Module):
 2     def __init__(self, input_size=1,hidden_layer_size=100,output_size=1):
 3         super().__init__()
 4         
 5         self.hidden_layer = hidden_layer_size
 6         self.lstm = nn.LSTM(input_size,hidden_layer_size)
 7         self.linear = nn.linear(hidden_layer_size,uotput_size)
 8         self.hidden_cell = (torch.zeros(1,1,self.hidden_layer_size),
 9                            torch.zeros(1,1,self.hidden_layer_size))
10     def forward(self, input_seq):
11         lstm_out, self.hidden_cell = self.lstm(input_seq.view(len(input_seq),1,-1), self.hidden_cell)
12         predictions = self.linear(lstm_out.view(len(input_seq),-1))
13         return predictions[-1]

input_size:對應的輸入數據特征; 雖然我們的序列長度是12,但是對於每個月來說,我們只有1個值,例如,乘客的總數量,因此輸入的size是1;
hidden_layer_size: 每層的神經元的數量,我們每層一共有100個神經元;
output_size:預測下一個月的輸出數量,輸出的size為1;


之后我們創建hidden_layer_size, lstm, linear 以及hidden_cell。
LSTM算法接收三個輸入:之前的輸入狀態;之前的的cell狀態以及當前的輸入;
hidden_cell變量包含了先前的隱藏狀態和cell狀態;
lstm和linear層變量,用於創建LSTM和線性層;

在forward()算法中,使用input_seq作為輸入參數,首先被傳遞給lstm;
lstm的輸出,包含了當前時間戳下的隱藏層和細胞狀態,以及輸出;
lstm層的輸出被傳遞給Linear層,預測的乘客數量,就是predictions的最后一項;

創建模型類的對象、定義損失函數和優化器:
1 model = LSTM()
2 loss_function = nn.MSELoss()
3 optimizer = torch.optim.Adam(model.parameters(),lr=0.001)

 

 1 # 模型的訓練
 2 epochs = 15
 3 
 4 for i in range(epochs):
 5     for seq, labels in train_inout_seq:
 6         optimizer.zero_grad()
 7         model.hidden_cell = (torch.zeros(1,1,model.hidden_layer_size),
 8                             torch.zeros(1,1,model.hidden_layer_size))
 9         
10         y_pred = model(seq)
11         
12         single_loss = loss_function(y_pred, labels)
13         single_loss.backward()
14         optimizer.step()
15         
16     if i%2 ==1 :
17         print(f'epoch:{i:3} loss:{single_loss.item():10.8f}')
18 print(f'epoch:{i:3} loss:{single_loss.item():10.8f}')

 

 

 

模型的預測:

 1 # 預測:
 2 fut_pre = 12
 3 
 4 test_inputs = train_data_normalized[-train_window:].tolist()
 5 print(test_inputs)
 6 
 7 model.eval()
 8 for i in range(fut_pre):
 9     seq = torch.FloatTensor(test_inputs[-train_window:])
10     with torch.no_grad():
11         model.hidden = (torch.zeros(1,1,model.hidden_layer_size),
12                             torch.zeros(1,1,model.hidden_layer_size))
13         
14         test_inputs.append(model(seq).item())

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM