基盤モデルと自動異常検出を用いた TimeCopilot による予測パイプラインの構築方法
TimeCopilot を用いた時系列予測パイプラインの構築チュートリアルでは、統計モデルと基盤モデルを比較評価し、LLM エージェントによる自動モデル選択と異常検出の実装方法が示される。
キーポイント
多様なモデルの包括的評価フレームワーク
時系列データ(航空機乗客数および合成データ)を用いて、統計モデル、Prophet、Chronos などの基盤モデルをローリングクロスバリデーションで比較し、最適な予測手法を選定する手順が示される。
LLM エージェントによる自動化と解釈
TimeCopilot の LLM エージェント機能を活用し、データ特性に基づいて自動でモデルを選択し、その予測結果を自然言語で分析回答として生成するワークフローが紹介される。
異常検出と確率的予測の実装
人工的に注入された異常値を検出し、予測区間(信頼区間)を含む確率的な未来トレンドの可視化を行うことで、不確実性を考慮した意思決定を支援する手法が解説される。
ハードウェアに応じたモデル選択と統合
利用可能な GPU の有無に基づいて Chronos モデルのサイズを自動調整し、GPU があれば TimesFM を追加して多様な統計・深層学習モデルを TimeCopilotForecaster で一元管理します。
ローリング交差検証による厳密な評価
3 つのウィンドウにわたるローリング交差検証を実行し、MAE、RMSE、MAPE の各指標で時系列ごとの精度を測定してモデルを比較します。
平均 RMSE によるベストモデルの選定
全時系列における評価指標の平均値を算出したリーダーボードを作成し、最も低い平均 RMSE を持つモデルを最適な予測モデルとして特定します。
確率的予測と可視化の自動化
80% と 95% の信頼区間を含む 12 ヶ月分の確率的予測を生成し、履歴データ、ポイント推定値、不確実性範囲を同時に表示する再利用可能なプロット関数を定義して各時系列に適用します。
影響分析・編集コメントを表示
影響分析
この記事は、時系列予測における「ブラックボックス化」した基盤モデルの実用的な活用方法を提示しており、従来の統計手法と最新 AI をシームレスに統合する標準的なワークフローを確立する上で重要な指針となる。特に LLM エージェントによる自動推論機能は、データサイエンティストの負荷軽減と意思決定の迅速化に寄与し、実務現場での導入障壁を大幅に下げる可能性を秘めている。
編集コメント
時系列予測の分野において、単なるモデル比較を超え、LLM が自律的に分析を行う「エージェント型」アプローチの実装例として非常に示唆に富む記事です。実務での即戦力となるコードと概念が提供されています。
本チュートリアルでは、TimeCopilot を用いてエンドツーエンドの予測ワークフローを構築します。実際の航空会社乗客データを含むパネルデータセットと、異常値を注入した合成季節時系列を用意し、多様な統計モデル、ファウンデーションモデル、およびオプションの GPU ベース予測モデルを評価します。ローリング交差検証と複数の誤差指標を用いて最良のモデルを特定し、予測区間付きの確率的予測を生成し、将来のトレンドを可視化し、異常な観測値を検出します。最後に、予測モデルを選択し、その予測結果をアクセスしやすい分析回答に変換する TimeCopilot のオプション LLM エージェント(大規模言語モデルエージェント)について探ります。
TimeCopilot のインストールと互換性のある NumPy および SciPy バージョンの固定
!pip install -q "timecopilot" "utilsforecast" "matplotlib"
!pip install -q --force-reinstall --no-deps "numpy==1.26.4" "scipy==1.13.1"
print("Setup complete. Restarting the runtime to load clean binaries...")
import IPython
IPython.Application.instance().kernel.do_shutdown(True)
予測環境を準備するために、TimeCopilot、UtilsForecast(ユーティリティ予測)、Matplotlib をインストールします。バイナリ競合を防ぐため、互換性のある NumPy および SciPy のバージョンを強制適用します。その後、Colab ランタイムを再起動して更新されたライブラリが正しく読み込まれるようにします。
AirPassengers データの読み込みと合成異常パネルの構築
必要なライブラリをインポートし、環境を確認して GPU の利用可否を検出します。AirPassengers データセットを読み込み、スパイク(急激な変動)を組み込んだ第 2 の合成季節時系列を作成します。これら 2 つの時系列を結合してパネルデータセットとし、予測ホライズンと月次頻度を設定します。
統計モデル、Prophet モデル、Chronos モデルの構成
異なるブラウザを使用する
from timecopilot.forecaster import TimeCopilotForecaster
from timecopilot.models.stats import AutoARIMA, AutoETS, SeasonalNaive, Theta
from timecopilot.models.prophet import Prophet
from timecopilot.models.foundation.chronos import Chronos
chronos_repo = "amazon/chronos-bolt-small" if HAS_GPU else "amazon/chronos-bolt-tiny"
models = [
SeasonalNaive(), AutoETS(), AutoARIMA(), Theta(), Prophet(),
Chronos(repo_id=chronos_repo, alias="Chronos"),
]
if HAS_GPU:
try:
from timecopilot.models.foundation.timesfm import TimesFM
models.append(TimesFM(repo_id="google/timesfm-2.0-500m-pytorch", alias="TimesFM"))
except Exception as e:
print("Skipping TimesFM:", e)
tcf = TimeCopilotForecaster(models=models)
print("\nModels:", [getattr(m, "alias", type(m).__name__) for m in models])
統計モデル、Prophet モデル、および Chronos モデルの多様なコレクションを構成します。利用可能なハードウェアに応じて Chronos モデルのサイズを選択し、GPU が存在する場合はオプションで TimesFM を含めます。その後、TimeCopilotForecaster を初期化して、すべてのモデルを一貫したインターフェースを通じて管理できるようにします。
ロールイング交差検証の実行と RMSE によるモデルランキング
print("\nRunning cross-validation (slow step: foundation weights download)...")
cv_df = tcf.cross_validation(df=panel, h=H, freq=FREQ, n_windows=3)
print(cv_df.head())
from utilsforecast.evaluation import evaluate
from utilsforecast.losses import mae, rmse, mape
eval_df = evaluate(cv_df.drop(columns=["cutoff"]), metrics=[mae, rmse, mape])
print("\n=== Per-series error (lower = better) ===")
print(eval_df.round(3))
model_cols = [c for c in eval_df.columns if c not in ("unique_id", "metric")]
leaderboard = (eval_df.groupby("metric")[model_cols].mean().T.sort_values("rmse"))
print("\n=== Leaderboard (mean across series) ===")
print(leaderboard.round(3))
best_model = leaderboard.index[0]
print(f"\n>>> Best model by mean RMSE: {best_model}")
We perform rolling cross-validation across three windows to measure each model's forecasting performance. We calculate MAE, RMSE, and MAPE for every series and aggregate the results into a leaderboard. We identify the model with the lowest mean RMSE for subsequent forecasting and visualization.
Generating Probabilistic Forecasts with Prediction Intervals
Copy CodeCopiedUse a different Browser
fcst_df = tcf.forecast(df=panel, h=H, freq=FREQ, level=[80, 95])
print("\nForecast columns:", list(fcst_df.columns))
def plot_series(uid, point_model=best_model):
hist = panel[panel["unique_id"] == uid]; fc = fcst_df[fcst_df["unique_id"] == uid]
plt.figure(figsize=(11, 4)); plt.plot(hist["ds"], hist["y"], color="black", label="history")
if point_model in fc.columns:
plt.plot(fc["ds"], fc[point_model], color="C0", label=f"{point_model} forecast")
lo, hi = f"{point_model}-lo-95", f"{point_model}-hi-95"
if lo in fc.columns and hi in fc.columns:
plt.fill_between(fc["ds"], fc[lo], fc[hi], alpha=0.25, color="C0", label="95% interval")
plt.title(f"{uid} — {point_model}"); plt.legend(); plt.tight_layout(); plt.show()
for uid in panel["unique_id"].unique():
plot_series(uid)
80% および 95% の予測区間を含む、12 ヶ月分の確率的予測(probabilistic forecasts)を生成します。ここでは、履歴値、ポイント予測(point forecasts)、不確実性範囲を表示する再利用可能なプロット関数を定義しています。この関数を各時系列に適用し、観測された履歴と予測される将来の軌跡を比較します。
予測パネル全体における異常検出
Copy CodeCopiedUse a different Browser
print("\nRunning anomaly detection...")
anomalies_df = tcf.detect_anomalies(df=panel, h=H, freq=FREQ, level=99)
anom_cols = [c for c in anomalies_df.columns if c.endswith("-anomaly")]
if anom_cols:
flagged = anomalies_df[anomalies_df[anom_cols].any(axis=1)]
print(f"Flagged points (>=1 model): {len(flagged)}")
print(flagged[["unique_id", "ds", "y"] + anom_cols].head(20).to_string(index=False))
col = f"{best_model}-anomaly"
if col not in anomalies_df.columns: col = anom_cols[0]
sub = anomalies_df[anomalies_df["unique_id"] == "Synthetic"]
pts = sub[sub[col] == True]
plt.figure(figsize=(11, 4)); plt.plot(sub["ds"], sub["y"], color="black", label="value")
plt.scatter(pts["ds"], pts["y"], color="red", zorder=5, label=f"anomaly ({col})")
plt.title("Anomaly detection — Synthetic series"); plt.legend(); plt.tight_layout(); plt.show()
else:
print(anomalies_df.head())
Interpreting Forecasts with the TimeCopilot LLM Agent
Copy CodeCopiedUse a different Browser
from timecopilot import TimeCopilot
if os.environ.get("OPENAI_API_KEY") or os.environ.get("ANTHROPIC_API_KEY"):
llm = "openai:gpt-4o" if os.environ.get("OPENAI_API_KEY") else "anthropic:claude-sonnet-4-5"
tc = TimeCopilot(llm=llm, retries=3)
single = panel[panel["unique_id"] == "AirPassengers"]
result = tc.forecast(df=single, freq=FREQ, h=H,
query="Total air passengers expected over the next 12 months, and which months peak?")
out = result.output
print("\n=== AGENT REPORT ===")
print("Selected model:", out.selected_model)
print("Beats SeasonalNaive:", out.is_better_than_seasonal_naive)
print("Why:", out.reason_for_selection)
print("Answer:", out.user_query_response)
print(result.fcst_df.head())
else:
print("\n[Agent section skipped] No LLM key. Everything above ran key-free.")
print("\nDone.
image")
パネル全体で異常を検出し、フラグ付けされた観測値を合成系列上で可視化します。OpenAI または Anthropic の API キーが利用可能な場合に限り、TimeCopilot LLM エージェントを初期化するオプションがあります。このエージェントを用いてモデルを選択し、SeasonalNaive モデルとの比較評価を行い、実用的な質問に対する予測の解説を行います。
結論
結論として、データ準備からモデル評価、確率的予測、可視化、異常検出、そしてエージェントによる解釈までを一貫して行う統合された TimeCopilot パイプラインを構築しました。従来の統計手法と最新のファウンデーションモデルを、一貫した交差検証フレームワーク内で比較し、客観的な誤差指標に基づいて最もパフォーマンスの高いアプローチを選択しました。また、予測区間を通じて予測の不確実性を定量化し、複数の時系列にわたる異常な観測値も特定しました。自動化された予測とオプションの LLM エージェントを組み合わせることで、単一のワークフロー内で正確な数値予測と明確で意思決定指向の洞察の両方を生成することができました。
ノートブック付きの完全なコードをチェックしてください。また、Twitter でフォローすることもお気軽にどうぞ。150k 人以上が参加する ML サブレディットに参加し、ニュースレターを購読することを忘れないでください。待ってください!Telegram をご利用ですか?今なら Telegram でも私たちに参加できます。
GitHub リポジトリや Hugging Face ページ、製品リリース、ウェビナーなどのプロモーションのためにパートナーシップをご希望の方は、ぜひご連絡ください。
本記事「ファウンデーションモデルと自動化された異常検出を用いた TimeCopilot による予測パイプラインの構築方法」は、MarkTechPost で最初に公開されました。
原文を表示
In this tutorial, we build an end-to-end forecasting workflow with TimeCopilot. We prepare a panel dataset containing real airline passenger data and a synthetic seasonal series with injected anomalies, then evaluate a diverse collection of statistical, foundation, and optional GPU-based forecasting models. We use rolling cross-validation and multiple error metrics to identify the strongest model, generate probabilistic forecasts with prediction intervals, visualize future trends, and detect unusual observations. Finally, we explore TimeCopilot’s optional LLM agent, which selects a forecasting model and translates its predictions into an accessible analytical response.
Installing TimeCopilot and Pinning Compatible NumPy and SciPy Versions
Copy CodeCopiedUse a different Browser
!pip install -q "timecopilot" "utilsforecast" "matplotlib"
!pip install -q --force-reinstall --no-deps "numpy==1.26.4" "scipy==1.13.1"
print("Setup complete. Restarting the runtime to load clean binaries...")
import IPython
IPython.Application.instance().kernel.do_shutdown(True)
We install TimeCopilot, UtilsForecast, and Matplotlib to prepare the forecasting environment. We enforce compatible NumPy and SciPy versions to prevent binary conflicts. We then restart the Colab runtime so the updated libraries load correctly.
Loading AirPassengers Data and Building a Synthetic Anomaly Panel
Copy CodeCopiedUse a different Browser
import os, warnings
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
warnings.filterwarnings("ignore")
pd.set_option("display.width", 160)
pd.set_option("display.max_columns", 30)
print("numpy:", np.__version__)
import scipy; print("scipy:", scipy.__version__)
try:
import torch
HAS_GPU = torch.cuda.is_available()
except Exception:
HAS_GPU = False
print(f"GPU available: {HAS_GPU}")
df = pd.read_csv(
"https://timecopilot.s3.amazonaws.com/public/data/air_passengers.csv",
parse_dates=["ds"],
)
df["unique_id"] = df["unique_id"].astype(str)
rng = np.random.default_rng(7)
dates = df["ds"].unique(); n = len(dates)
synth = pd.DataFrame({
"unique_id": "Synthetic",
"ds": dates,
"y": (np.linspace(50, 250, n)
+ 40 * np.sin(2 * np.pi * np.arange(n) / 12)
+ rng.normal(0, 8, n)).round(2),
})
anomaly_idx = [30, 75, 120]
synth.loc[anomaly_idx, "y"] *= 2.2
panel = pd.concat([df[["unique_id", "ds", "y"]], synth], ignore_index=True)
print("\nPanel shape:", panel.shape)
print(panel.groupby("unique_id")["y"].agg(["count", "mean", "min", "max"]))
H, FREQ = 12, "MS"
We import the required libraries, verify the environment, and detect GPU availability. We load the AirPassengers dataset and create a second synthetic seasonal series with injected spikes. We combine the two series into a panel dataset and set the forecasting horizon and monthly frequency.
Configuring Statistical, Prophet, and Chronos Forecasting Models
Copy CodeCopiedUse a different Browser
from timecopilot.forecaster import TimeCopilotForecaster
from timecopilot.models.stats import AutoARIMA, AutoETS, SeasonalNaive, Theta
from timecopilot.models.prophet import Prophet
from timecopilot.models.foundation.chronos import Chronos
chronos_repo = "amazon/chronos-bolt-small" if HAS_GPU else "amazon/chronos-bolt-tiny"
models = [
SeasonalNaive(), AutoETS(), AutoARIMA(), Theta(), Prophet(),
Chronos(repo_id=chronos_repo, alias="Chronos"),
]
if HAS_GPU:
try:
from timecopilot.models.foundation.timesfm import TimesFM
models.append(TimesFM(repo_id="google/timesfm-2.0-500m-pytorch", alias="TimesFM"))
except Exception as e:
print("Skipping TimesFM:", e)
tcf = TimeCopilotForecaster(models=models)
print("\nModels:", [getattr(m, "alias", type(m).__name__) for m in models])
We configure a diverse collection of statistical, Prophet, and Chronos forecasting models. We select the Chronos model size according to the available hardware and optionally include TimesFM when a GPU is present. We then initialize TimeCopilotForecaster to manage all models through one consistent interface.
Running Rolling Cross-Validation and Ranking Models by RMSE
Copy CodeCopiedUse a different Browser
print("\nRunning cross-validation (slow step: foundation weights download)...")
cv_df = tcf.cross_validation(df=panel, h=H, freq=FREQ, n_windows=3)
print(cv_df.head())
from utilsforecast.evaluation import evaluate
from utilsforecast.losses import mae, rmse, mape
eval_df = evaluate(cv_df.drop(columns=["cutoff"]), metrics=[mae, rmse, mape])
print("\n=== Per-series error (lower = better) ===")
print(eval_df.round(3))
model_cols = [c for c in eval_df.columns if c not in ("unique_id", "metric")]
leaderboard = (eval_df.groupby("metric")[model_cols].mean().T.sort_values("rmse"))
print("\n=== Leaderboard (mean across series) ===")
print(leaderboard.round(3))
best_model = leaderboard.index[0]
print(f"\n>>> Best model by mean RMSE: {best_model}")
We perform rolling cross-validation across three windows to measure each model’s forecasting performance. We calculate MAE, RMSE, and MAPE for every series and aggregate the results into a leaderboard. We identify the model with the lowest mean RMSE for subsequent forecasting and visualization.
Generating Probabilistic Forecasts with Prediction Intervals
Copy CodeCopiedUse a different Browser
fcst_df = tcf.forecast(df=panel, h=H, freq=FREQ, level=[80, 95])
print("\nForecast columns:", list(fcst_df.columns))
def plot_series(uid, point_model=best_model):
hist = panel[panel["unique_id"] == uid]; fc = fcst_df[fcst_df["unique_id"] == uid]
plt.figure(figsize=(11, 4)); plt.plot(hist["ds"], hist["y"], color="black", label="history")
if point_model in fc.columns:
plt.plot(fc["ds"], fc[point_model], color="C0", label=f"{point_model} forecast")
lo, hi = f"{point_model}-lo-95", f"{point_model}-hi-95"
if lo in fc.columns and hi in fc.columns:
plt.fill_between(fc["ds"], fc[lo], fc[hi], alpha=0.25, color="C0", label="95% interval")
plt.title(f"{uid} — {point_model}"); plt.legend(); plt.tight_layout(); plt.show()
for uid in panel["unique_id"].unique():
plot_series(uid)
We generate 12-month probabilistic forecasts with 80% and 95% prediction intervals. We define a reusable plotting function that displays historical values, point forecasts, and uncertainty ranges. We apply this function to each series to compare its observed history with the predicted future trajectory.
Detecting Anomalies Across the Forecasting Panel
Copy CodeCopiedUse a different Browser
print("\nRunning anomaly detection...")
anomalies_df = tcf.detect_anomalies(df=panel, h=H, freq=FREQ, level=99)
anom_cols = [c for c in anomalies_df.columns if c.endswith("-anomaly")]
if anom_cols:
flagged = anomalies_df[anomalies_df[anom_cols].any(axis=1)]
print(f"Flagged points (>=1 model): {len(flagged)}")
print(flagged[["unique_id", "ds", "y"] + anom_cols].head(20).to_string(index=False))
col = f"{best_model}-anomaly"
if col not in anomalies_df.columns: col = anom_cols[0]
sub = anomalies_df[anomalies_df["unique_id"] == "Synthetic"]
pts = sub[sub[col] == True]
plt.figure(figsize=(11, 4)); plt.plot(sub["ds"], sub["y"], color="black", label="value")
plt.scatter(pts["ds"], pts["y"], color="red", zorder=5, label=f"anomaly ({col})")
plt.title("Anomaly detection — Synthetic series"); plt.legend(); plt.tight_layout(); plt.show()
else:
print(anomalies_df.head())
Interpreting Forecasts with the TimeCopilot LLM Agent
Copy CodeCopiedUse a different Browser
from timecopilot import TimeCopilot
if os.environ.get("OPENAI_API_KEY") or os.environ.get("ANTHROPIC_API_KEY"):
llm = "openai:gpt-4o" if os.environ.get("OPENAI_API_KEY") else "anthropic:claude-sonnet-4-5"
tc = TimeCopilot(llm=llm, retries=3)
single = panel[panel["unique_id"] == "AirPassengers"]
result = tc.forecast(df=single, freq=FREQ, h=H,
query="Total air passengers expected over the next 12 months, and which months peak?")
out = result.output
print("\n=== AGENT REPORT ===")
print("Selected model:", out.selected_model)
print("Beats SeasonalNaive:", out.is_better_than_seasonal_naive)
print("Why:", out.reason_for_selection)
print("Answer:", out.user_query_response)
print(result.fcst_df.head())
else:
print("\n[Agent section skipped] No LLM key. Everything above ran key-free.")
print("\nDone.
image")
We detect anomalies across the panel and visualize the flagged observations in the synthetic series. We optionally initialize the TimeCopilot LLM agent when an OpenAI or Anthropic API key is available. We use the agent to select a model, evaluate it against SeasonalNaive, and explain the forecast in response to a practical question.
Conclusion
In conclusion, we created a unified TimeCopilot pipeline that takes us from data preparation to model evaluation, probabilistic forecasting, visualization, anomaly detection, and agent-driven interpretation. We compared traditional statistical methods with modern foundation models within a consistent cross-validation framework and selected the best-performing approach based on objective error metrics. We also quantified forecast uncertainty through prediction intervals and identified abnormal observations across multiple time series. By combining automated forecasting with an optional LLM agent, we produced both accurate numerical predictions and clear, decision-oriented insights within a single workflow.
Check out the Full Codes with Notebook. Also, feel free to follow us on Twitter and don’t forget to join our 150k+ML SubReddit and Subscribe to our Newsletter. Wait! are you on telegram? now you can join us on telegram as well.
Need to partner with us for promoting your GitHub Repo OR Hugging Face Page OR Product Release OR Webinar etc.? Connect with us
The post How to Build a Forecasting Pipeline with TimeCopilot Using Foundation Models and Automated Anomaly Detection appeared first on MarkTechPost.
関連記事
Apple、Siri AI を発表(4 分読)
アップルは、遅れていた「Apple Intelligence」アップデートを発表し、Siri を「Siri AI」として再ブランド化しました。今秋の OS リリースで対話型アシスタントが導入され、オンデバイス基盤モデルに Google の技術が組み込まれるとされています。
Apple、低価格のAIが小規模開発者を惹きつけると賭ける
アップルは、コストを抑えたAI技術を提供することで、小規模な開発者層を自社のエコシステムに引き込む戦略を打ち出している。
Claude を Foundation Models フレームワークに組み込み、Apple プラットフォーム向けインテリジェントアプリを構築する
Anthropic は、自社の AI モデル「Claude」を Apple の Foundation Models フレームワークに統合し、開発者が iOS や macOS 上でローカル実行可能な高機能なインテリジェントアプリを容易に作成できる環境を提供したと発表した。
今日のまとめ
AI日報で今日の重要ニュースをまとめ読み