Monday, December 7, 2020

實作:利用 PyTorch LSTM 估計未來氣温

簡介
Long Short Term Memory (LSTM) 是一種對時序有記憶的神經網絡。簡單來講,你可以幻想它是一種有短暫及長期記憶的細胞。只要你不斷按順序地訓練它,日子有功,它就會記住事物的先後次序(例如:你每次都用 A-B-C 的順序去訓練它,以後它只要見到 A,就會想起下一個是 B)。

這種神經網絡,對自然語言處理 (Natural Language Processing) 特別有用:因為它能記住句子的先後順序,繼而找出代名詞原本的意思。 例如「小明去了踩單車,他覺得很開心」這一句中,使用 LSTM,系統就能運用短暫記憶,找出「他」所指的主語,是句子開頭的「小明」。

除了 NLP 之外,LSTM 還特別適合用來預測有規律的時序資料 (time-series data)。例如假設每年天氣都是有四季,而且每年氣温都差不多的話,LSTM 就能找出這個潛在的規律,從而推算出將來某月的氣温大約會是多少。還有,通訊系統的訊號、看似沒有規律的雜訊等等,也非常適合用 LSTM 來找出它的潛在規律。

是次實驗,我會使用新加坡的氣温歷史數據,訓練 LSTM,試試到底它能否有效預測將來的温度。不過,由於新加坡沒有四季,而且氣温有可能隨雨量及雲量影響,所以準繩度理應不會太高。但怎樣也好,姑且一試無妨。  

---

幾個重要的變數
是次實驗,我用了這些變數:

  • 原資料的長度為 466 個數據。
  • 我把資料切割成 448 份 [x1 x2 x3 ... x16 x17 x18],然後把期望目標設為 [x19]
    換句話說,我把頭 18 個月的數據進 LSTM,然後期望它會估計到第 19 個月的氣温,
    而這件事會重覆 448 次。
  •  我把 70% 的資料用作訓練,30% 用作驗證。
  • 我使用了 SciKit 的 MinMaxScaler,將所有輸入輸出數據,都以 fit_transform 正規化,
    之後,估算完成後,我再用 inverse_transform 還原。

關於 LSTM 的變數,我設定成:

  • 資料維度 (input_size / features / input_dimension) 為 1,因為氣温是一維的資料。
  • 次序長度 (sequence_len) 為 18,因為我順序放 18 個月的氣温資料。
  • 隱藏層大小 (hidden_size) 為 500,因為我估計會有 500 個特徵值得留意。
  • 層數 (num_layers) 為 3,所以會同時有三個短暫記憶的空間。
  • 我設定了 batch_first=True,所以資料結構是 (batch, sequence, features),
    也就正乎合 for loop DataLoader 時返回來的資料結構,省回轉來轉去的代碼。
    (RNN 全部都有這種選項,因為它的訓練模式與其他相異,
    x1 和 x2 是放進同一個 cell,而非像 linear regression 那種,是放進兩個不同 cells。)

關於訓練的變數:

  • 訓練包大小 (batch size) 為 20, 因為本人的電腦記憶體較少 ,不適宜大包大包訓練。 
  • 我運行了 500 個 epoch,因為我發現次數再多, loss 也沒再變少。
  • 我使用了 Mean Square Error (MSE) 來做 loss function,兩個氣温相差再平方,很直覺。

---

演示代碼

https://github.com/cmcvista/MLHelloWorld/blob/main/LSTMPyTorch/LSTMTemperaturePrediction.ipynb

---

預測結果

紅色為預測結果,藍色為實際結果。

由此可見,單純使用 LSTM 並不太準確。
我估計原因是因為,一來新加坡的氣温變化不大,所以難以準確預測,
二來就是訓練次數不足(或者 optimization strategy 太保守),以至它仍未學足 pattern。

但另一方面,雖然方向估錯,但預測結果的形狀,的確有點像實際數據的形狀。
所以,這也算是一個「有意義的發現」。

---

小結
LSTM 與其他傳統的神經網絡不同,它以 RNN 的形式運作,以致可以認出時間次序。
雖然初步來看,用作預測氣温並不可靠,但用來找出數據的規律,看來也還可以。

---

參考:

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