Skip to content

Time-Series-Library 子库架构学习文档

定位

ts_benchmark/baselines/time_series_library/ 是 TFB 内嵌的一个模型实现子库,收录了 Transformer 家族及多种现代时间序列预测模型。它同时也是一个独立的开源项目(thuml/Time-Series-Library)。

在 TFB 中,所有 TSL 模型都通过 TransformerAdapter 统一接入评测流程,你调用时写的 time_series_library.PatchTST 就是从这里加载的。


一、目录结构总览

time_series_library/
├── __init__.py                    ← 模型注册表(公开 20+ 个模型)
├── adapters_for_transformers.py   ← TFB 接入层(TransformerAdapter)

├── models/                        ← 每个文件 = 一个完整模型
│   ├── Transformer.py             ← 标准 Transformer(基线)
│   ├── Informer.py
│   ├── Autoformer.py
│   ├── PatchTST.py
│   ├── iTransformer.py
│   ├── DLinear.py                 ← 非 Transformer,线性基线
│   ├── TimeMixer.py               ← 多尺度 MLP-Mixer
│   └── ...(共 20 个文件)

├── layers/                        ← 可复用模块库(各模型共享)
│   ├── Embed.py                   ← 各种 Embedding 实现
│   ├── SelfAttention_Family.py    ← 各种 Attention 变体
│   ├── Transformer_EncDec.py      ← 标准 Encoder/Decoder 骨架
│   ├── Autoformer_EncDec.py       ← Autoformer 专用层(含 series_decomp)
│   ├── FourierCorrelation.py      ← FEDformer 用的傅里叶注意力
│   ├── MultiWaveletCorrelation.py ← FEDformer 小波注意力
│   ├── Conv_Blocks.py             ← 卷积相关构件
│   └── StandardNorm.py            ← 可学习的标准化层

└── patchs/                        ← 非官方补充模型(命名历史遗留)
    ├── Linear.py                  ← NLinear/Linear 等
    ├── NLinear.py
    └── Triformer.py

二、三层架构关系

┌─────────────────────────────────────────────┐
│              TFB 评测流程                    │
│         pipeline → eval_model()             │
└─────────────────┬───────────────────────────┘
                  │ 调用
┌─────────────────▼───────────────────────────┐
│         adapters_for_transformers.py         │
│                                              │
│  TransformerAdapter                          │
│  ├── 继承 DeepForecastingModelBase           │
│  │    (训练循环/归一化/早停 已内置)         │
│  ├── _init_model()  → model_class(config)   │
│  └── _process()     → 拼 dec_input, 调 forward() │
│                                              │
│  generate_model_factory()                    │
│  └── 把 PyTorch 模型类包装成 TFB 可识别格式  │
└─────────────────┬───────────────────────────┘
                  │ 实例化
┌─────────────────▼───────────────────────────┐
│              models/XxxModel.py              │
│                                              │
│  class XxxModel(nn.Module):                 │
│  ├── __init__(configs)  ← 用 layers/ 组装    │
│  └── forward(x_enc, x_mark_enc,            │
│               x_dec, x_mark_dec)            │
│       └── 按 task_name 路由到              │
│           forecast() / imputation() / ...   │
└─────────────────┬───────────────────────────┘
                  │ 复用
┌─────────────────▼───────────────────────────┐
│               layers/ 模块库                 │
│  Embed → SelfAttention → EncDec → Norm       │
└──────────────────────────────────────────────┘

三、关键接入层:adapters_for_transformers.py

3.1 TransformerAdapter

python
class TransformerAdapter(DeepForecastingModelBase):
    def __init__(self, model_name, model_class, **kwargs):
        super().__init__(MODEL_HYPER_PARAMS, **kwargs)  # 默认超参在这里
        self.model_class = model_class

    def _init_model(self):
        return self.model_class(self.config)   # 用 config 实例化具体网络

    def _process(self, input, target, input_mark, target_mark):
        # 构造 decoder 输入:前 label_len 步用真实值,后 horizon 步填 0
        dec_input = torch.zeros_like(target[:, -self.config.horizon:, :])
        dec_input = torch.cat([target[:, :self.config.label_len, :], dec_input], dim=1)
        output = self.model(input, input_mark, dec_input, target_mark)
        return {"output": output}
