Appearance
收束 — Non-stationary Transformer 端到端总结
一、端到端 Mermaid 流程图
二、Tensor 变化汇总表
| 步骤 | 操作 | 输出 shape |
|---|---|---|
| 0 | 输入 x_enc | (2, 12, 5) |
| 1 | x_raw = clone().detach() | (2, 12, 5) |
| 2 | mean_enc = .mean(1, keepdim=True).detach() | (2, 1, 5) |
| 3 | x_enc - mean_enc | (2, 12, 5) |
| 4 | std_enc = sqrt(var + 1e-5).detach() | (2, 1, 5) |
| 5 | x_enc / std_enc → x_enc_norm | (2, 12, 5) |
| 6 | tau_learner(x_raw, std_enc) | (2, 1) |
| 7 | .exp() → τ | (2, 1) |
| 8 | delta_learner(x_raw, mean_enc) → δ | (2, 12) |
| 9 | x_enc_norm[:,-6:,:] cat zeros(4) → x_dec_new | (2, 10, 5) |
| 10 | enc_embedding(x_enc_norm, x_mark_enc) | (2, 12, 8) |
| 11 | Encoder(2×EncoderLayer,DSAttention,τ/δ 注入) | (2, 12, 8) |
| 12 | dec_embedding(x_dec_new, x_mark_dec) | (2, 10, 8) |
| 13 | DecoderLayer.self_attention(τ, δ=None) | (2, 10, 8) |
| 14 | DecoderLayer.cross_attention(τ, δ) | (2, 10, 8) |
| 15 | DecoderLayer FFN + LayerNorm | (2, 10, 8) |
| 16 | Decoder.projection Linear(8→5) | (2, 10, 5) |
| 17 | × std_enc + mean_enc(反归一化) | (2, 10, 5) |
| 18 | [:, -4:, :](forward 截取) | (2, 4, 5) |
三、DSAttention 内部 Tensor 变化
| 步骤 | 操作 | shape |
|---|---|---|
| a | queries/keys/values 输入 AttentionLayer | (2, 12, 8) each |
| b | Linear 投影 → view 多头拆分 | (2, 12, 4, 2) each |
| c | tau.unsqueeze(1).unsqueeze(1) | (2, 1, 1, 1) |
| d | delta.unsqueeze(1).unsqueeze(1) | (2, 1, 1, 12) |
| e | einsum("blhe,bshe→bhls") | (2, 4, 12, 12) |
| f | × tau + delta → scores | (2, 4, 12, 12) |
| g | scale × scores → softmax → A | (2, 4, 12, 12) |
| h | einsum("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() 将任意实数映射到
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)。
五、跨模型核心对比
| 维度 | Informer | Autoformer | FEDformer | Non-stationary | iTransformer |
|---|---|---|---|---|---|
| 核心问题 | 效率 | 周期性缺失 | 局部分解 | 过平稳化 | 排列不变性 |
| 注意力类型 | ProbSparse | Auto-Correlation | 频域稀疏 | DSAttention | 倒置 Full-Attn |
| 归一化 | 无(或简单) | 序列分解 | 序列分解 | Instance Norm + 统计量恢复 | Instance Norm + .detach() |
| 非平稳信息 | 丢失 | 部分保留(trend) | 部分保留 | 主动恢复(τ/δ) | 截断梯度,不恢复 |
| token 语义 | 时间步 | 时间步 | 时间步 | 时间步 | 变量 |
| 唯一新组件 | ProbAttention | AutoCorrelation | FourierBlock | Projector | 倒置 Embedding |
六、检验问题
- 理解检验
- tau 乘在 score 上,delta 加在 score 上——从 softmax 的角度分别影响什么?(尖锐度 vs 位置偏置)
- Projector 里 Conv1d 的 in_channels=seq_len 是什么意思?为什么不用 Linear 直接压缩时间轴?
- delta shape 是 (B, seq_len),为什么 decoder self-attention 里 delta=None,而 cross-attention 里 delta 正常传?
- Non-stationary 和 DUET 都在解决分布问题——Non-stationary 处理的是"过平稳化",DUET 处理的是"分布漂移",两者有什么本质区别?
- 反归一化
dec_out × std_enc + mean_enc中,std_enc shape (2,1,5) 是在哪个时间步上计算的标准差?为什么可以广播到 pred_len=4 步的输出?
创建:2026-04-26 · BFS 精读文档(完整版)