Skip to content

Informer 论文原理与代码桥接

Abstract

这篇的目标不是继续解释某个局部代码块,而是:

把你之前那份“只从论文原理出发”的 Informer 笔记,重写成一篇能直接接上当前 modelread/Informer/ 代码主线的桥接文档。

这篇回答的是:

  1. 论文到底想解决什么问题
  2. 论文里的三大改动分别是什么
  3. 这些改动在当前 TFB 代码里各落到哪里
  4. 现在应该按什么顺序从“论文理解”走到“代码理解”

0. 为什么要重写这篇

你之前那份:

写得不错,但它有一个天然限制:

它是在“还没真正读代码”的前提下写的。

所以它更像:

  • 论文原理解释
  • 模块直觉总结
  • 数学和概念整理

而不是:

  • 当前这条命令怎样进 Informer(config)
  • 当前 batch 怎样进入 _process(...)
  • 当前代码里的 ProbAttention / ConvLayer / Decoder 到底在哪

这篇新文档就是补这个桥。


1. 论文第一性:Informer 到底在解决什么

Informer 针对的是:

长序列时间序列预测(LSTF, Long Sequence Time-Series Forecasting)

也就是:

  • 看很长的历史 L
  • 预测很长的未来 T

例如:

  • 输入过去 720 个时间步
  • 预测未来 720 个时间步

论文视角下,原始 Transformer 在这个任务上有三个核心问题:

  1. attention 复杂度太高
    • O(L^2)
  2. 序列太长,显存和中间张量太大
  3. 自回归 decoder 在长 horizon 下容易慢且误差累积

所以 Informer 的三把“手术刀”就是:

  1. ProbSparse attention
  2. Self-attention distilling
  3. Generative style decoder

2. 论文总图,放回当前代码树里看

2.1 论文视角的总图

2.2 放回当前代码主线后的总图

这张图的关键点是:

  • 论文里的三大改动,并不是悬在空中的概念
  • 它们在当前代码里分别挂在:
    • Encoder 内的 attention
    • Encoder 内的 ConvLayer
    • _process + Decoder 这条预测链

3. 改动一:ProbSparse Attention

3.1 论文里它想解决什么

论文里的问题是:

不是每个 query 都值得和所有 key 完整计算 attention。

论文观察是:

  • 大多数 query 的注意力分布接近平均
  • 只有少数 query 是“活跃”的

所以做法变成:

  • 先估计哪些 query 值得细算
  • 只对这些 top query 做完整 attention
  • 其余 query 用默认 context 近似代替

3.2 它在当前代码里落在哪

代码位置:

最关键的函数:

  • AttentionLayer.forward(...)
  • ProbAttention.forward(...)
  • _prob_QK(...)
  • _get_initial_context(...)
  • _update_context(...)

3.3 你现在该怎么理解它

论文语言:

  • 稀疏 query
  • top-u query
  • 近似 KL / 稀疏度度量

代码语言:

  • scores_top
  • index
  • context
  • 只更新 top query 对应位置

也就是说,论文里的:

“只保留重要 query 做精算”

在代码里具体变成:

text
_prob_QK
-> 找 top query
-> 先给所有 query 一个默认 context
-> 只把 top query 的 context 改写成真正 attention 结果

3.4 当前应该从哪几篇接着读

按顺序:

  1. 04C-Encoder主链
  2. 04C-1-AttentionLayer
  3. 04C-2-ProbAttention

4. 改动二:Self-attention Distilling

4.1 论文里它想解决什么

论文里的问题是:

Encoder 里如果每层都保持完整长度,长序列会让计算和显存越来越贵。

所以 Informer 的想法是:

  • attention 之后不必永远保持原长度
  • 可以逐层把序列压短
  • 只保留更浓缩的表示

4.2 它在当前代码里落在哪

代码位置:

当前真实配置里:

  • distil = True
  • e_layers = 2

所以当前真正走的是:

text
EncoderLayer 1
-> ConvLayer distil
-> EncoderLayer 2
-> LayerNorm

4.3 你现在该怎么理解它

论文语言:

  • distilling
  • pyramid encoder
  • sequence length halving

代码语言:

  • ConvLayer.forward(...)
  • MaxPool1d(stride=2)
  • 序列长度缩短