关键理解

_process 里拼接的 dec_input 就是 Informer/Autoformer 等 Transformer 系模型的 Generative Decoder 输入方式:

  • 前半段 [0 : label_len]:来自 target 的真实值(给 decoder 看历史上下文)
  • 后半段 [label_len : label_len+horizon]:全 0(让模型预测这部分)

对于 DLinear / iTransformer 等只有 Encoder 的模型,x_dec 传入但内部不使用。

3.2 generate_model_factory + transformer_adapter

python
# 方式一:手动注册(可以指定 required_args)
factory = generate_model_factory("MyModel", MyModelClass, required_args={
    "seq_len": "input_chunk_length",
    "horizon": "output_chunk_length",
})

# 方式二:装饰器风格(自动用类名作 model_name)
@transformer_adapter
class PatchTST(nn.Module): ...
# 等价于:generate_model_factory("PatchTST", PatchTST, {seq_len, horizon, norm})

required_args 的作用:告诉 TFB 的 ModelFactory 在加载模型时,哪些超参必须由外部传入(从 config 的 strategy_args 中自动注入)。


四、layers/ 模块库详解

4.1 Embed.py — 输入嵌入

类名用途公式
TokenEmbedding用 Conv1d 把 C 维升到 d_model[B,L,C] → [B,L,d_model]
PositionalEmbedding正弦位置编码(固定)PEpos,2i=sin(pos/100002i/d)
TemporalEmbedding月/日/星期/小时 各自查嵌入表4个 nn.Embedding 求和
TimeFeatureEmbedding对 4 维时间特征做线性投影[B,L,4] → [B,L,d_model]
DataEmbeddingToken + Positional + Temporal 三者相加标准 Transformer 嵌入
DataEmbedding_wo_pos去掉位置编码的版本TimeMixer 等使用
DataEmbedding_inverted转置后嵌入,把变量作为 tokeniTransformer 专用
PatchEmbedding先切 patch 再投影PatchTST 专用
DataEmbedding_inverted 的关键点

普通嵌入:[B, L, C] → [B, L, d_model](时间步是 token) 反转嵌入:[B, L, C] 转置为 [B, C, L],再投影为 [B, C, d_model]变量是 token

4.2 SelfAttention_Family.py — 注意力变体

类名创新点复杂度
FullAttention标准 Scaled Dot-ProductO(L2)
ProbAttentionProbSparse,只算 Top-u QueryO(LlogL)
AutoCorrelation基于 FFT 的周期相关,替代 AttentionO(LlogL)
DSAttentionDe-stationary,对 score 加可学习 τ 和 δ 修正O(L2)
AttentionLayerQKV 线性投影 + 多头包装(Wrapper)
AttentionLayer(FullAttention(...), d_model, n_heads)
    ↓ 内部分头
Q:[B,L,H,E]  K:[B,S,H,E]  V:[B,S,H,D]
    ↓ 传给 FullAttention.forward()
out:[B,L,H,D] → concat → [B,L,d_model]

4.3 Transformer_EncDec.py — 标准骨架

EncoderLayer:
  x → AttentionLayer → Add&Norm → FFN(Conv1d×2) → Add&Norm

Encoder:
  [EncoderLayer×e_layers] → (可选 ConvLayer 蒸馏) → LayerNorm

DecoderLayer:
  x → SelfAttn(Masked) → Add&Norm
    → CrossAttn(x,enc_out) → Add&Norm
    → FFN → Add&Norm

Decoder:
  [DecoderLayer×d_layers] → LayerNorm → (可选 Projection)
FFN 的实现

TSL 里 FFN 不是两个 Linear,而是两个 Conv1d(kernel_size=1),效果等价但更高效。

