基于LSTM的序列预测: 飞机月流量预测
基于LSTM的序列預測: 飛機月流量預測
?
循環神經網絡,如RNN,LSTM等模型,比較適合用于序列預測,下面以一個比較經典的飛機月流量數據集,介紹LSTM的使用方法和訓練過程。
完整的項目代碼下載:https://download.csdn.net/download/guyuealian/33998269
【尊重原作,轉載請注明出處】:https://panjinquan.blog.csdn.net/article/details/120918732
目錄
基于LSTM的序列預測: 飛機月流量預測
1.數據處理
2.構建LSTM模型
3.損失函數和優化器
4.訓練Pipeline
5.預測效果
6.更多AI項目
1.數據處理
下表圖是某國家12年共144個月的飛機月流量數據表,由于月流量數據是不規范的標量,需要將數據標準化到同一尺度,即0~1之間,以便用于模型訓練。
| 原始數據 | 歸一化后的數據 |
接著我們進行數據集的創建,我們想通過前面幾個月的流量來預測當月的流量,比如我們希望通過前兩個月的流量來預測當月的流量,我們可以將前兩個月的流量當做輸入,當月的流量當做輸出。同時我們需要將我們的數據集分為訓練集和測試集,通過測試集的效果來測試模型的性能,這里我們簡單的將前面幾年的數據作為訓練集(70%),后面兩年的數據作為測試集(30%),其中look_back=2表示使用前2個月的流量數據預測當前月的流量,當然也可以設置為look_back=3或4。
def create_dataset(dataset, look_back=2):""":param dataset: (144,1):param look_back::return: data_inputs (142,2)data_target (142,1)"""dataset = np.asarray(dataset)data_inputs, data_target = [], []for i in range(len(dataset) - look_back):a = dataset[i:(i + look_back)]data_inputs.append(a)data_target.append(dataset[i + look_back])data_inputs = np.array(data_inputs).reshape((-1, look_back))data_target = np.array(data_target).reshape((-1, 1))return data_inputs, data_targetdef split_train_test_data(data_inputs, data_target, rate=0.7):""":param data_inputs: :param data_target: :param rate:訓練集占比:return: """# 劃分訓練集和測試集,70% 作為訓練集train_size = math.ceil(len(data_inputs) * rate)train_inputs = data_inputs[:train_size]train_target = data_target[:train_size]test_inputs = data_inputs[train_size:]test_target = data_target[train_size:]return train_inputs, train_target, test_inputs, test_targetRNN模型輸入數據的維度是(seq,batch,input),其中batch是1,由于只有一個序列,input就是預測依據的月份數2,seq的大小就是訓練集的序列長度
2.構建LSTM模型
Pytorch已經實現了LSMT模塊,在此基礎上可構建循環神經網絡LSTM模型。模型共包含兩個模塊:第一模塊是LSTM,以兩個月的數據作為輸入,并得到一個輸出特征。第二個模塊是全連接層FC,將 RNN 的輸出回歸到目標值;模塊之間數據維度變化,需要使用?`view` 來重新排列
因為 `nn.Linear` 不接受三維的輸入,所以我們先將前兩維合并在一起,然后經過線性層之后再將其分開,最后輸出結果。
另外,模型輸入維度是根據前面的數據處理來確定的,由于我們新建的訓練數據是依賴前兩個月的飛機月流量數據來預測第三個月的流量,所以數據數據的維度是2。
# -*-coding: utf-8 -*- """@Author : panjq@E-mail : pan_jinquan@163.com@Date : 2021-10-17 14:21:43 """ import torch from torch import nnclass LSTMModel(nn.Module):"""定義LSTM模型: LSTM+FC的回歸模型"""def __init__(self, input_size, hidden_size=5, num_layers=7, output_dim=1):"""Ref:https://www.zhihu.com/question/41949741/answer/318771336https://zhuanlan.zhihu.com/p/41261640輸入數據格式:input(seq_len, batch, input_size)h0(num_layers * num_directions, batch, hidden_size)c0(num_layers * num_directions, batch, hidden_size)輸出數據格式:output(seq_len, batch, hidden_size * num_directions)hn(num_layers * num_directions, batch, hidden_size)cn(num_layers * num_directions, batch, hidden_size):param input_size: RNN輸入的特征維度,如單詞向量中embedding_dim,序列向量的特征維度,注意不是序列長度:param hidden_size: RNN隱藏層或輸出層的特征維度:param num_layers: RNN的網絡層數,即模型集成的LSTM的個數,相當于LSTM摞起個數,默認1個Number of recurrent layers. E.g., setting ``num_layers=2``would mean stacking two LSTMs together to form a `stacked LSTM`,with the second LSTM taking in outputs of the first LSTM andcomputing the final results. Default: 1:param output_dim:"""super(LSTMModel, self).__init__()self.rnn = nn.LSTM(input_size=input_size, hidden_size=hidden_size, num_layers=num_layers) # rnnself.reg = nn.Linear(hidden_size, output_dim) # 回歸def forward(self, inptut):"""inptut=(seq, batch, input_size)output=(seq, batch, hidden_size):param inptut::return:"""# output, (hn, cn) = rnn(input, (h0, c0))o, _ = self.rnn(inptut) # output=(seq, batch, hidden_size)s, b, h = o.shapeo = o.view(s * b, h) # 轉換成線性層的輸入格式o = self.reg(o)o = o.view(s, b, -1)return otorch.nn.LSTM()參數說明:
input_size 輸入數據的特征維數,通常就是embedding_dim(詞向量的維度)
hidden_size LSTM中隱層的維度
num_layers 循環神經網絡的層數
bias 用不用偏置,default=True
batch_first 這個要注意,通常我們輸入的數據shape=(batch_size,seq_length,embedding_dim),而batch_first默認是False,所以我們的輸入數據最好送進LSTM之前將batch_size與seq_length這兩個維度調換
dropout 默認是0,代表不用dropout
bidirectional默認是false,代表不用雙向LSTM
3.損失函數和優化器
序列預測本質還是一個回歸模型,回歸任務最常用的損失函數主要有MSE、RMSE、MAE,表達式如下:
本題目比較簡單,可以直接使用均方誤差(MSE) 作為優化目標函數,Pytorch中 已經定義MSELoss函數
nn.MSELoss()優化器,可使用SGD或者Adam
4.訓練Pipeline
# -*-coding: utf-8 -*- """@Author : panjq@E-mail : pan_jinquan@163.com@Date : 2021-10-17 14:21:43 """ import argparse import torch from torch import nn import matplotlib.pyplot as plt from seq.data_utils import load_dataset, create_dataset, split_train_test_data from seq.lstm import LSTMModelclass Trainer(object):def __init__(self, args):self.num_epoch = args.num_epoch# 通過前幾個月(look_back)的流量來預測當月的流量,默認2self.look_back = 2self.batch_size = 1self.dataset = load_dataset(args.data_file, plot=True)self.data_inputs, self.data_target = create_dataset(self.dataset, look_back=self.look_back)self.train_inputs, self.train_target, self.test_inputs, self.test_target = \split_train_test_data(self.data_inputs, self.data_target)# 需要將數據改變一下形狀,因為RNN讀入的數據維度是(seq, batch, feature)# 所以要重新改變一下數據的維度,這里只有一個序列,所以batch是 1# 而輸入的 feature就是我們希望依據的幾個月份# 這里我們定的是兩個月份,所以feature就是2self.train_inputs = self.train_inputs.reshape(-1, self.batch_size, self.look_back)self.train_target = self.train_target.reshape(-1, self.batch_size, 1)self.test_inputs = self.test_inputs.reshape(-1, self.batch_size, self.look_back)self.data_inputs = self.data_inputs.reshape(-1, self.batch_size, self.look_back)self.model = self.build_model()self.criterion = nn.MSELoss()self.optimizer = torch.optim.Adam(self.model.parameters(), lr=1e-2)def build_model(self):# 定義好網絡結構,輸入的維度input_dim=2(因為我們使用兩個月的流量作為輸入)# 隱藏層的維度hidden_dim=4model = LSTMModel(input_dim=self.look_back, hidden_dim=4)return modeldef train(self):inputs = torch.from_numpy(self.train_inputs)target = torch.from_numpy(self.train_target)self.model.train() # 轉換成測試模式# 開始訓練for epoch in range(self.num_epoch):# 前向傳播output = self.model(inputs)loss = self.criterion(output, target)# 反向傳播self.optimizer.zero_grad()loss.backward()self.optimizer.step()if epoch % 100 == 0: # 每 100 次輸出結果print('Epoch: {}, Loss: {:.5f}'.format(epoch, loss.item()))self.test()def test(self):"""這里藍色的是真實的數據集,紅色的是預測的結果,我們能夠看到,使用lstm能夠得到比較相近的結果,預測的趨勢也與真實的數據集是相同的,因為其能夠記憶之前的信息,而單純的使用線性回歸并不能得到較好的結果,從這個例子也說明了 RNN 對于序列有著非常好的性能。:return:"""self.model.eval() # 轉換成測試模式# inputs = torch.from_numpy(self.test_inputs)inputs = torch.from_numpy(self.data_inputs)output = self.model(inputs) # 測試集的預測結果# 改變輸出的格式output = output.view(-1).data.numpy()# 畫出實際結果和預測的結果plt.plot(output, 'r', label='prediction')plt.plot(self.dataset, 'b', label='real')plt.legend(loc='best')plt.show()def get_parser():data_file = "data/data.csv"parser = argparse.ArgumentParser(description=__doc__)# parser.add_argument('--batch_size', type=int, default=32, help='訓練的批量大小')parser.add_argument('--num_epoch', type=int, default=1000, help='訓練的輪數')parser.add_argument('--data_file', type=str, default=data_file, help='數據文件')return parserif __name__ == '__main__':parser = get_parser()args = parser.parse_args()t = Trainer(args)t.train()訓練迭代1000次后,模型已經收斂,Loss已經很小了
Epoch: 0, Loss: 0.08340 Epoch: 100, Loss: 0.00399 Epoch: 200, Loss: 0.00360 Epoch: 300, Loss: 0.00321 Epoch: 400, Loss: 0.00285 Epoch: 500, Loss: 0.00326 Epoch: 600, Loss: 0.00156 Epoch: 700, Loss: 0.00128 Epoch: 800, Loss: 0.00127 Epoch: 900, Loss: 0.001215.預測效果
下面是測試效果,其中藍色是真實的飛機月流量數據,紅色的預測的數據,可以看到使用LSTM能夠預測近似的結果。
6.更多AI項目
更多AI技術博客推薦:
人臉檢測+人體檢測C++ Android項目_pan_jinquan的博客-CSDN博客人臉檢測+人體檢測C++ Android實現本博客將實現C++版本的人臉檢測,人臉關鍵點檢測,人體檢測,人臉+人體檢測,推理框架采用TNN,在普通Android手機,CPU和GPU都可以達到實時檢測的效果人臉檢測+人臉關鍵點檢測+人體檢測Android Demo APP(非源碼,僅供學習交流)鏈接: https://pan.baidu.com/s/1By43I1DbMa0gBPLObtPZMQ 提取碼: msnr尊重原創,轉載請注明出處:https://panjinquan.blog..https://panjinquan.blog.csdn.net/article/details/120688804
2D Pose人體關鍵點實時檢測(Python/Android /C++ Demo)_pan_jinquan的博客-CSDN博客人體關鍵點檢測關鍵點圖示# 關鍵點連接線序號(用于繪制圖像)skeleton =[[15, 13], [13, 11], [16, 14], [14, 12], [11, 12], [5, 11], [6, 12], [5, 6], [5, 7], [6, 8], [7, 9], [8, 10], [0, 1], [0, 2], [1, 3], [2, 4]]# 圖像左右翻轉時,成對的關鍵點(訓練時用于數據增強)flip_...https://panjinquan.blog.csdn.net/article/details/115765863
?如果你覺得該帖子幫到你,還望貴人多多支持,鄙人會再接再厲,繼續努力的~
總結
以上是生活随笔為你收集整理的基于LSTM的序列预测: 飞机月流量预测的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 图像抠图Image Matting算法调
- 下一篇: /usr/lib/deepin-wine