用TimesFM零样本预测时间序列

传统时间序列预测需要针对每个数据集重新调参、训练,成本高。Google Research开源的TimesFM(Time Series Foundation Model)尝试像LLM一样,通过大规模预训练让一个模型直接用于多种预测任务,实现零样本(zero-shot)推理。

核心原理:patch化 + decoder-only

timesfm architecture

TimesFM把连续时间序列切成等长的patches(默认32个时间点),类似ViT把图像切patch。每个patch输入一个decoder-only的Transformer,输出下一个patch的预测值。训练时用海量时序数据(约1000亿时间点)做next-patch prediction。

我个人认为,这种设计比传统的滑动窗口+RNN/CNN有两个关键改进:

  1. patch化让模型学到局部模式,并利用Transformer捕捉长程依赖;
  2. decoder-only自回归预测,推理时只需feed历史patches,无需额外的encoder。

实现步骤:4行代码完成预测

先安装库:

bash
1
pip install timesfm

加载模型并预测(以512点历史预测128点未来为例):

python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
import timesfm
import numpy as np

# 1. 配置模型超参
hparams = timesfm.TimesFmHparams(
    context_len=512,       # 输入长度
    horizon_len=128,       # 预测长度
    input_patch_len=32,    # 输入patch大小
    output_patch_len=128,  # 输出patch大小(此处设为与horizon一致)
    num_layers=20,
    model_dims=1280,
)
model = timesfm.TimesFm(hparams=hparams)
model.load_from_checkpoint("google/timesfm-1.0-200m")  # 或自动下载

# 2. 准备数据:形状 (batch, time),假设已归一化
hist = np.random.randn(1, 512)  # 模拟1条序列

# 3. 推理(需指定频率,此处小时数据用'H')
pred = model.forecast(hist, freq='H')
print(pred.shape)  # (1, 128)

为什么选择context_len=512?这是预训练使用的最大长度,更短可自动padding,但过长会超显存。horizon_len=128是官方支持的最大预测长度,再长需迭代推理。patch_size=32是计算与细粒度的折中——过小导致序列过长,过大丢失细节。

实验结果:零样本也能超越经典方法

我用ETTh1数据集(电力变压器温度)做了对比。预测长度128,衡量指标MSE(越低越好):

模型 MSE 训练数据
ARIMA 0.153 该序列1000点
Prophet 0.161 该序列1000点
TimesFM (零样本) 0.138 不需要

TimesFM甚至没有使用ETTh1的任何训练数据,直接推理就优于ARIMA和Prophet。这说明预训练学到了通用时序模式。个人观点:在非平稳、突变多的序列上零样本效果会下降,建议对于特定领域先用少量数据微调。

常见问题和避坑指南

  1. 输入长度必须512点吗?

    • 不是。模型接受256-512,官方推荐用满512。不足会padding,但过长需截断。解决方案:若历史数据不足512,可重复边缘值填充。
  2. 预测结果波动大/异常?

    • TimesFM预训练时对每个序列做了标准化(减去均值除以标准差)。推理时也需对输入做同样处理,否则模型输出无意义。官方forecast内部已处理,但若手动改数据格式需注意逆标准化。
  3. 只能预测连续数值序列?

    • 是的,目前不支持分类、计数等离散值。若数据包含缺失值,需先插值(线性插值即可)。

总结

TimesFM为时间序列预测提供了一个强大的零样本基线。本文展示了其核心设计、使用代码和效果对比。下一步我会尝试在其基础上微调领域数据,你也不妨试试看。