4.4 Autoformer_EncDec.py — 分解层

python
class series_decomp(nn.Module):
    # 输入: x [B, L, C]
    # moving_avg(kernel_size) → trend [B, L, C]
    # seasonal = x - trend [B, L, C]
    def forward(self, x):
        trend = self.moving_avg(x)
        return x - trend, trend   # seasonal, trend

series_decomp 是 Autoformer、DLinear、TimeMixer 都会复用的模块。


五、模型实现规范:forward() 签名约定

所有 TSL 模型forward 函数都遵循同一签名:

python
def forward(self, x_enc, x_mark_enc, x_dec, x_mark_dec, mask=None):
    # x_enc:      [B, seq_len, C]         编码器输入
    # x_mark_enc: [B, seq_len, 4]         编码器时间特征
    # x_dec:      [B, label_len+pred, C]  解码器输入(TransformerAdapter 构造)
    # x_mark_dec: [B, label_len+pred, 4]  解码器时间特征
    # mask:       可选,用于 imputation 任务
    #
    # 返回: [B, pred_len, C](预测结果)
    ...

内部按 task_name 路由:

python
def forward(self, ...):
    if self.task_name in ("long_term_forecast", "short_term_forecast"):
        return self.forecast(...)   # 返回 [B, pred_len, C]
    if self.task_name == "imputation":
        return self.imputation(...) # 返回 [B, seq_len, C]
    if self.task_name == "anomaly_detection":
        return self.anomaly_detection(...)
    if self.task_name == "classification":
        return self.classification(...)

六、典型模型实例分析

6.1 DLinear — 最简模型(无 Attention)

文件models/DLinear.py复用 layersAutoformer_EncDec.series_decomp

输入 x_enc [B, seq_len, C]

series_decomp(moving_avg=25)
    ├── seasonal [B, seq_len, C]
    └── trend    [B, seq_len, C]
    ↓ permute → [B, C, seq_len]
Linear_Seasonal: seq_len → pred_len (per-channel)
Linear_Trend:    seq_len → pred_len (per-channel)
    ↓ 相加 + permute → [B, pred_len, C]
输出

核心代码models/DLinear.py:64-87):

python
def encoder(self, x):
    seasonal_init, trend_init = self.decompsition(x)   # 分解
    seasonal_init = seasonal_init.permute(0, 2, 1)     # [B,C,L]
    trend_init    = trend_init.permute(0, 2, 1)
    seasonal_output = self.Linear_Seasonal(seasonal_init)  # [B,C,pred_len]
    trend_output    = self.Linear_Trend(trend_init)
    return (seasonal_output + trend_output).permute(0, 2, 1)  # [B,pred_len,C]
为什么能打败 Transformer?
  1. 序列分解让线性层只需要拟合平稳的分量,难度大降
  2. Transformer 的注意力在长序列上对噪声敏感,线性层反而更鲁棒
  3. 参数量极少,不容易在小数据集上过拟合

6.2 PatchTST — Patch 机制

文件models/PatchTST.py复用 layersEmbed.PatchEmbeddingTransformer_EncDec.EncoderSelfAttention_Family.FullAttention

输入 x_enc [B, seq_len, C]
    ↓ PatchEmbedding (channel independence: 每个变量单独处理)
    拆 patch: N_patch = ⌊(seq_len - patch_len) / stride⌋ + 1
    投影:     [B*C, N_patch, d_model]

Encoder (FullAttention × e_layers)   # patch 间做注意力
    [B*C, N_patch, d_model]
    ↓ reshape → [B, C, N_patch, d_model]
FlattenHead: flatten(N_patch, d_model) → Linear → pred_len
    [B, C, pred_len] → permute → [B, pred_len, C]

关键设计

要素实现位置作用
Channel Independencex.reshape(B*C, ...)避免变量间虚假相关
PatchPatchEmbedding (layers/Embed.py)token 有局部语义,降低序列长度
无 Decoderforward 直接返回 Encoder 输出简化结构

6.3 iTransformer — 反转维度

