Skip to content

收束 — Non-stationary Transformer 端到端总结

一、端到端 Mermaid 流程图


二、Tensor 变化汇总表

步骤操作输出 shape
0输入 x_enc(2, 12, 5)
1x_raw = clone().detach()(2, 12, 5)
2mean_enc = .mean(1, keepdim=True).detach()(2, 1, 5)
3x_enc - mean_enc(2, 12, 5)
4std_enc = sqrt(var + 1e-5).detach()(2, 1, 5)
5x_enc / std_enc → x_enc_norm(2, 12, 5)
6tau_learner(x_raw, std_enc)(2, 1)
7.exp() → τ(2, 1)
8delta_learner(x_raw, mean_enc) → δ(2, 12)
9x_enc_norm[:,-6:,:] cat zeros(4) → x_dec_new(2, 10, 5)
10enc_embedding(x_enc_norm, x_mark_enc)(2, 12, 8)
11Encoder(2×EncoderLayer,DSAttention,τ/δ 注入)(2, 12, 8)
12dec_embedding(x_dec_new, x_mark_dec)(2, 10, 8)
13DecoderLayer.self_attention(τ, δ=None)(2, 10, 8)
14DecoderLayer.cross_attention(τ, δ)(2, 10, 8)
15DecoderLayer FFN + LayerNorm(2, 10, 8)
16Decoder.projection Linear(8→5)(2, 10, 5)
17× std_enc + mean_enc(反归一化)(2, 10, 5)
18[:, -4:, :](forward 截取)(2, 4, 5)

三、DSAttention 内部 Tensor 变化

步骤操作shape
aqueries/keys/values 输入 AttentionLayer(2, 12, 8) each
bLinear 投影 → view 多头拆分(2, 12, 4, 2) each
ctau.unsqueeze(1).unsqueeze(1)(2, 1, 1, 1)
ddelta.unsqueeze(1).unsqueeze(1)(2, 1, 1, 12)
eeinsum("blhe,bshe→bhls")(2, 4, 12, 12)
f× tau + delta → scores(2, 4, 12, 12)
gscale × scores → softmax → A(2, 4, 12, 12)
heinsum("bhls,bshd→blhd") → V_out(2, 12, 4, 2)
i.view(2,12,8) → out_projection(2, 12, 8)

四、核心设计决策回顾

① 为什么 tau 用 .exp(),delta 不用?

tau 需要是正数:乘法因子若为负,会翻转所有注意力分数的符号,使 softmax 分布完全反转,语义混乱。.exp() 将任意实数映射到 (0,+)

delta 是加法偏置,可以正可以负(正值增强关注,负值削弱关注),不需要符号约束。

② 为什么 self-attention 不传 delta,cross-attention 才传?

delta shape 是 (B, seq_len) = (2, 12),经 unsqueeze 后为 (2, 1, 1, 12),对应 scores 的 S(key 序列长度)维度。

Encoder self-attention:Q 和 K 都是 seq_len=12,scores (2,4,12,12),delta 对最后维 S=12 广播 ✅

Decoder self-attention:Q 和 K 都是 dec_len=10,scores (2,4,10,10),delta (2,1,1,12) 的 S=12 ≠ 10 ❌ 维度不匹配

Decoder cross-attention:Q 来自 decoder (dec_len=10),K/V 来自 encoder (seq_len=12),scores (2,4,10,12),delta (2,1,1,12) 对 S=12 广播 ✅

所以 delta 的语义绑定了"encoder key 位置的偏置",只在 key=encoder_output 时有意义。

③ x_dec_new 用归一化后的 x_enc 末段,不用原始 x_dec?

_process() 传入的 x_dec 包含真实历史标签(前 label_len 步),理论上也可以用。但 Non-stationary 选择用归一化后的 enc 末段,原因是:

  • enc_out 和 x_dec_new 需要处于同一分布空间(都是归一化后的空间),否则 cross-attention 的 Q/K 数值尺度不匹配
  • 归一化后的 enc 末段已经通过 encoder 的注意力机制提炼过,质量优于原始标签

④ Projector 的 Conv1d 为什么不用 Linear 直接处理时间轴?

Linear(seq_len=12, 1) 的权重为 (12,)×enc_in=5,没有参数共享,且无法利用"相邻时间步的信息可以局部聚合"的归纳偏置。

Conv1d(in_channels=12, out_channels=1, kernel_size=3) 的权重 (1, 12, 3),等价于"对 enc_in 空间做局部卷积,对 seq_len 维度做加权聚合",kernel_size=3 在变量轴引入局部感受野,比 Linear 更有结构约束。参数量也更少(12×3 = 36 vs 12×5×1 = 60)。


五、跨模型核心对比

维度InformerAutoformerFEDformerNon-stationaryiTransformer
核心问题效率 O(L2)周期性缺失局部分解过平稳化排列不变性
注意力类型ProbSparseAuto-Correlation频域稀疏DSAttention倒置 Full-Attn
归一化无(或简单)序列分解序列分解Instance Norm + 统计量恢复Instance Norm + .detach()
非平稳信息丢失部分保留(trend)部分保留主动恢复(τ/δ)截断梯度,不恢复
token 语义时间步时间步时间步时间步变量
唯一新组件ProbAttentionAutoCorrelationFourierBlockProjector倒置 Embedding

六、检验问题

- 理解检验
  1. tau 乘在 score 上,delta 加在 score 上——从 softmax 的角度分别影响什么?(尖锐度 vs 位置偏置)
  2. Projector 里 Conv1d 的 in_channels=seq_len 是什么意思?为什么不用 Linear 直接压缩时间轴?
  3. delta shape 是 (B, seq_len),为什么 decoder self-attention 里 delta=None,而 cross-attention 里 delta 正常传?
  4. Non-stationary 和 DUET 都在解决分布问题——Non-stationary 处理的是"过平稳化",DUET 处理的是"分布漂移",两者有什么本质区别?
  5. 反归一化 dec_out × std_enc + mean_enc 中,std_enc shape (2,1,5) 是在哪个时间步上计算的标准差?为什么可以广播到 pred_len=4 步的输出?

创建:2026-04-26 · BFS 精读文档(完整版)

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