Skip to content

PatchTST 总览与 Level 树

一句话定位

PatchTST = 把时间序列切成 patch + channel-independent Transformer。 核心洞见:把连续时间步视为 token(patch),attention 建模 patch 间依赖;同时每个变量独立送进模型,变量间完全不交互。


1. 论文问题:时序 Transformer 的三个困境

PatchTST(2023, ICLR)在一批时序 Transformer 之后提出,它要解决的不是"没有 Transformer",而是"已有的 Transformer 用法有问题"。

困境 1:O(L²) 的 attention 复杂度

传统 Transformer 把每个时间步当一个 token。序列长 512 → 512 个 token → attention 矩阵 512×512。序列变长,计算量平方增长。

传统做法(每步一个 token):
时序: [t1][t2][t3][t4][t5][t6][t7][t8][t9]
token:  T1  T2  T3  T4  T5  T6  T7  T8  T9   → 9 个 token,attention O(9²)=O(81)

困境 2:单点 token 语义太弱

一个时间步(比如"17:00 的温度")本身携带的信息极少,attention 学到的是点与点之间的相关,而不是更有意义的局部时间模式。

困境 3:channel-mixing 引入跨变量噪声

多变量时序里,不同变量(温度、湿度、风速)并不总是强相关。如果 attention 让变量之间互相影响,经常引入噪声反而使预测变差。


2. 两大核心创新

创新 1:Patch Token(时间片段作为 token)

类比:NLP 里的 BPE 把字符合并成词;ViT 把图片切成 16×16 的图块当 token。PatchTST 把时间序列切成重叠的时间片段(patch)当 token。

PatchTST 做法(patch_len=4,stride=2):

原始时序(长度 9,右端补 2):
  [1][3][5][2][4][6][3][5][7][7][7]
   0  1  2  3  4  5  6  7  8  9  10  ← 索引

滑窗切 patch(窗口=4,步长=2):
  Patch 0:  [1, 3, 5, 2]   ← 索引 0~3
  Patch 1:  [5, 2, 4, 6]   ← 索引 2~5
  Patch 2:  [4, 6, 3, 5]   ← 索引 4~7
  Patch 3:  [3, 5, 7, 7]   ← 索引 6~9

9 个时间步 → 4 个 patch token,attention O(4²)=O(16)

效果:

  • token 数量大幅减少(9→4),attention 更轻量
  • 每个 token 包含局部时间结构(4 步的连续信息),语义更丰富
  • 相邻 patch 有重叠(stride < patch_len),边界信息不丢失

创新 2:Channel-Independent(变量独立建模)

Channel-Mixing(传统做法):
  变量 A: [a1, a2, a3, ...]
  变量 B: [b1, b2, b3, ...]    → 三条时序一起送进 Transformer
  变量 C: [c1, c2, c3, ...]      变量之间 attention 可以互相影响

Channel-Independent(PatchTST):
  变量 A: [a1, a2, a3, ...]  ─→  独立 Transformer  ─→  预测 A
  变量 B: [b1, b2, b3, ...]  ─→  独立 Transformer  ─→  预测 B
  变量 C: [c1, c2, c3, ...]  ─→  独立 Transformer  ─→  预测 C
         (参数共享,同一套权重)

实现方式:把 batch 维和 channel 维合并,(B=2, enc_in=3, time) → (B×enc_in=6, time),让 6 条时序以"独立样本"的身份同时通过同一个 Transformer。

论文实证:在大多数数据集上,channel-independent 比 channel-mixing 效果更好。作者认为:跨变量相关性是噪声信号,强行建模反而有害。


3. 论文架构图(原理层)


4. 论文组件 → 代码文件对应

