Chronos-Boltを使ったゼロショット時系列予測お試し
時系列予測モデル
Chronos-Boltというゼロショットで時系列予測ができるモデルを知りました。
一般的な時系列予測モデルというと、予測したいデータの過去データをたくさん集めて学習させて・・・という手順を踏みますが、こちらは事前に大量の時系列データを学習しておくことで、予測したいデータの過去データを集めなくてもなんとなく予測できてしまうよー、というもののようです。
そんなこと本当にできるのだろうかと思いますが、考えてみるとLLMでやられているようなアプローチを時系列モデルに持ってきていると思えば確かにできるのかも・・・ということで、実験してみます。
モデルの概要については上記の記事が詳しいのでご覧ください。
対象データ
予測する実験データとして、e-Statのデータを使います。
e-Stat自体、だいぶ有名になってきている気もしますが念の為紹介しておくと、統計局などが運用していて、日本の様々な統計情報を公開しています。
APIで利用もできたり、web上でグラフ化できたりと便利なので興味あれば見てみてください。大量に情報があるので目的のものを見つけるのが大変ですが・・・。
今回は消費者物価指数を見てみます。
時間軸(年・月) | /2020年基準品目 | 0001 総合 | 0002 食料 | 0045 住居 | 0054 光熱・水道 | 0060 家具・家事用品 |
---|---|---|---|---|---|---|
2025年3月 | 2.9 | 6.7 | 1.1 | 4.7 | ... | |
2025年2月 | 2.8 | 7 | 1 | 5.4 | ... | |
2025年1月 | 3.4 | 7.6 | 0.8 | 11.1 | ... |
出典:「政府統計の総合窓口(e-Stat)」、消費者物価指数 2020年基準消費者物価指数
このように必要な情報をグラフ化したり、csvでダウンロードもできます。
元データは品目ごとに大量にデータがあるのですが、今回は品目を選んでサンプルデータとしています。
Chronos-Boltセットアップと実行
Colaboratoryで動かす想定のコード例です。
まず、日本語が化けるのを防止するためにjapanize-matplotlibを入れておきます。
!pip install japanize-matplotlib
!pip install autogluon
データは上の表のように列ごとにデータがあるものとします。
import pandas as pd
import japanize_matplotlib
from matplotlib import pyplot as plt
# 時間列を指定
df = pd.read_csv("data.tsv", sep="\t", parse_dates=['時間軸(年・月)'])
# parse_datesでうまく行かない場合は個別で処理しましょう
df['日付'] = pd.to_datetime(df['時間軸(年・月)'].str.replace('年', '-').str.replace('月', ''), format='%Y-%m')
# 不要な部分削除
df.drop(columns=['時間軸(年・月)', '/2020年基準品目'], inplace=True)
Chronos-Boltでは複数の時系列データを同時に予測することができます。
データの持ち方としては縦に持って、時系列の名前にあたる部分をitem_id
としておきます。
こんなイメージです。
日付 | item_id | 値 |
---|---|---|
2025-03-01 | A | 1 |
2025-02-01 | A | 2 |
2025-01-01 | A | 3 |
2025-03-01 | B | 5 |
2025-02-01 | B | 4 |
2025-01-01 | B | 3 |
df_long = df.melt(id_vars='日付', var_name='item_id', value_name='値')
予測はわずかこれだけ!
from autogluon.timeseries import TimeSeriesPredictor, TimeSeriesDataFrame
base_data = TimeSeriesDataFrame.from_data_frame(
df_long,
timestamp_column = '日付')
# 12コマ先まで予測してみる
predictor = TimeSeriesPredictor(prediction_length=12, freq="ME", target="値").fit(base_data, presets="bolt_base")
predictions = predictor.predict(base_data)
コードはこれだけですが、初回実行時はモデル(800MB強)をダウンロードして来るので時間がかかります。
結果の可視化はこちら。グラフもうまく作ってくれます。
予測時間はモデルのロードでわずかに待ちますが、2〜3秒も待たないうちに完了します。すごい。
ret = predictor.plot(base_data,predictions,max_history_length=365)
出力された予測結果を見ても、なんとなく納得感ありそうです。
予測結果の検証用
予測結果を評価したい場合、一部を学習データ・一部を検証データにすることが多いと思いますが、そうしたい場合は以下のようにすると良さそうです。
9月を基準に分割し、train_dataを使って予測&実際のデータに重ねて表示
train_data = TimeSeriesDataFrame.from_data_frame(
df_long.query('日付 < "2024-09-01"'),
timestamp_column = '日付')
test_data = TimeSeriesDataFrame.from_data_frame(
df_long.query('日付 >= "2024-09-01"'),
timestamp_column = '日付')
# trainで予測
predictor = TimeSeriesPredictor(prediction_length=7, freq="ME", target="値").fit(train_data, presets="bolt_base")
predictions = predictor.predict(train_data)
# 可視化
# ret = predictor.plot(base_data,predictions,max_history_length=365, item_ids=["0001 総合"])
ret = predictor.plot(base_data,predictions,max_history_length=365)
また、item_idsを指定すると特定のデータだけ可視化することもできます。
実際のデータと重ねて見ると、そんなにぴったり当たっているわけではなさそうですね。
そもそも元データが前年同月比データですし予測に適してないというのはありますが、予測精度を上げる場合はファインチューニングや外部情報の取り込みもできるようです。
実際に実務などに利用する場合はそういった手段を検討すると良さそう。
また、もう一個例として曜日影響の強いデータを同じように予測してみたところ、うまく周期性などは捉えてくれていました。(ARIMAなどと比較しないとな・・・。)
期間変更実験
ふと疑問が生まれました。
大量の過去データを学習しているということは、何月何日に何が起こったみたいなイベント的な影響も加味されているのでしょうか?
試しに、今回のデータの日付を2年半ほど過去日付に書き換えて実験してみます。
元々が2020年〜2025年3月のデータなので、コロナ期間まっただ中のデータとして扱ってみます。
結果、変わらず。
イベント的な情報や、夏だからどうみたいな情報はなさそうです。
(よく考えたらイベント情報入れてしまうと未来日付の予測に影響出るからそりゃそうですね)
まとめ・感想
ゼロショットで予測できるので非常に手軽に利用できるモデルです。
このモデル単体でめちゃくちゃ精度が出るものというよりは、まずはこのモデルでやってみて様子を見るというベースモデルとして使いやすそうです。もちろん、カスタマイズすることで精度もあげれそうなので、下手に自前で時系列モデルを作り込むよりも簡単に高精度のモデルができる可能性も感じました。
また、予測速度も魅力的で、たくさんのデータを一気に予測したい場面は結構あるので、色々応用したいなと思いました。
Discussion