暑い日々が続くのでgluonTS(LSTM)を用いた気温予測を試みる


この暑さはいつまで続くのか。

過去の気温から未来の予測が出来ないか。
気を紛らすために確率的時系列モデリングのためのGluonツールキットのGluonTSを試してみました。

インストール

利用するためには、mxnet,gluonライブラリが必要です(この記事を参考にしました)。
anacondaなどでPythonを導入していると、pipですぐインストールできます。

$pip install -U pip
$pip install mxnet
$pip install gluonts

pip自体が古いと、この後のソースコードを実行する際にエラーが出る場合があるので、pip自体のアップデートをしておくとよいと思います。

データ取得

気温データをcsvファイルで取得したいので、気象庁の過去の気象データ・ダウンロードサイトからデータを取得することにしました。

例として佐賀県佐賀市のの2018/8/14~2020/8/14の2年分のデータをダウンロードしました。
年度推移を覚え込ませるために、なんとなく2年分のデータを取得しました。

#jupyter notebook上で動作確認を実施
import pandas as pd
import datetime
%matplotlib inline

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

#まずは佐賀県の気温データの読み込み
tempera_data = pd.read_excel("saga_weather_data_20200815.xlsx") #※加工しやすいようにexcelファイルに修正
tempera_data["time"] = pd.to_datetime(tempera_data['年月日'])

現状こんな感じのデータです。

このDataFrameの"time","平均気温(℃)"列を用いていきます。

analysis_data = tempera_data[["time", '平均気温(℃)']]

どんなデータか可視化してみます。

plt.figure(figsize=(15, 5))
plt.plot(analysis_data["time"], analysis_data["平均気温(℃)"])
plt.grid(True)
plt.show()

直近の7日分を予測するために、学習:1日目~725日目、評価:726日目~とすることにしました。
以下の図でいうところのオレンジ色の部分です。

tmp_time = np.arange(0, len(analysis_data))
analysis_data["re_time"] = tmp_time #時間情報を変換
plt.figure(figsize=(15, 5))

# 推論したい領域(網掛け部分)
plt.axvspan(725,len(tmp_time),color="orange")

plt.plot(tmp_time, analysis_data["平均気温(℃)"])
plt.xlabel("[day]")
plt.grid(True)
plt.show()

学習と評価

学習と評価のデータを定義します。

from gluonts.dataset.common import ListDataset

#make_train
predict_length = 7
training_data = ListDataset(
    [{"start": analysis_data["time"].values[0], "target": analysis_data.iloc[:len(tmp_time)-predict_length, 1]}],
    freq = "24H")

#make_test
test_data = ListDataset(
    [{"start": analysis_data["time"].values[0], "target": analysis_data.iloc[:len(tmp_time), 1]}],
    freq = "24H")

学習をするため、estimatorを定義します。
パラメータは参考記事や公式チュートリアルなどを参考に設定しました。

from gluonts.model.simple_feedforward import SimpleFeedForwardEstimator
from gluonts.trainer import Trainer

estimator = SimpleFeedForwardEstimator(freq="24H",
                            context_length=20,
                            prediction_length=10,
                            trainer=Trainer(epochs=300,
                                            batch_size=32,
                                            learning_rate=0.001))

predictor = estimator.train(training_data=training_data)

どのような推論結果になるのか、可視化してみます。

from gluonts.dataset.util import to_pandas

for test_entry, forecast in zip(test_data, predictor.predict(test_data)):
    plt.figure(figsize=(15, 5))
    to_pandas(test_entry).plot(linewidth=2)
    forecast.plot(color='g', prediction_intervals=[50.0, 90.0])

plt.legend(["observations", "median prediction", "90% confidence interval", "50% confidence interval"], 
          loc='lower left')
plt.grid(which='both')

バラつきが大きいものの、なんとな~く予測が出来ていそうです。

今後

  • もっと精度よく推論するため、GluonTSの使い方を色々試してみたい(コメント等でアドバイス頂けると嬉しいです)。

参考記事

ありがとうございました!