時系列データの未来予測 - 気温予測
AIゆめ
CNNモデルによる未来予測は、本ページに示すように多要素が絡み合う複雑な時系列データであっても、高精度に予測することが可能ですので、製造業・非製造業に拘わらず、「自社の問題解決に応用できるのではないか?」と思われた方は、
ネオラクス・メール送信フォーム からお気軽にご相談ください。AI技術を用いて、世の中にある様々な問題の解決に貢献して行きたいと思います。
AIによる一般的な時系列データの予測方法
AIモデルを用いて時系列データの未来を予測する方法としては、
時系列予測:TensorFlowチュートリアル で示されているように、気温や風速など一定の時刻幅ウィンドウと、次の時刻の目標値(今回の場合は気温)のデータセットを教師データとして学習させる方法が一般的であり、図1に示すようなデータを生成することから始める。しかし、この方法を使用しても、意外に予測精度が上がらない。本ページでは、
気象庁が公開している気温、風速、風向、天候などの情報 を用いて、高精度に未来の気温を予測する方法について検討する。
図1 一般的な時系列データの予測のためのデータ生成
気象庁のデータの準備
上記、気象庁のページから「地点(今回は東京)」「項目(日平均気温、日合計全天日射量、日最大風速(風向)、天気概況(昼:06時~18時)、天気概況(夜:18時~翌日06時)」「期間」を設定しCSVファイルにダウンロードする。今回使用した期間は1990年1月1日~2023年7月20日の33年間に渡る日々のデータであり、6ファイルに分割してダウンロードした。時間によってはアクセスが集中し、ダウンロードがタイムアウトすることもあったが、企業の営業活動時間帯を避ければ、スムーズにダウンロードできるようである。ダウンロードCSVファイルの品質情報列と均質番号列を削除、最大風速(m/s)列が2列になるので風向のタイトルを移動、1~3行と5,6行目を削除し、最終的に図2のようなCSVファイルにする。
図2 加工後の気象庁CSVファイル
その後、Pythonで読み込み、NaNデータを埋め、正規化するなどの処理を行うが、忘備録も兼ねて、キーポイントを記録しておく。特に、最大風速と風向にNaNが二か所含まれていたが、それだけでトレーニングのmse(平均二乗誤差)出力がNaNになるなど、学習が全くできなくなるので、NaNのチェックとその処理は重要である。今回のケースでは、風速や風向は前日に近いだろうという考えから前日の値で代用したが、NaNを含む行を消すというのも一つの選択肢であろう。また、訓練の全入力はfloat64で与えるため、文字列で与えられている"風向", "天気概況(昼:06時~18時)", "天気概況(夜:18時~翌日06時)"の3列は、あらかじめユニークな数値IDに変換した後float64に変換している。
#trainファイルを読み込み、日付を日時データにしてindexにし、全ファイルを結合し日付でソートする
files = glob.glob("./data_JMA/*.csv")
data_list = []
for file in files:
data_list.append(pd.read_csv(file, index_col=0, encoding='cp932', parse_dates=True))
df = pd.concat(data_list).sort_index()
#NaNデータを全てその上段の値で置換する
df = df.fillna(method="ffill")
#NaNが無いことを確認する
print(df.isna().sum())
#風向、天気概況の文字列をユニークな数値IDに変換する
for col in ["風向", "天気概況(昼:06時~18時)", "天気概況(夜:18時~翌日06時)"]:
df[col] = df[col].astype("category").cat.codes.astype('float64')
#各列の統計値を確認する
print(df.describe())
この時点で日付は日時データにしてindexになっているため、このままでは日時データ抜きの解析しかできない。
時系列データの未来予測 - 航空機乗客数の予測 のページに示したように、年、月、日ごとの変化を精度よく捉えるためには、単に年月日が入った列を用意するのではなく、下記のように'年','月','日'の列データを用意する必要がある。
#年月日をカラムに分ける
df['Year'] = df.index.year
df['Month'] = df.index.month
df['Day'] = df.index.day
df = df.astype('float64')
そして、正規化を行った後、訓練データ(df_train)80%、評価データ(df_val)10%、予測値確認用データ(df_pred)10%に分割する。時系列解析なのでシャッフルは行わない。訓練データで訓練を行い、1エポックごとに評価データのmse(平均二乗誤差)が最小になるよう学習を続ける。そして、最新の10%のデータは、予測値の精度評価のために使用するので、訓練では全く使用しない。正規化においては、全データが0~1の範囲に入るようにしたが、-1~1の範囲でも良いし、標準偏差で割って±1の範囲から多少はみ出すような設定でも問題はない。
#正規化を行う
df_min = df.min()
df_norm = df.max() - df_min
df = ( df - df_min ) / df_norm
#train,test,valに分割する
df_num = len(df)
df_train = df[0:int(df_num*0.8)]
df_val = df[int(df_num*0.8):int(df_num*0.9)]
df_pred = df[int(df_num*0.9):]
一次元CNNモデルによる予測結果
まず、
AIによる一般的な時系列データの予測方法 に示すような時系列データに関する特殊な処理を行わず、以下のような簡単な一次元CNNモデルで予測した。列数は、indexを'年','月','日'の列データに分割し、温度列を除いた8列であり、tf.keras.layers.Conv1Dのfilters=64としている。この項の解析は時系列解析ではないのでシャッフルを行ってもよいが、ここではシャッフルは行っていない。
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv1d (Conv1D) (None, 8, 64) 256
flatten (Flatten) (None, 512) 0
dense (Dense) (None, 8) 4104
dense_1 (Dense) (None, 1) 9
=================================================================
Total params: 4,369
Trainable params: 4,369
Non-trainable params: 0
_________________________________________________________________
図3に一次元CNNモデルの機械学習の進行状況を示すが、まずまずの進行状況と言える。図4に気温の予測結果を示すが、この図は全期間の最後30%の期間のみを表示している。そして、この図の最初の1/3が訓練データの最後の期間、次の1/3が評価データの期間、最後の1/3が予測データの期間であり、予測データの期間は学習には全く関与していない部分を意味する。図5は、より詳細な比較を行うため、予測データの期間の内、2022/01/01~2023/07/20の期間を拡大表示した。予測データ全期間の二乗平均平方根誤差は2.25℃であり、詳細な日々の変動の予測は不十分であるものの、まずまずの精度で予測できていることがわかる。
図3 一次元CNNモデルの機械学習の進行状況
図4 一次元CNNモデルによる気温の予測結果
図5 一次元CNNモデルによる気温の予測結果(2022/01/01~2023/07/20)
LSTMモデルによる予測結果
時系列データの未来予測のページで説明した
LSTM(Long Short Term Memory)モデル を使用して、気温の予測精度を向上することができないかを試したので報告する。タイムステップ幅を128日とし、下記のようなLSTMモデルで予測した。図6および図7にLSTMモデルによるの機械学習の進行状況と気温の予測結果(2022/01/01~2023/07/20)を示すが、一次元CNNモデルに比較して予測精度が悪化しているようであり、LSTMモデルを二層にしても改善は見られなかった。予測データ全期間の二乗平均平方根誤差は2.42℃であり、確かに一次元CNNに比較して悪化している。
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
lstm (LSTM) (None, 128) 70656
dense (Dense) (None, 1) 129
=================================================================
Total params: 70,785
Trainable params: 70,785
Non-trainable params: 0
_________________________________________________________________
図6 LSTMモデルの機械学習の進行状況
図7 LSTMモデルによる気温の予測結果(2022/01/01~2023/07/20)