株式会社ホコサキ

TimesFMをゼロショットで動かす:Prophet・ARIMAとの使い分けと最小構成コード

天京祐輔
天京祐輔
TimesFMをゼロショットで動かす:Prophet・ARIMAとの使い分けと最小構成コード

Prophet や ARIMA で回していた予測パイプラインに、そろそろ手を入れたい。でも新しいモデルを試すたびに学習データの整備・ハイパーパラメータ探索・評価サイクルが発生して、結局「動いてるものを触るな」になりがち——そんな経験がある人に、TimesFM は刺さると思います。

Google Research が公開した時系列予測の基盤モデル TimesFM を、ファインチューニングなし・手元の業務 CSV をそのまま渡す最小構成で動かすまでを具体的に示します。あわせて Prophet/ARIMA との使い分け基準と、需要予測・シフト計画・在庫管理への当てはめ方を整理します。

TimesFMが「ゼロショットで動く」理由を実務目線で整理する

TimesFM は Google Research が開発した 200M パラメータの Transformer ベース時系列予測モデルで、約 100B(1000億)データポイントで事前学習されています。ICML 2024 に採択された論文で詳細が公開されており、現時点の最新版は TimesFM 2.5 です(パラメータ効率の改善と長いコンテキスト長への対応が主な改良点)。

アーキテクチャ上の特徴は「パッチベースのデコーダ専用 Transformer」という点です。入力時系列を短いウィンドウ(パッチ)に切り分けてトークン化し、デコーダのみの構造で次のパッチを逐次生成します。出力パッチの長さを入力パッチより長く設定できるため、自己回帰的な呼び出し回数を減らしながら長めのホライズンを一気に予測できます。LLM が文章の続きを生成するのと構造的に近い発想です。

ゼロショットで動く理由は、事前学習の規模と多様性にあります。小売・交通・エネルギー・金融など多領域の実データで学習することで、事前学習段階で多様な時系列パターンを暗黙的に内包しています。だから初見のデータにも汎化できる——LLM がゼロショットで質問に答えられるのと同じ理由です。

Prophet や ARIMA との対比で言うと、違いは明確です。ARIMA は次数 (p, d, q) の選定と各系列へのフィッティングが必要で、系列ごとに計算コストがかかります。Prophet は fit() を呼ぶだけとはいえ、祝日設定や季節性の周期を調整するパラメータチューニングが実務では避けられません。TimesFM はそのどちらも不要で、コンテキスト長と予測ホライズンを指定して渡すだけです。

Chronos(Amazon)や Moirai(Salesforce)など同系統の時系列基盤モデルも存在しますが、本稿では TimesFM に絞ります。

Prophet・ARIMAとの使い分け:判断軸は「データ量」と「外部変数」

「TimesFM に全部乗り換える」という発想より、「このシーンでは何を選ぶか」という判断基準を持つ方が実務では使いやすいです。

Medium に公開されているロンドン自転車シェアデータを使った比較実験では、TimesFM は 3 日以降の予測精度で ARIMA・Prophet を上回る傾向が確認されています。一方、1 日以内の短期では ARIMA が健闘するケースもあり、「TimesFM が常に勝つ」わけではありません。データの特性と予測ホライズンで使い分けるのが現実的です。

外部変数の扱いは、現時点の TimesFM の最大の制約です。プロモーション施策・祝日フラグ・気温などの共変量を直接モデルに渡す仕組みがなく、「売上に影響する外部イベントを考慮した予測」が必要なシーンでは Prophet が依然として有効です。Prophet の add_regressor()add_country_holidays() の柔軟性は、この点で TimesFM にはない強みです。

データ量が少ない場合も注意が必要です。TimesFM のゼロショット性能は事前学習の汎化力に依存しているため、極端に短い系列(数十点以下)でも一応動きますが、精度保証は難しくなります。逆に、系列数が多くて各系列のデータ量が中程度(数百点以上)というケースでは、フィッティング不要の TimesFM が圧倒的にスループットで有利です。

