Appearance
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 | 正弦位置编码(固定) | |
TemporalEmbedding | 月/日/星期/小时 各自查嵌入表 | 4个 nn.Embedding 求和 |
TimeFeatureEmbedding | 对 4 维时间特征做线性投影 | [B,L,4] → [B,L,d_model] |
DataEmbedding | Token + Positional + Temporal 三者相加 | 标准 Transformer 嵌入 |
DataEmbedding_wo_pos | 去掉位置编码的版本 | TimeMixer 等使用 |
DataEmbedding_inverted | 转置后嵌入,把变量作为 token | iTransformer 专用 |
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-Product | |
ProbAttention | ProbSparse,只算 Top-u Query | |
AutoCorrelation | 基于 FFT 的周期相关,替代 Attention | |
DSAttention | De-stationary,对 score 加可学习 τ 和 δ 修正 | |
AttentionLayer | QKV 线性投影 + 多头包装(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, trendseries_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复用 layers:Autoformer_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?
- 序列分解让线性层只需要拟合平稳的分量,难度大降
- Transformer 的注意力在长序列上对噪声敏感,线性层反而更鲁棒
- 参数量极少,不容易在小数据集上过拟合
6.2 PatchTST — Patch 机制
文件:models/PatchTST.py复用 layers:Embed.PatchEmbedding、Transformer_EncDec.Encoder、SelfAttention_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 Independence | x.reshape(B*C, ...) | 避免变量间虚假相关 |
| Patch | PatchEmbedding (layers/Embed.py) | token 有局部语义,降低序列长度 |
| 无 Decoder | forward 直接返回 Encoder 输出 | 简化结构 |
6.3 iTransformer — 反转维度
文件:models/iTransformer.py复用 layers:Embed.DataEmbedding_inverted、Transformer_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复用 layers:Autoformer_EncDec.series_decomp、Embed.DataEmbedding_wo_pos、StandardNorm.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 NoneStep 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 分钟。
九、模型对比速查表
| 模型 | Encoder | Decoder | Attention 类型 | 关键创新 | 适合场景 |
|---|---|---|---|---|---|
| Transformer | ✅ | ✅ | Full | 基线 | 短序列 |
| Informer | ✅ | ✅ | ProbSparse | 稀疏注意力 | 长序列 |
| Autoformer | ✅ | ✅ | AutoCorrelation | 序列分解+周期相关 | 周期性数据 |
| PatchTST | ✅ | ❌ | Full(patch 间) | Patch token | 长序列,单变量 |
| iTransformer | ✅ | ❌ | Full(变量间) | 反转 token | 多变量 |
| DLinear | ❌ | ❌ | 无 | 分解+线性 | 快速 baseline |
| TimeMixer | ❌ | ❌ | 无 | 多尺度 MLP mixing | 多尺度时序 |