文件models/iTransformer.py复用 layersEmbed.DataEmbedding_invertedTransformer_EncDec.Encoder

输入 x_enc [B, seq_len, C]
    ↓ DataEmbedding_inverted
    转置+投影: [B, C, d_model]    ← 变量是 token!

Encoder (FullAttention × e_layers)
    注意力跑在变量维度:[B, C, d_model]
    学习的是变量间相关

Linear Projection: d_model → pred_len
    [B, C, pred_len] → permute → [B, pred_len, C]
    ↓ 反归一化(减去的均值和方差加回来)
输出

与 PatchTST 的核心区别models/iTransformer.py:69-86):

PatchTST 的 Attention: 同一变量内,patch_i 和 patch_j 之间(时间维度)
iTransformer 的 Attention: 不同变量 var_i 和 var_j 之间(变量维度)

6.4 TimeMixer — 多尺度无 Attention

文件models/TimeMixer.py复用 layersAutoformer_EncDec.series_decompEmbed.DataEmbedding_wo_posStandardNorm.Normalize

输入 x_enc [B, seq_len, C]
    ↓ 下采样生成多分辨率序列
    scale_0 = original [B, L, C]
    scale_1 = avg_pool  [B, L/2, C]
    scale_2 = avg_pool  [B, L/4, C]
    ↓ series_decomp 分解每个尺度
    (seasonal_0, trend_0), (seasonal_1, trend_1), ...

MultiScaleSeasonMixing  ← 季节分量:细粒度→粗粒度汇聚(Bottom-Up)
MultiScaleTrendMixing   ← 趋势分量:粗粒度→细粒度下传(Top-Down)
    ↓ 融合 + MLP 预测头
输出 [B, pred_len, C]
为什么没有 Attention?

TimeMixer 认为多变量时序的关键是时间尺度之间的信息传递,用轻量 MLP 在不同分辨率间 mixing,效果优于 Attention,且计算更快。


七、如何在 TSL 中新增模型

如果你想把自己的模型放进 TSL 体系,标准步骤:

Step 1:在 models/ 下创建 MyModel.py,实现 nn.Module

python
class MyModel(nn.Module):
    def __init__(self, configs):
        super().__init__()
        # 用 layers/ 里的模块组装

    def forecast(self, x_enc, x_mark_enc, x_dec, x_mark_dec):
        # 返回 [B, pred_len, C]
        ...

    def forward(self, x_enc, x_mark_enc, x_dec, x_mark_dec, mask=None):
        if self.task_name in ("long_term_forecast", "short_term_forecast"):
            return self.forecast(x_enc, x_mark_enc, x_dec, x_mark_dec)
        return None

Step 2:在 __init__.py 注册:

python
from .models.MyModel import MyModel
__all__ = [..., "MyModel"]

Step 3:但如果你是在 TFB 里用,不用动 TSL,直接按 TFB 的 self_impl/ 方式接入即可(参见 TFB学习笔记.md 第四节)。


八、阅读新模型的标准流程

拿到一个陌生的 TSL 模型文件,按以下顺序读:

1. __init__ 里 import 了哪些 layers/  → 知道用了哪些积木
2. __init__ 中的 self.xxx = ...       → 网络结构拼装方式
3. forecast() 函数                    → 核心前向流程 + 维度变化
4. 回头看 layers/ 对应文件             → 每块积木的细节

用这个流程读 DLinear 约 10 分钟,读 iTransformer 约 20 分钟。


九、模型对比速查表

模型EncoderDecoderAttention 类型关键创新适合场景
TransformerFull O(L2)基线短序列
InformerProbSparse O(LlogL)稀疏注意力长序列
AutoformerAutoCorrelation序列分解+周期相关周期性数据
PatchTSTFull(patch 间)Patch token长序列,单变量
iTransformerFull(变量间)反转 token多变量
DLinear分解+线性快速 baseline
TimeMixer多尺度 MLP mixing多尺度时序

*记录并在线阅读我的笔记*