判断軸TimesFMProphetARIMA
学習・フィッティング不要(ゼロショット)系列ごとに fit()系列ごとに次数選定+fit
外部変数(共変量)非対応対応(add_regressor限定的
短期予測(〜1日)普通良好良好
中期予測(3日〜数週間)良好普通劣化しやすい
系列数が多い場合高スループット系列数に比例してコスト増同左

月次売上CSVを渡して予測グラフを出すまで

まずインストールから。PyPI に公開されているので pip 一発です。最新の v2 系を使う場合は以下のとおりです。

pip install timesfm

GPU 環境なら timesfm[gpu] を指定すると JAX の GPU バックエンドが有効になります。手元の検証は backend="cpu" で十分動きます。本番で大量系列を捌く場合は GPU を推奨します。

次に、月次売上 CSV を読み込んで予測グラフを出力するまでの一気通貫コードを示します。CSV は date(YYYY-MM-DD 形式)と sales(数値)の 2 列を想定しています。

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

# --- 1. データ読み込み ---
df = pd.read_csv("monthly_sales.csv", parse_dates=["date"])
df = df.sort_values("date").reset_index(drop=True)

# コンテキストとして渡す過去データ(直近 24 ヶ月)
context_len = 24
history = df["sales"].values[-context_len:].astype(np.float32)

# --- 2. TimesFm 初期化 ---
tfm = timesfm.TimesFm(
    context_len=context_len,   # モデルに渡す過去系列の長さ
    horizon_len=6,             # 予測したい未来のステップ数(ここでは 6 ヶ月先)
    input_patch_len=32,        # 入力パッチ長(チェックポイント対応の固定値)
    output_patch_len=128,      # 出力パッチ長(チェックポイント対応の固定値)
    num_layers=20,             # Transformer の層数(チェックポイント対応の固定値)
    model_dims=1280,           # 隠れ層の次元数(チェックポイント対応の固定値)
    backend="cpu",             # "cpu" / "gpu" / "tpu" から選択
)
tfm.load_from_checkpoint(repo_id="google/timesfm-1.0-200m")

# --- 3. 予測実行 ---
# forecast() は numpy 配列を直接受け取る低レベル API
# forecast_on_df() は DataFrame を渡す高レベル API(複数系列の一括処理に便利)
forecast_input = [history]  # リスト形式で渡す
point_forecast, experimental_quantile_forecast = tfm.forecast(
    inputs=forecast_input,
    freq=[0],  # freq パラメータの詳細は公式リポジトリの README を参照
)

# --- 4. 可視化 ---
future_index = pd.date_range(
    start=df["date"].iloc[-1] + pd.DateOffset(months=1),
    periods=6,
    freq="MS",
)

fig, ax = plt.subplots(figsize=(12, 5))
ax.plot(df["date"].values[-context_len:], history, label="実績", color="steelblue")
ax.plot(future_index, point_forecast[0], label="予測(TimesFM)",
        color="tomato", linestyle="--", marker="o")
ax.set_title("月次売上予測(TimesFM ゼロショット)")
ax.legend()
plt.tight_layout()
plt.savefig("forecast.png", dpi=150)
plt.show()

TimesFm の初期化パラメータのうち、input_patch_len=32 / output_patch_len=128 / num_layers=20 / model_dims=1280 は公式チェックポイント(timesfm-1.0-200m)に対応した固定値です。チェックポイントと不整合な値を渡すとエラーになるため、基本的にはそのまま使います。

実務で調整する余地があるのは context_lenhorizon_len の 2 つです。context_len は長いほど季節性やトレンドを捉えやすくなりますが、手元のデータが短い場合は無理に大きな値を設定せず、実際に持っているデータ点数に合わせます。欠損値が含まれる場合は ffill() や線形補間で埋めてから渡すのが無難です。不規則な時間間隔(例:営業日ベースのデータに休日の欠落がある)は、あらかじめリサンプリングして等間隔に整えておく必要があります。TimesFM 自体は等間隔を前提とした設計です。

forecast()forecast_on_df() の使い分けは単純で、単一系列や numpy 配列で渡したい場合は前者、複数系列を DataFrame で一括処理したい場合は後者が便利です。

実務3シーンへの当てはめと、現時点の限界

需要予測(月次売上)

月次売上の 3〜6 ヶ月先予測は、TimesFM が最も素直にはまるシーンです。過去 24〜36 ヶ月の売上実績を context_len に渡し、horizon_len=3 または 6 を設定するだけで、季節性を暗黙的に考慮した予測値が得られます。

既存の Prophet パイプラインを置き換えるというより、ベースライン予測を瞬時に生成する器として使い、外部変数(キャンペーン・新商品投入)の影響は別途アナリストが補正する——という組み込み方が現実的です。

シフト計画(週次来客数)

週次の来客数データに対して horizon_len=4(4 週先)を設定すれば、翌月のシフト計画の叩き台になる予測値を数秒で生成できます。店舗ごとに系列が分かれている場合は forecast_on_df() で複数系列を一括処理するとスループットが出ます。

フィッティング不要の恩恵が最も出るのがこのパターンです。系列数が数十〜数百になっても処理時間がほぼ線形に増えるだけで、Prophet のように系列ごとに fit() を回す必要がありません。

在庫管理(発注サイクル)

発注リードタイムが 2〜4 週間の商品であれば、週次の出荷実績を入力として horizon_len をリードタイム分に設定し、予測値に安全在庫係数を掛けて発注点を算出するパイプラインが組めます。TimesFM の出力は点予測と実験的な分位数予測の両方を返すので、確率的な在庫モデルと組み合わせる場合は experimental_quantile_forecast の上側分位数を保守的な発注量の根拠として使う方法もあります。

現時点の限界と使いどころの見極め

正直に言うと、TimesFM には現時点でいくつかの制約があります。

最大の制約は多変量・外部変数への非対応です。プロモーション施策・祝日・天候など、売上に明確に影響する共変量をモデルに渡す手段がなく、「外部イベントを織り込んだ予測」が必要なシーンでは Prophet の方が適しています。

長期予測での精度劣化も実務上の注意点です。ホライズンをコンテキスト長に対して大きく取るほど精度は落ちやすくなります。「とりあえず遠い未来まで予測させる」という使い方は避け、用途に応じた現実的なホライズン設定を心がけてください。

ファインチューニングによって自社データへの適合精度を上げることも可能ですが、それは別の話題として改めて扱います。

TimesFM のゼロショット利用が効くのは、系列数が多くフィッティングコストを下げたい場面、外部変数の影響が小さいか別途補正できる場面、そして中期予測を素早くベースライン化したい場面です。逆に、外部変数が予測精度の鍵を握るシーン・超短期予測・データが極端に少ない系列では、Prophet や ARIMA の方が扱いやすいケースが残ります。「乗り換え」ではなく「使い分け」の視点で手元のパイプラインに組み込んでみてください。


株式会社ホコサキは山口県宇部を拠点に、業務システム開発・AI 活用支援・DX 推進に取り組んでいます。TimesFM のような OSS モデルを実務データに適用する際の設計相談や、予測パイプラインの構築支援も対応しています。お気軽にお問い合わせください。

    TimesFMをゼロショットで動かす:Prophet・ARIMAとの使い分けと最小構成コード | 株式会社ホコサキ