也就是说,论文里的:

“蒸馏后长度逐步减半”

在代码里具体挂到:

text
ConvLayer
-> conv1d
-> batchnorm / activation
-> maxpool(stride=2)
-> L 变短

4.4 当前应该从哪几篇接着读

按顺序:

  1. 04C-Encoder主链
  2. 看其中的 ConvLayer 代码段和 toy 例子

5. 改动三:Generative Style Decoder

5.1 论文里它想解决什么

论文里的问题是:

原始 Transformer decoder 常按自回归方式一步一步预测,长 horizon 下慢而且误差累积。

Informer 的做法是:

  • 不是一步步喂前一步预测值
  • 而是一次性喂一个 decoder 输入模板
  • 再一次性输出整段未来结果

5.2 它在当前代码里落在哪

这点最容易和“只看论文”时的理解脱节。

在当前代码里,这个改动不是只落在 Decoder 一个类里,而是分散在两处:

  1. _process(...)
    • 决定 decoder 输入怎么构造
  2. Decoder.forward(...)
    • 负责真正把 decoder 输入和 encoder 上下文融合后投影成输出

对应文档:

5.3 当前代码里具体发生了什么

_process(...) 里:

text
target
-> 取前 label_len 段真实值
-> 拼上 pred_len 段零占位
-> 得到 x_dec

也就是:

  • decoder 前半段看到真实历史尾部
  • decoder 后半段是未来占位
  • 然后一次性跑完整个 decoder

这就是论文里所谓的:

generative style decoder

5.4 当前应该从哪几篇接着读

按顺序:

  1. 02-Level2-数据进入Informer
  2. 04D-Decoder主链

6. 论文整体架构,对应到当前运行链的哪几段

论文模块论文想解决的问题当前代码位置当前文档
Input Representation原始值 + 时间信息怎样表示DataEmbedding04B-DataEmbedding
ProbSparse Self-Attention减少 attention 计算量AttentionLayer + ProbAttention04C-1-AttentionLayer, 04C-2-ProbAttention
Self-attention Distilling压缩 encoder 序列长度ConvLayer04C-Encoder主链
Generative Decoder一次性预测整段未来_process + Decoder02-Level2-数据进入Informer, 04D-Decoder主链
Final Prediction取最后 pred_lenshort_forecast 末尾03-Level3-forward主链

7. 现在应该怎么读这组文档

如果你想保持“论文 -> 代码”的视角,顺序建议不是直接按 01 -> 09 硬读,而是:

第一轮:先从论文三大改动入手

  1. 先读这篇
  2. 再读:

第二轮:再回到真实运行链

  1. 01-Level1-配置进入Informer
  2. 02-Level2-数据进入Informer
  3. 03-Level3-forward主链
  4. 09-Informer全览流程图收束

这样你会得到两条互相咬合的线:

  • 论文线:为什么这么设计
  • 运行线:代码实际怎么跑

8. 这篇和旧笔记的关系

旧笔记里最有价值、应该继续保留的部分是:

  1. 对 LSTF 问题本身的第一性理解
  2. 对三大改动的动机解释
  3. ProbSparse / Distilling / Generative Decoder 的论文级直觉
  4. 你当时写下来的大矩阵推导和长篇数学演变

但当前 modelread 更重视的是:

  • 当前命令怎样进 Informer
  • 当前 batch 怎样进 x_enc / x_dec
  • 当前代码里的模块怎样真正落地

所以关系应该这样定:

旧笔记保留“论文原理的深度”; 当前 modelread 负责“把这些原理挂回真实代码和真实运行链”。


9. 最后压成 5 句话

  1. Informer 论文的第一性是:解决长序列预测里原始 Transformer 太慢、太大、太自回归的问题。
  2. 论文里的三大改动,当前代码里分别落到:ProbAttentionConvLayer_process + Decoder
  3. 只看论文会懂“为什么要改”;只看代码会懂“怎么实现”;这篇负责把两者接起来。
  4. 当前最重要的不是继续背论文公式,而是把论文里的模块名和当前代码对象一一对上。
  5. 这篇之后,再回头读 04B / 04C / 04D,你就不会只是在读代码块,而是在读 Informer 论文的具体实现。

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