论文组件实现代码对应精读文档
Instance Normalization(RevIN 思路)PatchTST.py:forecast() 第 97-100 行03-Level3-forward主链 §3.1
Channel-Independent 拆分PatchTST.py:forecast() 第 103 行 permute03-Level3-forward主链 §3.2
Patch 切割Embed.py:PatchEmbedding.forward() 第 201-203 行04A-PatchEmbedding精读 §B~D
Patch 投影 + 位置编码Embed.py:PatchEmbedding.forward() 第 205 行04A-PatchEmbedding精读 §E~F
Transformer EncoderTransformer_EncDec.py:Encoder / EncoderLayer04B-Encoder精读 §一~四
Multi-Head Self-AttentionSelfAttention_Family.py:AttentionLayer / FullAttention04B-Encoder精读 §三~四
Prediction HeadPatchTST.py:FlattenHead04B-Encoder精读 §五
DenormalizePatchTST.py:forecast() 第 122-123 行03-Level3-forward主链 §3.9

5. 模型对比

对比项InformerDLinearPatchTST
token 是什么单个时间步无(直接线性)一段时间步(patch)
attention 复杂度O(L log L)(稀疏)O(patch_num²),远小于 O(L²)
多变量处理channel-mixing共享或独立线性channel-independent
Decoder有(生成式)
归一化RevIN 思路(实例归一化)

6. PatchTST 在完整 benchmark 中的坐标

6.1 顺序图(执行主线)

从外层 benchmark 到 PatchTST.forward 的完整调用链,和 DLinear / Informer 的外层完全相同,只在最后一步进入不同的模型。

和 DLinear / Informer 的区别只在 Level 8 之后:外层 benchmark 主线完全不变,从 _process(...) 往下才是 PatchTST 自己的逻辑。

6.2 抽象索引树

A~F 和 DLinear、Informer 的坐标树完全相同。PatchTST 独有的内容全在 G 节点展开。


7. 文档 Level 树


7. 全局 Toy 参数

本套文档所有文件统一使用以下参数,不得单独修改。

参数含义
B2batch size
seq_len9输入序列长度
enc_in3变量数(channels)
d_model8embedding 维度
patch_len4每个 patch 的长度(时间步数)
stride2patch 滑动步长
padding2右端填充(= stride,硬编码)
pred_len7预测步长
n_heads2attention 头数

派生量:

派生量计算出现位置
填充后长度9 + 211PatchEmbedding padding 步
patch_numint((9-4)/2 + 2)4unfold 输出
B×enc_in2 × 36channel-independent 虚拟 batch
d_k8 // 24attention 每头维度
head_nf8 × 432FlattenHead 输入维度

为什么这组参数好B×enc_in(6) ≠ patch_num(4) ≠ d_model(8),Encoder 内部各 transpose 操作的轴变化都可见,不存在"两轴相等导致变化隐藏"的问题。


8. 文件索引

文件Level覆盖内容关键 tensor 变化
01-Level1-配置进入PatchTST.mdL1命令行 → PatchTST(config)无 tensor,参数流
02-Level2-数据进入PatchTST.mdL2DataLoader → forward() 入参(2,9,3) (2,11,3)
03-Level3-forward主链.mdL3forecast() 9步骨架(2,9,3)→...→(2,7,3)
04-Level4-精读总览.mdL4精读索引-
04A-PatchEmbedding精读.mdL4Aunfold + embed(2,3,9)→(6,4,8)
04B-Encoder精读.mdL4BAttention + FFN + FlattenHead(6,4,8)→(2,7,3)
09-PatchTST全览流程图收束.md收束端到端流程图 + tensor 汇总全链

9. 推荐阅读路径

只想理解原理和直觉(不读代码):

00(§1-4 原理部分)→ 03(只看骨架)→ 09

完整精读(从原理到每行代码):

00 → 01 → 02 → 03 → 04A → 04B → 09

10. 代码层全局形状链(速览)

x_enc 输入:  (2,  9,  3)
  ↓ normalize
  ↓ permute(0,2,1)        → (2,  3,  9)      ← channel-independent 起点
  ↓ PatchEmbedding        → (6,  4,  8)      ← B×enc_in=6 是虚拟 batch
  ↓ Encoder               → (6,  4,  8)
  ↓ reshape               → (2,  3,  4,  8)
  ↓ permute(0,1,3,2)      → (2,  3,  8,  4)
  ↓ FlattenHead           → (2,  3,  7)
  ↓ permute(0,2,1)        → (2,  7,  3)
  ↓ denormalize
输出:         (2,  7,  3)  = (B, pred_len, enc_in)

附:三模型结构对比

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