Skip to content

Layer 2C — Decoder(调度层)

父层(Layer 1)步骤⑤:decoder(dec_out, enc_out, x_mask=None, cross_mask=None)
本文档只覆盖 Decoder.forward 这一层(循环调度 + LayerNorm + projection)。
子层 DecoderLayer 及以下见 03C1-Layer3-DecoderLayer


1. 在父层中的位置

long_forecast()
  ├─ ④ encoder(enc_out) → (3,6,8)
  └─ ⑤ dec_out = self.decoder(dec_out, enc_out)   ← 本文档
          ├─ DecoderLayer × d_layers=1             → 详见 Layer3
          ├─ LayerNorm(8)
          └─ projection Linear(8→6)
          → (3, 12, 6)

2. I/O 接口定义

python
def forward(self, x, cross, x_mask=None, cross_mask=None, tau=None, delta=None):
shape(toy)含义
输入 x(dec_out)(3, 12, 8) = (B, dec_len, d_model)decoder embedding 输出,含 label_len+pred_len
输入 cross(enc_out)(3, 6, 8) = (B, enc_seq, d_model)encoder 最终输出(distilling 后 seq=6)
输出(3, 12, 6)projection 后的完整 decoder 输出;long_forecast() 再取后 pred_len=7

x_mask / cross_mask / tau / delta 全为 None,原样透传给 DecoderLayer。


3. 顺序图(具体层)


4. 语义分组图(索引层)

Decoder 只做"管理":迭代调度 DecoderLayer → 收尾 LayerNorm → 投影到输出维度。


5. 逐步解析

5.0 完整原始代码

python
def forward(self, x, cross, x_mask=None, cross_mask=None, tau=None, delta=None):
    for layer in self.layers:
        x = layer(x, cross, x_mask=x_mask, cross_mask=cross_mask,
                  tau=tau, delta=delta)

    if self.norm is not None:
        x = self.norm(x)

    if self.projection is not None:
        x = self.projection(x)
    return x

5.1 循环调度

本节的作用

循环调用 d_layers=1 个 DecoderLayer,每次把 decoder token x 和固定的 encoder 输出 cross 一起传入,返回的新 x 携带历史信息。

python
for layer in self.layers:
    x = layer(x, cross, x_mask=x_mask, cross_mask=cross_mask,
               tau=tau, delta=delta)

self.layersnn.ModuleList([DecoderLayer_0]),toy 里 d_layers=1 只循环一次。每次把 x(decoder token)和 cross(encoder 输出)同时传给 DecoderLayer,返回的新 x 覆盖旧值。

cross 在整个循环中保持不变——所有 DecoderLayer 都读同一份 encoder 输出。

x: (3,12,8) + cross: (3,6,8) → DecoderLayer 0 → x: (3,12,8)

Generative Decoder 并行生成原理:decoder 输入的后 pred_len=7 步是全零占位,每步在 cross-attention 中同时向 encoder 检索历史信息,整个 pred_len 一次性并行输出,而非逐步 autoregressive 生成。

DecoderLayer 的内部三段式见 03C1-Layer3-DecoderLayer


5.2 最终归一化 + projection

本节的作用

所有 DecoderLayer 跑完后,self.norm 对输出序列做最终归一化,self.projection 将隐层维度映射回原始变量数。两者均在 Informer.py 构造 Decoder 时注入。

初始化来源(Informer.py:102-103

python
norm_layer=torch.nn.LayerNorm(configs.d_model),
projection=nn.Linear(configs.d_model, configs.c_out, bias=True),

toy:self.norm = LayerNorm(8)self.projection = Linear(8, 6, bias=True),参数名是 c_out=6(输出变量数)而非 enc_in——两者数值相同但语义不同:enc_in 是 encoder 输入通道数,c_out 是 decoder 输出通道数。

原始代码

python
if self.norm is not None:
    x = self.norm(x)

if self.projection is not None:
    x = self.projection(x)
return x

self.norm — 序列级最终 LayerNorm

LayerNorm(d_model=8) 对每个 token 的 8 维特征向量独立归一化,形状 (3,12,8) 不变。作用于最后一维,前两维 (B, dec_len) 视为独立的归一化单位。

self.projection — 维度投影

nn.Linear(in_features=8, out_features=6, bias=True)。公式:

output[b,t,:]=x[b,t,:]WT+b,WR6×8, bR6

nn.Linear 仅作用于最后一维,(3, 12) 共 36 个 token 各自独立做 6×8 线性变换,最终组织回 (3, 12, 6)

toy 数值:设 x[0,0,:] = [0.3, -0.1, 0.5, -0.2, 0.4, -0.3, 0.2, -0.4](LayerNorm 后),W[0,:] = [0.1, 0.2, -0.1, 0.3, -0.2, 0.1, 0.4, -0.3]b[0] = 0.05

output[0,0,0]=0.3×0.1+(0.1)×0.2+0.5×(0.1)+(0.2)×0.3+0.4×(0.2)+(0.3)×0.1+0.2×0.4+(0.4)×(0.3)+0.050.05

最终 Decoder.forward 返回 (3, 12, 6),父层 long_forecast()[:, -pred_len:, :] = (3, 7, 6) 作预测输出。


DecoderLayer 已有三次 LayerNorm,外层 Decoder 为什么还要再加一个?

这不是重复,而是 Post-LN Transformer 的两级归一化设计:

第一级:子块级归一化(DecoderLayer 内部)
norm1(self-attn 之后)、norm2(cross-attn 之后)、norm3(FFN 之后)——每个残差子块做完立刻归一化,控制残差叠加不爆炸。它们保证的是"当前子块的输出在一个合理范围",而不是整个 DecoderLayer 的输出。

第二级:层序列级归一化(Decoder 外层)
d_layers 个 DecoderLayer 串联后,残差累积效果与 d_layers=1 时不同——层数越多,输出的 DC 偏置越大。外层 self.norm 在所有层跑完后统一标准化,让 projection 接收到稳定的输入,权重学习不受层数变化的影响。

Encoder 侧完全对称:EncoderLayer 内部有 norm1/norm2(子块级),Encoder 外层有 norm(序列级)——这份标准化后的 encoder 输出是 cross-attention 的 K/V,稳定的 K/V 对 cross-attention 的梯度流动至关重要。

归一化位置作用对象作用
norm1/norm2(EncoderLayer 内部)每个残差子块控制残差累加,防梯度爆炸
norm(Encoder 外层)全部 EncoderLayer 跑完后的序列稳定 cross-attn 的 K/V 来源
norm1/norm2/norm3(DecoderLayer 内部)每个残差子块同 EncoderLayer
norm(Decoder 外层)全部 DecoderLayer 跑完后的序列稳定 projection 的输入

6. 下钻子组件

子组件职责下层文档
DecoderLayerlayer三段式:masked self-attn + cross-attn + FFN,各带残差03C1-Layer3-DecoderLayer

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