timesfm-forecasting
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTimesFM Forecasting
TimesFM 预测
Overview
概述
TimesFM (Time Series Foundation Model) is a pretrained decoder-only foundation model
developed by Google Research for time-series forecasting. It works zero-shot — feed it
any univariate time series and it returns point forecasts with calibrated quantile
prediction intervals, no training required.
This skill wraps TimesFM for safe, agent-friendly local inference. It includes a
mandatory preflight system checker that verifies RAM, GPU memory, and disk space
before the model is ever loaded so the agent never crashes a user's machine.
Key numbers: TimesFM 2.5 uses 200M parameters (~800 MB on disk, ~1.5 GB in RAM on CPU, ~1 GB VRAM on GPU). The archived v1/v2 500M-parameter model needs ~32 GB RAM. Always run the system checker first.
TimesFM(Time Series Foundation Model,时间序列基础模型)是谷歌研究院开发的一款预训练的仅解码器基础模型,用于时间序列预测。它支持零样本模式——输入任意单变量时间序列,即可返回带校准分位数预测区间的点预测结果,无需训练。
本技能对TimesFM进行了封装,以实现安全、适配Agent的本地推理。它包含一个强制预飞系统检查器,会在加载模型前验证RAM、GPU内存和磁盘空间,避免Agent导致用户机器崩溃。
关键参数:TimesFM 2.5拥有2亿参数(磁盘占用约800MB,CPU运行时RAM占用约1.5GB,GPU运行时VRAM占用约1GB)。已归档的v1/v2版本为5亿参数模型,需要约32GB RAM。请务必先运行系统检查器。
When to Use This Skill
何时使用本技能
Use this skill when:
- Forecasting any univariate time series (sales, demand, sensor, vitals, price, weather)
- You need zero-shot forecasting without training a custom model
- You want probabilistic forecasts with calibrated prediction intervals (quantiles)
- You have time series of any length (the model handles 1–16,384 context points)
- You need to batch-forecast hundreds or thousands of series efficiently
- You want a foundation model approach instead of hand-tuning ARIMA/ETS parameters
Do not use this skill when:
- You need classical statistical models with coefficient interpretation → use
statsmodels - You need time series classification or clustering → use
aeon - You need multivariate vector autoregression or Granger causality → use
statsmodels - Your data is tabular (not temporal) → use
scikit-learn
Note on Anomaly Detection: TimesFM does not have built-in anomaly detection, but you can use the quantile forecasts as prediction intervals — values outside the 90% CI (q10–q90) are statistically unusual. See thedirectory for a full example.examples/anomaly-detection/
在以下场景使用本技能:
- 对任意单变量时间序列进行预测(销售、需求、传感器、生命体征、价格、天气)
- 需要零样本预测,无需训练自定义模型
- 需要带校准预测区间(分位数)的概率性预测
- 时间序列长度任意(模型支持1–16384个上下文点)
- 需要高效地对数百或数千个序列进行批量预测
- 希望采用基础模型方案,而非手动调优ARIMA/ETS参数
请勿在以下场景使用本技能:
- 需要可解释系数的经典统计模型 → 使用
statsmodels - 需要时间序列分类或聚类 → 使用
aeon - 需要多变量向量自回归或格兰杰因果检验 → 使用
statsmodels - 数据为表格型(非时序型)→ 使用
scikit-learn
异常检测说明:TimesFM没有内置异常检测功能,但可以将分位数预测作为预测区间——超出90%置信区间(q10–q90)的值在统计上属于异常值。完整示例请查看目录。examples/anomaly-detection/
⚠️ Mandatory Preflight: System Requirements Check
⚠️ 强制预飞:系统要求检查
CRITICAL — ALWAYS run the system checker before loading the model for the first time.
bash
python scripts/check_system.pyThis script checks:
- Available RAM — warns if below 4 GB, blocks if below 2 GB
- GPU availability — detects CUDA/MPS devices and VRAM
- Disk space — verifies room for the ~800 MB model download
- Python version — requires 3.10+
- Existing installation — checks if and
timesfmare installedtorch
Note: Model weights are NOT stored in this repository. TimesFM weights (~800 MB) download on-demand from HuggingFace on first use and cache in. The preflight checker ensures sufficient resources before any download begins.~/.cache/huggingface/
mermaid
flowchart TD
accTitle: Preflight System Check
accDescr: Decision flowchart showing the system requirement checks that must pass before loading TimesFM.
start["🚀 Run check_system.py"] --> ram{"RAM ≥ 4 GB?"}
ram -->|"Yes"| gpu{"GPU available?"}
ram -->|"No (2-4 GB)"| warn_ram["⚠️ Warning: tight RAM<br/>CPU-only, small batches"]
ram -->|"No (< 2 GB)"| block["🛑 BLOCKED<br/>Insufficient memory"]
warn_ram --> disk
gpu -->|"CUDA / MPS"| vram{"VRAM ≥ 2 GB?"}
gpu -->|"CPU only"| cpu_ok["✅ CPU mode<br/>Slower but works"]
vram -->|"Yes"| gpu_ok["✅ GPU mode<br/>Fast inference"]
vram -->|"No"| cpu_ok
gpu_ok --> disk{"Disk ≥ 2 GB free?"}
cpu_ok --> disk
disk -->|"Yes"| ready["✅ READY<br/>Safe to load model"]
disk -->|"No"| block_disk["🛑 BLOCKED<br/>Need space for weights"]
classDef ok fill:#dcfce7,stroke:#16a34a,stroke-width:2px,color:#14532d
classDef warn fill:#fef9c3,stroke:#ca8a04,stroke-width:2px,color:#713f12
classDef block fill:#fee2e2,stroke:#dc2626,stroke-width:2px,color:#7f1d1d
classDef neutral fill:#f3f4f6,stroke:#6b7280,stroke-width:2px,color:#1f2937
class ready,gpu_ok,cpu_ok ok
class warn_ram warn
class block,block_disk block
class start,ram,gpu,vram,disk neutral重要提示——首次加载模型前务必运行系统检查器。
bash
python scripts/check_system.py该脚本会检查:
- 可用RAM——低于4GB时发出警告,低于2GB时阻止运行
- GPU可用性——检测CUDA/MPS设备及VRAM
- 磁盘空间——验证是否有足够空间下载约800MB的模型
- Python版本——要求3.10+
- 现有安装情况——检查和
timesfm是否已安装torch
注意:模型权重未存储在本仓库中。TimesFM权重(约800MB)会在首次使用时从HuggingFace按需下载,并缓存到。预飞检查器会在开始下载前确保资源充足。~/.cache/huggingface/
mermaid
flowchart TD
accTitle: Preflight System Check
accDescr: Decision flowchart showing the system requirement checks that must pass before loading TimesFM.
start["🚀 Run check_system.py"] --> ram{"RAM ≥ 4 GB?"}
ram -->|"Yes"| gpu{"GPU available?"}
ram -->|"No (2-4 GB)"| warn_ram["⚠️ Warning: tight RAM<br/>CPU-only, small batches"]
ram -->|"No (< 2 GB)"| block["🛑 BLOCKED<br/>Insufficient memory"]
warn_ram --> disk
gpu -->|"CUDA / MPS"| vram{"VRAM ≥ 2 GB?"}
gpu -->|"CPU only"| cpu_ok["✅ CPU mode<br/>Slower but works"]
vram -->|"Yes"| gpu_ok["✅ GPU mode<br/>Fast inference"]
vram -->|"No"| cpu_ok
gpu_ok --> disk{"Disk ≥ 2 GB free?"}
cpu_ok --> disk
disk -->|"Yes"| ready["✅ READY<br/>Safe to load model"]
disk -->|"No"| block_disk["🛑 BLOCKED<br/>Need space for weights"]
classDef ok fill:#dcfce7,stroke:#16a34a,stroke-width:2px,color:#14532d
classDef warn fill:#fef9c3,stroke:#ca8a04,stroke-width:2px,color:#713f12
classDef block fill:#fee2e2,stroke:#dc2626,stroke-width:2px,color:#7f1d1d
classDef neutral fill:#f3f4f6,stroke:#6b7280,stroke-width:2px,color:#1f2937
class ready,gpu_ok,cpu_ok ok
class warn_ram warn
class block,block_disk block
class start,ram,gpu,vram,disk neutralHardware Requirements by Model Version
不同模型版本的硬件要求
| Model | Parameters | RAM (CPU) | VRAM (GPU) | Disk | Context |
|---|---|---|---|---|---|
| TimesFM 2.5 (recommended) | 200M | ≥ 4 GB | ≥ 2 GB | ~800 MB | up to 16,384 |
| TimesFM 2.0 (archived) | 500M | ≥ 16 GB | ≥ 8 GB | ~2 GB | up to 2,048 |
| TimesFM 1.0 (archived) | 200M | ≥ 8 GB | ≥ 4 GB | ~800 MB | up to 2,048 |
Recommendation: Always use TimesFM 2.5 unless you have a specific reason to use an older checkpoint. It is smaller, faster, and supports 8× longer context.
| 模型 | 参数数量 | CPU运行RAM | GPU运行VRAM | 磁盘占用 | 上下文长度 |
|---|---|---|---|---|---|
| TimesFM 2.5(推荐) | 200M | ≥ 4 GB | ≥ 2 GB | ~800 MB | 最高16,384 |
| TimesFM 2.0(已归档) | 500M | ≥ 16 GB | ≥ 8 GB | ~2 GB | 最高2,048 |
| TimesFM 1.0(已归档) | 200M | ≥ 8 GB | ≥ 4 GB | ~800 MB | 最高2,048 |
建议:除非有特殊理由使用旧版本,否则始终使用TimesFM 2.5。它体积更小、速度更快,且支持8倍长的上下文。
🔧 Installation
🔧 安装步骤
Step 1: Verify System (always first)
步骤1:验证系统(始终第一步)
bash
python scripts/check_system.pybash
python scripts/check_system.pyStep 2: Install TimesFM
步骤2:安装TimesFM
bash
undefinedbash
undefinedUsing uv (recommended by this repo)
使用uv(本仓库推荐方式)
uv pip install timesfm[torch]
uv pip install timesfm[torch]
Or using pip
或使用pip
pip install timesfm[torch]
pip install timesfm[torch]
For JAX/Flax backend (faster on TPU/GPU)
用于JAX/Flax后端(在TPU/GPU上更快)
uv pip install timesfm[flax]
undefineduv pip install timesfm[flax]
undefinedStep 3: Install PyTorch for Your Hardware
步骤3:为你的硬件安装PyTorch
bash
undefinedbash
undefinedCUDA 12.1 (NVIDIA GPU)
CUDA 12.1(NVIDIA GPU)
pip install torch>=2.0.0 --index-url https://download.pytorch.org/whl/cu121
pip install torch>=2.0.0 --index-url https://download.pytorch.org/whl/cu121
CPU only
仅CPU
pip install torch>=2.0.0 --index-url https://download.pytorch.org/whl/cpu
pip install torch>=2.0.0 --index-url https://download.pytorch.org/whl/cpu
Apple Silicon (MPS)
Apple Silicon(MPS)
pip install torch>=2.0.0 # MPS support is built-in
undefinedpip install torch>=2.0.0 # MPS支持已内置
undefinedStep 4: Verify Installation
步骤4:验证安装
python
import timesfm
import numpy as np
print(f"TimesFM version: {timesfm.__version__}")
print("Installation OK")python
import timesfm
import numpy as np
print(f"TimesFM version: {timesfm.__version__}")
print("Installation OK")🎯 Quick Start
🎯 快速开始
Minimal Example (5 Lines)
最简示例(5行代码)
python
import torch, numpy as np, timesfm
torch.set_float32_matmul_precision("high")
model = timesfm.TimesFM_2p5_200M_torch.from_pretrained(
"google/timesfm-2.5-200m-pytorch"
)
model.compile(timesfm.ForecastConfig(
max_context=1024, max_horizon=256, normalize_inputs=True,
use_continuous_quantile_head=True, force_flip_invariance=True,
infer_is_positive=True, fix_quantile_crossing=True,
))
point, quantiles = model.forecast(horizon=24, inputs=[
np.sin(np.linspace(0, 20, 200)), # any 1-D array
])python
import torch, numpy as np, timesfm
torch.set_float32_matmul_precision("high")
model = timesfm.TimesFM_2p5_200M_torch.from_pretrained(
"google/timesfm-2.5-200m-pytorch"
)
model.compile(timesfm.ForecastConfig(
max_context=1024, max_horizon=256, normalize_inputs=True,
use_continuous_quantile_head=True, force_flip_invariance=True,
infer_is_positive=True, fix_quantile_crossing=True,
))
point, quantiles = model.forecast(horizon=24, inputs=[
np.sin(np.linspace(0, 20, 200)), # 任意一维数组
])point.shape == (1, 24) — median forecast
point.shape == (1, 24) — 中位数预测
quantiles.shape == (1, 24, 10) — 10th–90th percentile bands
quantiles.shape == (1, 24, 10) — 10%–90%分位数区间
undefinedundefinedForecast from CSV
从CSV文件进行预测
python
import pandas as pd, numpy as np
df = pd.read_csv("monthly_sales.csv", parse_dates=["date"], index_col="date")python
import pandas as pd, numpy as np
df = pd.read_csv("monthly_sales.csv", parse_dates=["date"], index_col="date")Convert each column to a list of arrays
将每列转换为数组列表
inputs = [df[col].dropna().values.astype(np.float32) for col in df.columns]
point, quantiles = model.forecast(horizon=12, inputs=inputs)
inputs = [df[col].dropna().values.astype(np.float32) for col in df.columns]
point, quantiles = model.forecast(horizon=12, inputs=inputs)
Build a results DataFrame
构建结果DataFrame
for i, col in enumerate(df.columns):
last_date = df[col].dropna().index[-1]
future_dates = pd.date_range(last_date, periods=13, freq="MS")[1:]
forecast_df = pd.DataFrame({
"date": future_dates,
"forecast": point[i],
"lower_80": quantiles[i, :, 2], # 20th percentile
"upper_80": quantiles[i, :, 8], # 80th percentile
})
print(f"\n--- {col} ---")
print(forecast_df.to_string(index=False))
undefinedfor i, col in enumerate(df.columns):
last_date = df[col].dropna().index[-1]
future_dates = pd.date_range(last_date, periods=13, freq="MS")[1:]
forecast_df = pd.DataFrame({
"date": future_dates,
"forecast": point[i],
"lower_80": quantiles[i, :, 2], # 20%分位数
"upper_80": quantiles[i, :, 8], # 80%分位数
})
print(f"\n--- {col} ---")
print(forecast_df.to_string(index=False))
undefinedForecast with Covariates (XReg)
带协变量的预测(XReg)
TimesFM 2.5+ supports exogenous variables through . Requires .
forecast_with_covariates()timesfm[xreg]python
undefinedTimesFM 2.5+支持通过使用外生变量,需要安装。
forecast_with_covariates()timesfm[xreg]python
undefinedRequires: uv pip install timesfm[xreg]
需要先安装:uv pip install timesfm[xreg]
point, quantiles = model.forecast_with_covariates(
inputs=inputs,
dynamic_numerical_covariates={"price": price_arrays},
dynamic_categorical_covariates={"holiday": holiday_arrays},
static_categorical_covariates={"region": region_labels},
xreg_mode="xreg + timesfm", # or "timesfm + xreg"
)
| Covariate Type | Description | Example |
| -------------- | ----------- | ------- |
| `dynamic_numerical` | Time-varying numeric | price, temperature, promotion spend |
| `dynamic_categorical` | Time-varying categorical | holiday flag, day of week |
| `static_numerical` | Per-series numeric | store size, account age |
| `static_categorical` | Per-series categorical | store type, region, product category |
**XReg Modes:**
- `"xreg + timesfm"` (default): TimesFM forecasts first, then XReg adjusts residuals
- `"timesfm + xreg"`: XReg fits first, then TimesFM forecasts residuals
> See `examples/covariates-forecasting/` for a complete example with synthetic retail data.point, quantiles = model.forecast_with_covariates(
inputs=inputs,
dynamic_numerical_covariates={"price": price_arrays},
dynamic_categorical_covariates={"holiday": holiday_arrays},
static_categorical_covariates={"region": region_labels},
xreg_mode="xreg + timesfm", # 或 "timesfm + xreg"
)
| 协变量类型 | 描述 | 示例 |
| -------------- | ----------- | ------- |
| `dynamic_numerical` | 时变数值型 | 价格、温度、促销支出 |
| `dynamic_categorical` | 时变类别型 | 节假日标记、星期几 |
| `static_numerical` | 单序列数值型 | 门店规模、账户时长 |
| `static_categorical` | 单序列类别型 | 门店类型、地区、产品类别 |
**XReg模式:**
- `"xreg + timesfm"`(默认):先由TimesFM进行预测,再由XReg调整残差
- `"timesfm + xreg"`:先由XReg拟合,再由TimesFM预测残差
> 完整示例请查看`examples/covariates-forecasting/`,包含合成零售数据。Anomaly Detection (via Quantile Intervals)
异常检测(通过分位数区间)
TimesFM does not have built-in anomaly detection, but the quantile forecasts naturally provide
prediction intervals that can detect anomalies:
python
point, q = model.forecast(horizon=H, inputs=[values])TimesFM没有内置异常检测功能,但分位数预测天然提供了可用于检测异常的预测区间:
python
point, q = model.forecast(horizon=H, inputs=[values])90% prediction interval
90%预测区间
lower_90 = q[0, :, 1] # 10th percentile
upper_90 = q[0, :, 9] # 90th percentile
lower_90 = q[0, :, 1] # 10%分位数
upper_90 = q[0, :, 9] # 90%分位数
Detect anomalies: values outside the 90% CI
检测异常:超出90%置信区间的值
actual = test_values # your holdout data
anomalies = (actual < lower_90) | (actual > upper_90)
actual = test_values # 你的留存数据
anomalies = (actual < lower_90) | (actual > upper_90)
Severity levels
严重程度等级
is_warning = (actual < q[0, :, 2]) | (actual > q[0, :, 8]) # outside 80% CI
is_critical = anomalies # outside 90% CI
| Severity | Condition | Interpretation |
| -------- | --------- | -------------- |
| **Normal** | Inside 80% CI | Expected behavior |
| **Warning** | Outside 80% CI | Unusual but possible |
| **Critical** | Outside 90% CI | Statistically rare (< 10% probability) |
> See `examples/anomaly-detection/` for a complete example with visualization.
```pythonis_warning = (actual < q[0, :, 2]) | (actual > q[0, :, 8]) # 超出80%置信区间
is_critical = anomalies # 超出90%置信区间
| 严重程度 | 条件 | 解释 |
| -------- | --------- | -------------- |
| **正常** | 在80%置信区间内 | 预期行为 |
| **警告** | 超出80%置信区间 | 异常但可能发生 |
| **严重** | 超出90%置信区间 | 统计上罕见(概率<10%) |
> 完整示例及可视化请查看`examples/anomaly-detection/`。
```pythonRequires: uv pip install timesfm[xreg]
需要先安装:uv pip install timesfm[xreg]
point, quantiles = model.forecast_with_covariates(
inputs=inputs,
dynamic_numerical_covariates={"temperature": temp_arrays},
dynamic_categorical_covariates={"day_of_week": dow_arrays},
static_categorical_covariates={"region": region_labels},
xreg_mode="xreg + timesfm", # or "timesfm + xreg"
)
undefinedpoint, quantiles = model.forecast_with_covariates(
inputs=inputs,
dynamic_numerical_covariates={"temperature": temp_arrays},
dynamic_categorical_covariates={"day_of_week": dow_arrays},
static_categorical_covariates={"region": region_labels},
xreg_mode="xreg + timesfm", # 或 "timesfm + xreg"
)
undefined📊 Understanding the Output
📊 理解输出结果
Quantile Forecast Structure
分位数预测结构
TimesFM returns :
(point_forecast, quantile_forecast)- : shape
point_forecast— the median (0.5 quantile)(batch, horizon) - : shape
quantile_forecast— ten slices:(batch, horizon, 10)
| Index | Quantile | Use |
|---|---|---|
| 0 | Mean | Average prediction |
| 1 | 0.1 | Lower bound of 80% PI |
| 2 | 0.2 | Lower bound of 60% PI |
| 3 | 0.3 | — |
| 4 | 0.4 | — |
| 5 | 0.5 | Median (= |
| 6 | 0.6 | — |
| 7 | 0.7 | — |
| 8 | 0.8 | Upper bound of 60% PI |
| 9 | 0.9 | Upper bound of 80% PI |
TimesFM返回:
(point_forecast, quantile_forecast)- :形状为
point_forecast——中位数(0.5分位数)(batch, horizon) - :形状为
quantile_forecast——包含10个切片:(batch, horizon, 10)
| 索引 | 分位数 | 用途 |
|---|---|---|
| 0 | 均值 | 平均预测值 |
| 1 | 0.1 | 80%预测区间下限 |
| 2 | 0.2 | 60%预测区间下限 |
| 3 | 0.3 | — |
| 4 | 0.4 | — |
| 5 | 0.5 | 中位数(与 |
| 6 | 0.6 | — |
| 7 | 0.7 | — |
| 8 | 0.8 | 60%预测区间上限 |
| 9 | 0.9 | 80%预测区间上限 |
Extracting Prediction Intervals
提取预测区间
python
point, q = model.forecast(horizon=H, inputs=data)python
point, q = model.forecast(horizon=H, inputs=data)80% prediction interval (most common)
80%预测区间(最常用)
lower_80 = q[:, :, 1] # 10th percentile
upper_80 = q[:, :, 9] # 90th percentile
lower_80 = q[:, :, 1] # 10%分位数
upper_80 = q[:, :, 9] # 90%分位数
60% prediction interval (tighter)
60%预测区间(更窄)
lower_60 = q[:, :, 2] # 20th percentile
upper_60 = q[:, :, 8] # 80th percentile
lower_60 = q[:, :, 2] # 20%分位数
upper_60 = q[:, :, 8] # 80%分位数
Median (same as point forecast)
中位数(与点预测一致)
median = q[:, :, 5]
```mermaid
flowchart LR
accTitle: Quantile Forecast Anatomy
accDescr: Diagram showing how the 10-element quantile vector maps to prediction intervals.
input["📈 Input Series<br/>1-D array"] --> model["🤖 TimesFM<br/>compile + forecast"]
model --> point["📍 Point Forecast<br/>(batch, horizon)"]
model --> quant["📊 Quantile Forecast<br/>(batch, horizon, 10)"]
quant --> pi80["80% PI<br/>q[:,:,1] – q[:,:,9]"]
quant --> pi60["60% PI<br/>q[:,:,2] – q[:,:,8]"]
quant --> median["Median<br/>q[:,:,5]"]
classDef data fill:#dbeafe,stroke:#2563eb,stroke-width:2px,color:#1e3a5f
classDef model fill:#f3e8ff,stroke:#9333ea,stroke-width:2px,color:#581c87
classDef output fill:#dcfce7,stroke:#16a34a,stroke-width:2px,color:#14532d
class input data
class model model
class point,quant,pi80,pi60,median outputmedian = q[:, :, 5]
```mermaid
flowchart LR
accTitle: Quantile Forecast Anatomy
accDescr: Diagram showing how the 10-element quantile vector maps to prediction intervals.
input["📈 Input Series<br/>1-D array"] --> model["🤖 TimesFM<br/>compile + forecast"]
model --> point["📍 Point Forecast<br/>(batch, horizon)"]
model --> quant["📊 Quantile Forecast<br/>(batch, horizon, 10)"]
quant --> pi80["80% PI<br/>q[:,:,1] – q[:,:,9]"]
quant --> pi60["60% PI<br/>q[:,:,2] – q[:,:,8]"]
quant --> median["Median<br/>q[:,:,5]"]
classDef data fill:#dbeafe,stroke:#2563eb,stroke-width:2px,color:#1e3a5f
classDef model fill:#f3e8ff,stroke:#9333ea,stroke-width:2px,color:#581c87
classDef output fill:#dcfce7,stroke:#16a34a,stroke-width:2px,color:#14532d
class input data
class model model
class point,quant,pi80,pi60,median output🔧 ForecastConfig Reference
🔧 ForecastConfig参考
All forecasting behavior is controlled by :
timesfm.ForecastConfigpython
timesfm.ForecastConfig(
max_context=1024, # Max context window (truncates longer series)
max_horizon=256, # Max forecast horizon
normalize_inputs=True, # Normalize inputs (RECOMMENDED for stability)
per_core_batch_size=32, # Batch size per device (tune for memory)
use_continuous_quantile_head=True, # Better quantile accuracy for long horizons
force_flip_invariance=True, # Ensures f(-x) = -f(x) (mathematical consistency)
infer_is_positive=True, # Clamp forecasts ≥ 0 when all inputs > 0
fix_quantile_crossing=True, # Ensure q10 ≤ q20 ≤ ... ≤ q90
return_backcast=False, # Return backcast (for covariate workflows)
)| Parameter | Default | When to Change |
|---|---|---|
| 0 | Set to match your longest historical window (e.g., 512, 1024, 4096) |
| 0 | Set to your maximum forecast length |
| False | Always set True — prevents scale-dependent instability |
| 1 | Increase for throughput; decrease if OOM |
| False | Set True for calibrated prediction intervals |
| True | Keep True unless profiling shows it hurts |
| True | Set False for series that can be negative (temperature, returns) |
| False | Set True to guarantee monotonic quantiles |
所有预测行为由控制:
timesfm.ForecastConfigpython
timesfm.ForecastConfig(
max_context=1024, # 最大上下文窗口(截断更长的序列)
max_horizon=256, # 最大预测时长
normalize_inputs=True, # 归一化输入(为了稳定性,推荐开启)
per_core_batch_size=32, # 每个设备的批量大小(根据内存调整)
use_continuous_quantile_head=True, # 长时长预测时提升分位数精度
force_flip_invariance=True, # 确保f(-x) = -f(x)(数学一致性)
infer_is_positive=True, # 当所有输入>0时,将预测值限制为≥0
fix_quantile_crossing=True, # 确保q10 ≤ q20 ≤ ... ≤ q90
return_backcast=False, # 返回反向预测(用于协变量工作流)
)| 参数 | 默认值 | 何时修改 |
|---|---|---|
| 0 | 设置为匹配你的最长历史窗口(例如512、1024、4096) |
| 0 | 设置为你的最大预测长度 |
| False | 始终设为True——避免依赖尺度的不稳定性 |
| 1 | 为了提升吞吐量可增大;出现内存不足时减小 |
| False | 设为True以获得校准后的预测区间 |
| True | 除非性能分析显示有负面影响,否则保持True |
| True | 对于可能为负的序列(温度、收益)设为False |
| False | 设为True以保证分位数单调递增 |
📋 Common Workflows
📋 常见工作流
Workflow 1: Single Series Forecast
工作流1:单序列预测
mermaid
flowchart TD
accTitle: Single Series Forecast Workflow
accDescr: Step-by-step workflow for forecasting a single time series with system checking.
check["1. Run check_system.py"] --> load["2. Load model<br/>from_pretrained()"]
load --> compile["3. Compile with ForecastConfig"]
compile --> prep["4. Prepare data<br/>pd.read_csv → np.array"]
prep --> forecast["5. model.forecast()<br/>horizon=N"]
forecast --> extract["6. Extract point + PI"]
extract --> plot["7. Plot or export results"]
classDef step fill:#f3f4f6,stroke:#6b7280,stroke-width:2px,color:#1f2937
class check,load,compile,prep,forecast,extract,plot steppython
import torch, numpy as np, pandas as pd, timesfmmermaid
flowchart TD
accTitle: Single Series Forecast Workflow
accDescr: Step-by-step workflow for forecasting a single time series with system checking.
check["1. Run check_system.py"] --> load["2. Load model<br/>from_pretrained()"]
load --> compile["3. Compile with ForecastConfig"]
compile --> prep["4. Prepare data<br/>pd.read_csv → np.array"]
prep --> forecast["5. model.forecast()<br/>horizon=N"]
forecast --> extract["6. Extract point + PI"]
extract --> plot["7. Plot or export results"]
classDef step fill:#f3f4f6,stroke:#6b7280,stroke-width:2px,color:#1f2937
class check,load,compile,prep,forecast,extract,plot steppython
import torch, numpy as np, pandas as pd, timesfm1. System check (run once)
1. 系统检查(运行一次)
python scripts/check_system.py
python scripts/check_system.py
2-3. Load and compile
2-3. 加载并编译模型
torch.set_float32_matmul_precision("high")
model = timesfm.TimesFM_2p5_200M_torch.from_pretrained(
"google/timesfm-2.5-200m-pytorch"
)
model.compile(timesfm.ForecastConfig(
max_context=512, max_horizon=52, normalize_inputs=True,
use_continuous_quantile_head=True, fix_quantile_crossing=True,
))
torch.set_float32_matmul_precision("high")
model = timesfm.TimesFM_2p5_200M_torch.from_pretrained(
"google/timesfm-2.5-200m-pytorch"
)
model.compile(timesfm.ForecastConfig(
max_context=512, max_horizon=52, normalize_inputs=True,
use_continuous_quantile_head=True, fix_quantile_crossing=True,
))
4. Prepare data
4. 准备数据
df = pd.read_csv("weekly_demand.csv", parse_dates=["week"])
values = df["demand"].values.astype(np.float32)
df = pd.read_csv("weekly_demand.csv", parse_dates=["week"])
values = df["demand"].values.astype(np.float32)
5. Forecast
5. 进行预测
point, quantiles = model.forecast(horizon=52, inputs=[values])
point, quantiles = model.forecast(horizon=52, inputs=[values])
6. Extract prediction intervals
6. 提取预测区间
forecast_df = pd.DataFrame({
"forecast": point[0],
"lower_80": quantiles[0, :, 1],
"upper_80": quantiles[0, :, 9],
})
forecast_df = pd.DataFrame({
"forecast": point[0],
"lower_80": quantiles[0, :, 1],
"upper_80": quantiles[0, :, 9],
})
7. Plot
7. 绘图
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(12, 5))
ax.plot(values[-104:], label="Historical")
x_fc = range(len(values[-104:]), len(values[-104:]) + 52)
ax.plot(x_fc, forecast_df["forecast"], label="Forecast", color="tab:orange")
ax.fill_between(x_fc, forecast_df["lower_80"], forecast_df["upper_80"],
alpha=0.2, color="tab:orange", label="80% PI")
ax.legend()
ax.set_title("52-Week Demand Forecast")
plt.tight_layout()
plt.savefig("forecast.png", dpi=150)
print("Saved forecast.png")
undefinedimport matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(12, 5))
ax.plot(values[-104:], label="历史数据")
x_fc = range(len(values[-104:]), len(values[-104:]) + 52)
ax.plot(x_fc, forecast_df["forecast"], label="预测值", color="tab:orange")
ax.fill_between(x_fc, forecast_df["lower_80"], forecast_df["upper_80"],
alpha=0.2, color="tab:orange", label="80%预测区间")
ax.legend()
ax.set_title("52周需求预测")
plt.tight_layout()
plt.savefig("forecast.png", dpi=150)
print("已保存forecast.png")
undefinedWorkflow 2: Batch Forecasting (Many Series)
工作流2:批量预测(多个序列)
python
import pandas as pd, numpy as nppython
import pandas as pd, numpy as npLoad wide-format CSV (one column per series)
加载宽格式CSV(每列对应一个序列)
df = pd.read_csv("all_stores.csv", parse_dates=["date"], index_col="date")
inputs = [df[col].dropna().values.astype(np.float32) for col in df.columns]
df = pd.read_csv("all_stores.csv", parse_dates=["date"], index_col="date")
inputs = [df[col].dropna().values.astype(np.float32) for col in df.columns]
Forecast all series at once (batched internally)
一次性预测所有序列(内部批量处理)
point, quantiles = model.forecast(horizon=30, inputs=inputs)
point, quantiles = model.forecast(horizon=30, inputs=inputs)
Collect results
收集结果
results = {}
for i, col in enumerate(df.columns):
results[col] = {
"forecast": point[i].tolist(),
"lower_80": quantiles[i, :, 1].tolist(),
"upper_80": quantiles[i, :, 9].tolist(),
}
results = {}
for i, col in enumerate(df.columns):
results[col] = {
"forecast": point[i].tolist(),
"lower_80": quantiles[i, :, 1].tolist(),
"upper_80": quantiles[i, :, 9].tolist(),
}
Export
导出结果
import json
with open("batch_forecasts.json", "w") as f:
json.dump(results, f, indent=2)
print(f"Forecasted {len(results)} series → batch_forecasts.json")
undefinedimport json
with open("batch_forecasts.json", "w") as f:
json.dump(results, f, indent=2)
print(f"已完成{len(results)}个序列的预测 → batch_forecasts.json")
undefinedWorkflow 3: Evaluate Forecast Accuracy
工作流3:评估预测精度
python
import numpy as nppython
import numpy as npHold out the last H points for evaluation
留存最后H个点用于评估
H = 24
train = values[:-H]
actual = values[-H:]
point, quantiles = model.forecast(horizon=H, inputs=[train])
pred = point[0]
H = 24
train = values[:-H]
actual = values[-H:]
point, quantiles = model.forecast(horizon=H, inputs=[train])
pred = point[0]
Metrics
评估指标
mae = np.mean(np.abs(actual - pred))
rmse = np.sqrt(np.mean((actual - pred) ** 2))
mape = np.mean(np.abs((actual - pred) / actual)) * 100
mae = np.mean(np.abs(actual - pred))
rmse = np.sqrt(np.mean((actual - pred) ** 2))
mape = np.mean(np.abs((actual - pred) / actual)) * 100
Prediction interval coverage
预测区间覆盖率
lower = quantiles[0, :, 1]
upper = quantiles[0, :, 9]
coverage = np.mean((actual >= lower) & (actual <= upper)) * 100
print(f"MAE: {mae:.2f}")
print(f"RMSE: {rmse:.2f}")
print(f"MAPE: {mape:.1f}%")
print(f"80% PI Coverage: {coverage:.1f}% (target: 80%)")
undefinedlower = quantiles[0, :, 1]
upper = quantiles[0, :, 9]
coverage = np.mean((actual >= lower) & (actual <= upper)) * 100
print(f"MAE: {mae:.2f}")
print(f"RMSE: {rmse:.2f}")
print(f"MAPE: {mape:.1f}%")
print(f"80%预测区间覆盖率: {coverage:.1f}%(目标值: 80%)")
undefined⚙️ Performance Tuning
⚙️ 性能调优
GPU Acceleration
GPU加速
python
import torchpython
import torchCheck GPU availability
检查GPU可用性
if torch.cuda.is_available():
print(f"GPU: {torch.cuda.get_device_name(0)}")
print(f"VRAM: {torch.cuda.get_device_properties(0).total_mem / 1e9:.1f} GB")
elif hasattr(torch.backends, "mps") and torch.backends.mps.is_available():
print("Apple Silicon MPS available")
else:
print("CPU only — inference will be slower but still works")
if torch.cuda.is_available():
print(f"GPU: {torch.cuda.get_device_name(0)}")
print(f"VRAM: {torch.cuda.get_device_properties(0).total_mem / 1e9:.1f} GB")
elif hasattr(torch.backends, "mps") and torch.backends.mps.is_available():
print("Apple Silicon MPS可用")
else:
print("仅使用CPU——推理速度较慢但仍可运行")
Always set this for Ampere+ GPUs (A100, RTX 3090, etc.)
对于Ampere+ GPU(A100、RTX 3090等),请始终设置此项
torch.set_float32_matmul_precision("high")
undefinedtorch.set_float32_matmul_precision("high")
undefinedBatch Size Tuning
批量大小调优
python
undefinedpython
undefinedStart conservative, increase until OOM
从保守值开始,逐步增大直到出现内存不足
GPU with 8 GB VRAM: per_core_batch_size=64
8GB VRAM的GPU: per_core_batch_size=64
GPU with 16 GB VRAM: per_core_batch_size=128
16GB VRAM的GPU: per_core_batch_size=128
GPU with 24 GB VRAM: per_core_batch_size=256
24GB VRAM的GPU: per_core_batch_size=256
CPU with 8 GB RAM: per_core_batch_size=8
8GB RAM的CPU: per_core_batch_size=8
CPU with 16 GB RAM: per_core_batch_size=32
16GB RAM的CPU: per_core_batch_size=32
CPU with 32 GB RAM: per_core_batch_size=64
32GB RAM的CPU: per_core_batch_size=64
model.compile(timesfm.ForecastConfig(
max_context=1024,
max_horizon=256,
per_core_batch_size=32, # <-- tune this
normalize_inputs=True,
use_continuous_quantile_head=True,
fix_quantile_crossing=True,
))
undefinedmodel.compile(timesfm.ForecastConfig(
max_context=1024,
max_horizon=256,
per_core_batch_size=32, # <-- 调整此参数
normalize_inputs=True,
use_continuous_quantile_head=True,
fix_quantile_crossing=True,
))
undefinedMemory-Constrained Environments
内存受限环境
python
import gc, torchpython
import gc, torchForce garbage collection before loading
加载模型前强制垃圾回收
gc.collect()
if torch.cuda.is_available():
torch.cuda.empty_cache()
gc.collect()
if torch.cuda.is_available():
torch.cuda.empty_cache()
Load model
加载模型
model = timesfm.TimesFM_2p5_200M_torch.from_pretrained(
"google/timesfm-2.5-200m-pytorch"
)
model = timesfm.TimesFM_2p5_200M_torch.from_pretrained(
"google/timesfm-2.5-200m-pytorch"
)
Use small batch size on low-memory machines
在低内存机器上使用小批量
model.compile(timesfm.ForecastConfig(
max_context=512, # Reduce context if needed
max_horizon=128, # Reduce horizon if needed
per_core_batch_size=4, # Small batches
normalize_inputs=True,
use_continuous_quantile_head=True,
fix_quantile_crossing=True,
))
model.compile(timesfm.ForecastConfig(
max_context=512, # 必要时减小上下文长度
max_horizon=128, # 必要时减小预测时长
per_core_batch_size=4, # 小批量
normalize_inputs=True,
use_continuous_quantile_head=True,
fix_quantile_crossing=True,
))
Process series in chunks to avoid OOM
分块处理序列以避免内存不足
CHUNK = 50
all_results = []
for i in range(0, len(inputs), CHUNK):
chunk = inputs[i:i+CHUNK]
p, q = model.forecast(horizon=H, inputs=chunk)
all_results.append((p, q))
gc.collect() # Clean up between chunks
undefinedCHUNK = 50
all_results = []
for i in range(0, len(inputs), CHUNK):
chunk = inputs[i:i+CHUNK]
p, q = model.forecast(horizon=H, inputs=chunk)
all_results.append((p, q))
gc.collect() # 分块之间清理内存
undefined🔗 Integration with Other Skills
🔗 与其他技能集成
With statsmodels
statsmodels与statsmodels
集成
statsmodelsUse for classical models (ARIMA, SARIMAX) as a comparison baseline:
statsmodelspython
undefined使用的经典模型(ARIMA、SARIMAX)作为对比基准:
statsmodelspython
undefinedTimesFM forecast
TimesFM预测结果
tfm_point, tfm_q = model.forecast(horizon=H, inputs=[values])
tfm_point, tfm_q = model.forecast(horizon=H, inputs=[values])
statsmodels ARIMA forecast
statsmodels ARIMA预测结果
from statsmodels.tsa.arima.model import ARIMA
arima = ARIMA(values, order=(1,1,1)).fit()
arima_forecast = arima.forecast(steps=H)
from statsmodels.tsa.arima.model import ARIMA
arima = ARIMA(values, order=(1,1,1)).fit()
arima_forecast = arima.forecast(steps=H)
Compare
对比结果
print(f"TimesFM MAE: {np.mean(np.abs(actual - tfm_point[0])):.2f}")
print(f"ARIMA MAE: {np.mean(np.abs(actual - arima_forecast)):.2f}")
undefinedprint(f"TimesFM MAE: {np.mean(np.abs(actual - tfm_point[0])):.2f}")
print(f"ARIMA MAE: {np.mean(np.abs(actual - arima_forecast)):.2f}")
undefinedWith matplotlib
/ scientific-visualization
matplotlibscientific-visualization与matplotlib
/ scientific-visualization
集成
matplotlibscientific-visualizationPlot forecasts with prediction intervals as publication-quality figures.
将预测结果和预测区间绘制成可用于发表的高质量图表。
With exploratory-data-analysis
exploratory-data-analysis与exploratory-data-analysis
集成
exploratory-data-analysisRun EDA on the time series before forecasting to understand trends, seasonality, and stationarity.
在预测前对时间序列进行探索性数据分析,了解趋势、季节性和平稳性。
📚 Available Scripts
📚 可用脚本
scripts/check_system.py
scripts/check_system.pyscripts/check_system.py
scripts/check_system.pyMandatory preflight checker. Run before first model load.
bash
python scripts/check_system.pyOutput example:
=== TimesFM System Requirements Check ===
[RAM] Total: 32.0 GB | Available: 24.3 GB ✅ PASS
[GPU] NVIDIA RTX 4090 | VRAM: 24.0 GB ✅ PASS
[Disk] Free: 142.5 GB ✅ PASS
[Python] 3.12.1 ✅ PASS
[timesfm] Installed (2.5.0) ✅ PASS
[torch] Installed (2.4.1+cu121) ✅ PASS
VERDICT: ✅ System is ready for TimesFM 2.5 (GPU mode)
Recommended: per_core_batch_size=128强制预飞检查器。首次加载模型前运行。
bash
python scripts/check_system.py输出示例:
=== TimesFM系统要求检查 ===
[RAM] 总容量: 32.0 GB | 可用: 24.3 GB ✅ 通过
[GPU] NVIDIA RTX 4090 | VRAM: 24.0 GB ✅ 通过
[磁盘] 可用空间: 142.5 GB ✅ 通过
[Python] 3.12.1 ✅ 通过
[timesfm] 已安装 (2.5.0) ✅ 通过
[torch] 已安装 (2.4.1+cu121) ✅ 通过
结论: ✅ 系统已准备好运行TimesFM 2.5(GPU模式)
推荐设置: per_core_batch_size=128scripts/forecast_csv.py
scripts/forecast_csv.pyscripts/forecast_csv.py
scripts/forecast_csv.pyEnd-to-end CSV forecasting with automatic system check.
bash
python scripts/forecast_csv.py input.csv \
--horizon 24 \
--date-col date \
--value-cols sales,revenue \
--output forecasts.csv端到端CSV预测,包含自动系统检查。
bash
python scripts/forecast_csv.py input.csv \
--horizon 24 \
--date-col date \
--value-cols sales,revenue \
--output forecasts.csv📖 Reference Documentation
📖 参考文档
Detailed guides in :
references/| File | Contents |
|---|---|
| Hardware tiers, GPU/CPU selection, memory estimation formulas |
| Full |
| Input formats, NaN handling, CSV loading, covariate setup |
详细指南位于目录:
references/| 文件 | 内容 |
|---|---|
| 硬件层级、GPU/CPU选择、内存估算公式 |
| |
| 输入格式、NaN处理、CSV加载、协变量设置 |
Common Pitfalls
常见陷阱
- Not running system check → model load crashes on low-RAM machines. Always run first.
check_system.py - Forgetting →
model.compile(). Must callRuntimeError: Model is not compiledbeforecompile().forecast() - Not setting → unstable forecasts for series with large values.
normalize_inputs=True - Using v1/v2 on machines with < 32 GB RAM → use TimesFM 2.5 (200M params) instead.
- Not setting → quantiles may not be monotonic (q10 > q50).
fix_quantile_crossing=True - Huge on small GPU → CUDA OOM. Start small, increase.
per_core_batch_size - Passing 2-D arrays → TimesFM expects a list of 1-D arrays, not a 2-D matrix.
- Forgetting → slower inference on Ampere+ GPUs.
torch.set_float32_matmul_precision("high") - Not handling NaN in output → edge cases with very short series. Always check .
np.isnan(point).any() - Using for series that can be negative → clamps forecasts at zero. Set False for temperature, returns, etc.
infer_is_positive=True
- 未运行系统检查 → 低RAM机器上加载模型时崩溃。务必先运行。
check_system.py - 忘记调用→ 出现
model.compile()。调用RuntimeError: Model is not compiled前必须先调用forecast()。compile() - 未设置→ 数值较大的序列预测结果不稳定。
normalize_inputs=True - 在内存<32GB的机器上使用v1/v2版本 → 改用TimesFM 2.5(2亿参数)。
- 未设置→ 分位数可能不单调(q10 > q50)。
fix_quantile_crossing=True - 小GPU上设置过大的→ CUDA内存不足。从小值开始逐步增大。
per_core_batch_size - 传入二维数组 → TimesFM需要一维数组的列表,而非二维矩阵。
- 忘记设置→ Ampere+ GPU上推理速度较慢。
torch.set_float32_matmul_precision("high") - 未处理输出中的NaN → 极短序列的边缘情况。务必检查。
np.isnan(point).any() - 对可能为负的序列设置→ 预测值被限制为0。对于温度、收益等序列设为False。
infer_is_positive=True
Model Versions
模型版本
mermaid
timeline
accTitle: TimesFM Version History
accDescr: Timeline of TimesFM model releases showing parameter counts and key improvements.
section 2024
TimesFM 1.0 : 200M params, 2K context, JAX only
TimesFM 2.0 : 500M params, 2K context, PyTorch + JAX
section 2025
TimesFM 2.5 : 200M params, 16K context, quantile head, no frequency indicator| Version | Params | Context | Quantile Head | Frequency Flag | Status |
|---|---|---|---|---|---|
| 2.5 | 200M | 16,384 | ✅ Continuous (30M) | ❌ Removed | Latest |
| 2.0 | 500M | 2,048 | ✅ Fixed buckets | ✅ Required | Archived |
| 1.0 | 200M | 2,048 | ✅ Fixed buckets | ✅ Required | Archived |
Hugging Face checkpoints:
- (recommended)
google/timesfm-2.5-200m-pytorch google/timesfm-2.5-200m-flax- (archived)
google/timesfm-2.0-500m-pytorch - (archived)
google/timesfm-1.0-200m-pytorch
mermaid
timeline
accTitle: TimesFM Version History
accDescr: Timeline of TimesFM model releases showing parameter counts and key improvements.
section 2024
TimesFM 1.0 : 200M params, 2K context, JAX only
TimesFM 2.0 : 500M params, 2K context, PyTorch + JAX
section 2025
TimesFM 2.5 : 200M params, 16K context, quantile head, no frequency indicator| 版本 | 参数数量 | 上下文长度 | 分位数头 | 频率标记 | 状态 |
|---|---|---|---|---|---|
| 2.5 | 200M | 16,384 | ✅ 连续型(30M) | ❌ 已移除 | 最新版 |
| 2.0 | 500M | 2,048 | ✅ 固定桶 | ✅ 必填 | 已归档 |
| 1.0 | 200M | 2,048 | ✅ 固定桶 | ✅ 必填 | 已归档 |
Hugging Face checkpoint:
- (推荐)
google/timesfm-2.5-200m-pytorch google/timesfm-2.5-200m-flax- (已归档)
google/timesfm-2.0-500m-pytorch - (已归档)
google/timesfm-1.0-200m-pytorch
Resources
资源
- Paper: A Decoder-Only Foundation Model for Time-Series Forecasting (ICML 2024)
- Repository: https://github.com/google-research/timesfm
- Hugging Face: https://huggingface.co/collections/google/timesfm-release-66e4be5fdb56e960c1e482a6
- Google Blog: https://research.google/blog/a-decoder-only-foundation-model-for-time-series-forecasting/
- BigQuery Integration: https://cloud.google.com/bigquery/docs/timesfm-model
- 论文:A Decoder-Only Foundation Model for Time-Series Forecasting(ICML 2024)
- 仓库:https://github.com/google-research/timesfm
- Hugging Face:https://huggingface.co/collections/google/timesfm-release-66e4be5fdb56e960c1e482a6
- 谷歌博客:https://research.google/blog/a-decoder-only-foundation-model-for-time-series-forecasting/
- BigQuery集成:https://cloud.google.com/bigquery/docs/timesfm-model
Examples
示例
Three fully-working reference examples live in . Use them as ground truth for correct API usage and expected output shape.
examples/| Example | Directory | What It Demonstrates | When To Use It |
|---|---|---|---|
| Global Temperature Forecast | | Basic | Starting point; copy-paste baseline for any univariate series |
| Anomaly Detection | | Two-phase detection: linear detrend + Z-score on context, quantile PI on forecast; 2-panel viz | Any task requiring outlier detection on historical + forecasted data |
| Covariates (XReg) | | | Retail, energy, or any series with known exogenous drivers |
三个完整可运行的参考示例位于目录。可作为正确API用法和预期输出形状的基准。
examples/| 示例 | 目录 | 演示内容 | 使用场景 |
|---|---|---|---|
| 全球温度预测 | | 基础 | 入门示例;可作为任意单变量序列的复制粘贴基准 |
| 异常检测 | | 两阶段检测:上下文数据线性去趋势+Z分数、预测值分位数区间;双面板可视化 | 需要对历史数据和预测数据进行异常值检测的场景 |
| 协变量预测(XReg) | | | 零售、能源或存在已知外生驱动因素的序列 |
Running the Examples
运行示例
bash
undefinedbash
undefinedGlobal temperature (no TimesFM 2.5 needed)
全球温度预测(无需TimesFM 2.5)
cd examples/global-temperature && python run_forecast.py && python visualize_forecast.py
cd examples/global-temperature && python run_forecast.py && python visualize_forecast.py
Anomaly detection (uses TimesFM 1.0)
异常检测(使用TimesFM 1.0)
cd examples/anomaly-detection && python detect_anomalies.py
cd examples/anomaly-detection && python detect_anomalies.py
Covariates (API demo -- requires TimesFM 2.5 + timesfm[xreg] for real inference)
协变量预测(API演示——需要TimesFM 2.5 + timesfm[xreg]才能进行实际推理)
cd examples/covariates-forecasting && python demo_covariates.py
undefinedcd examples/covariates-forecasting && python demo_covariates.py
undefinedExpected Outputs
预期输出
| Example | Key output files | Acceptance criteria |
|---|---|---|
| global-temperature | | |
| anomaly-detection | | Sep 2023 flagged CRITICAL (z >= 3.0); >= 2 forecast CRITICAL from injected anomalies |
| covariates-forecasting | | CSV has 108 rows (3 stores x 36 weeks); stores have distinct price arrays |
| 示例 | 关键输出文件 | 验收标准 |
|---|---|---|
| global-temperature | | |
| anomaly-detection | | 2023年9月被标记为严重(z >= 3.0);至少2个预测值因注入异常被标记为严重 |
| covariates-forecasting | | CSV包含108行(3个门店×36周);门店价格数组各不相同 |
Quality Checklist
质量检查清单
Run this checklist after every TimesFM task before declaring success:
- Output shape correct -- shape is
point_fc,(n_series, horizon)isquant_fc(n_series, horizon, 10) - Quantile indices -- index 0 = mean, 1 = q10, 2 = q20 ... 9 = q90. NOT 0 = q0, 1 = q10.
- Frequency flag -- TimesFM 1.0/2.0: pass for monthly data. TimesFM 2.5: no freq flag.
freq=[0] - Series length -- context must be >= 32 data points (model minimum). Warn if shorter.
- No NaN -- should be False. Check input series for gaps first.
np.isnan(point_fc).any() - Visualization axes -- if multiple panels share data, use . All time axes must cover the same span.
sharex=True - Binary outputs in Git LFS -- PNG and GIF files must be tracked via (repo root already configured).
.gitattributes - No large datasets committed -- any real dataset > 1 MB should be downloaded to and annotated in code.
tempfile.mkdtemp() - -- must appear before any pyplot import when running headless.
matplotlib.use('Agg') - -- set
infer_is_positivefor temperature anomalies, financial returns, or any series that can be negative.False
完成TimesFM任务后,运行以下清单确认任务成功:
- 输出形状正确——形状为
point_fc,(n_series, horizon)形状为quant_fc(n_series, horizon, 10) - 分位数索引正确——索引0=均值,1=q10,2=q20……9=q90。不是0=q0,1=q10。
- 频率标记——TimesFM 1.0/2.0:月度数据需传入。TimesFM 2.5:无需频率标记。
freq=[0] - 序列长度——上下文必须≥32个数据点(模型最小值)。如果更短,发出警告。
- 无NaN值——应为False。先检查输入序列是否存在缺失值。
np.isnan(point_fc).any() - 可视化坐标轴——如果多个面板共享数据,使用。所有时间轴必须覆盖相同范围。
sharex=True - Git LFS中的二进制输出——PNG和GIF文件必须通过跟踪(仓库根目录已配置)。
.gitattributes - 未提交大型数据集——任何大于1MB的真实数据集应下载到并在代码中注明。
tempfile.mkdtemp() - ——在无图形界面环境运行时,必须在任何pyplot导入前设置。
matplotlib.use('Agg') - 设置正确——对于温度异常、金融收益或任何可能为负的序列,设为False。
infer_is_positive
Common Mistakes
常见错误
These bugs have appeared in this skill's examples. Learn from them:
-
Quantile index off-by-one -- The most common mistake.is the mean, not q0. q10 = index 1, q90 = index 9. Always define named constants:
quant_fc[..., 0].IDX_Q10, IDX_Q20, IDX_Q80, IDX_Q90 = 1, 2, 8, 9 -
Variable shadowing in comprehensions -- If you build per-series covariate dicts inside a loop, do NOT use the loop variable as the comprehension variable. Accumulate into separateoutside the loop, then assign.
dict[str, ndarray]python# WRONG -- outer `store_id` gets shadowed: covariates = {store_id: arr[store_id] for store_id in stores} # inside outer loop over store_id # CORRECT -- use a different name or accumulate beforehand: prices_by_store: dict[str, np.ndarray] = {} for store_id, config in stores.items(): prices_by_store[store_id] = compute_price(config) -
Wrong CSV column name -- The global-temperature CSV uses, not
anomaly_c. Alwaysanomalybefore accessing.print(df.columns) -
warning with
tight_layout()-- Harmless; suppress withsharex=Trueor ignore.plt.tight_layout(rect=[0, 0, 1, 0.97]) -
TimesFM 2.5 required for-- TimesFM 1.0 does NOT have this method. Install
forecast_with_covariates()and use checkpointpip install timesfm[xreg].google/timesfm-2.5-200m-pytorch -
Future covariates must span the full horizon -- Dynamic covariates (price, promotions, holidays) must have values for BOTH the context AND the forecast horizon. You cannot pass context-only arrays.
-
Anomaly thresholds must be defined once -- Define,
CRITICAL_Z = 3.0as module-level constants. Never hardcodeWARNING_Z = 2.0or3inline.2 -
Context anomaly detection uses residuals, not raw values -- Always detrend first (linear, or seasonal decomposition), then Z-score the residuals. Raw-value Z-scores are misleading on trending data.
np.polyfit
这些错误曾出现在本技能的示例中,可引以为戒:
-
分位数索引偏移一位——最常见的错误。是均值,不是q0。q10=索引1,q90=索引9。始终定义命名常量:
quant_fc[..., 0]。IDX_Q10, IDX_Q20, IDX_Q80, IDX_Q90 = 1, 2, 8, 9 -
推导式中的变量遮蔽——如果在循环内构建单序列协变量字典,请勿将循环变量用作推导式变量。在循环外单独积累到中,再进行赋值。
dict[str, ndarray]python# 错误——外部的`store_id`被遮蔽: covariates = {store_id: arr[store_id] for store_id in stores} # 在遍历store_id的外部循环内 # 正确——使用不同名称或提前积累: prices_by_store: dict[str, np.ndarray] = {} for store_id, config in stores.items(): prices_by_store[store_id] = compute_price(config) -
CSV列名错误——全球温度CSV使用而非
anomaly_c。访问前始终先anomaly。print(df.columns) -
时
sharex=True警告——无害;可使用tight_layout()抑制或忽略。plt.tight_layout(rect=[0, 0, 1, 0.97]) -
需要TimesFM 2.5——TimesFM 1.0没有该方法。安装
forecast_with_covariates()并使用checkpointpip install timesfm[xreg]。google/timesfm-2.5-200m-pytorch -
未来协变量必须覆盖完整预测时长——动态协变量(价格、促销、节假日)必须同时包含上下文和预测时长的值。不能仅传入上下文数组。
-
异常阈值必须统一定义——将、
CRITICAL_Z = 3.0定义为模块级常量。切勿在代码中硬编码WARNING_Z = 2.0或3。2 -
上下文异常检测使用残差而非原始值——必须先去趋势(线性去趋势或季节性分解),再对残差计算Z分数。原始值的Z分数在趋势数据上会产生误导。
np.polyfit
Validation & Verification
验证与确认
Use the example outputs as regression baselines. If you change forecasting logic, verify:
bash
undefined使用示例输出作为回归基准。如果修改了预测逻辑,请验证:
bash
undefinedAnomaly detection regression check:
异常检测回归检查:
python -c "
import json
d = json.load(open('examples/anomaly-detection/output/anomaly_detection.json'))
ctx = d['context_summary']
assert ctx['critical'] >= 1, 'Sep 2023 must be CRITICAL'
assert any(r['date'] == '2023-09' and r['severity'] == 'CRITICAL'
for r in d['context_detections']), 'Sep 2023 not found'
print('Anomaly detection regression: PASS')"
python -c "
import json
d = json.load(open('examples/anomaly-detection/output/anomaly_detection.json'))
ctx = d['context_summary']
assert ctx['critical'] >= 1, '2023年9月必须被标记为严重'
assert any(r['date'] == '2023-09' and r['severity'] == 'CRITICAL'
for r in d['context_detections']), '未找到2023年9月的标记'
print('异常检测回归检查: 通过')"
Covariates regression check:
协变量回归检查:
python -c "
import pandas as pd
df = pd.read_csv('examples/covariates-forecasting/output/sales_with_covariates.csv')
assert len(df) == 108, f'Expected 108 rows, got {len(df)}'
prices = df.groupby('store_id')['price'].mean()
assert prices['store_A'] > prices['store_B'] > prices['store_C'], 'Store price ordering wrong'
print('Covariates regression: PASS')"
undefinedpython -c "
import pandas as pd
df = pd.read_csv('examples/covariates-forecasting/output/sales_with_covariates.csv')
assert len(df) == 108, f'预期108行,实际{len(df)}行'
prices = df.groupby('store_id')['price'].mean()
assert prices['store_A'] > prices['store_B'] > prices['store_C'], '门店价格排序错误'
print('协变量回归检查: 通过')"
undefined