⚖️ Pre-LN vs Post-LN 结构对比卡片

Pre-LN(层归一化在子层输入之前)
① LayerNorm①(子层前)
x_n=(x-μ)/√(σ²+ε)·γ+β 维度保持(B,N,D)
② 多头自注意力(7步完整展开)
步骤1-整体QKV投影: Q=X·W_Q,K=X·W_K,V=X·W_V W_*∈ℝ^(D×D);Q/K/V∈(B,N,D) 步骤2-来源:自注意力 Q/K/V来自同层输入X∈(B,N,D) 步骤3-多头拆分:d_k=D/h Q_i=Q[:,:,i*d_k:(i+1)*d_k] Q_i/K_i/V_i∈(B,N,d_k) reshape等价: Q.reshape(B,N,h,d_k).transpose(1,2) →(B,h,N,d_k) 步骤4-△Q·Kᵀ产生注意力分数 ∈(B,h,N,N);每token对其他的关注度 V_i不参与分数计算 只被分数加权聚合,作为输出值 步骤5-单头计算: head_i=Softmax(Q_i·K_iᵀ/√d_k)·V_i ∈(B,N,d_k);√d_k缩放防梯度消失 步骤6-多头拼接: Concat(head_1..head_h) →(B,N,h*d_k)=(B,N,D) 步骤7-输出投影: ·W_O+b_O,W_O∈ℝ^(D×D) out:(B,N,D)
③ 残差加法①
x←x+attn_out 维度保持(B,N,D)
④ LayerNorm②(第二子层前)
x_n=(x-μ)/√(σ²+ε)·γ+β
⑤ Linear升维
out=x·W+b,W∈ℝ^(D×4D) out:(B,N,4D)
⑥ GELU
GELU(x)=x·Φ(1.702x)
⑦ Linear降维
W∈ℝ^(4D×D) out:(B,N,D)
⑧ 残差加法②
x←x+ffn_out 维度(B,N,D)
x = x + Attn(LN(x))
x = x + FFN(LN(x))
ViT-Base/Large DeiT Swin-T MAE BEiT DINO CaiT GPT-2 LLaMA
Post-LN(层归一化在残差输出之后)
① 多头自注意力(7步展开)
步骤1-整体QKV投影: Q=X·W_Q,K=X·W_K,V=X·W_V W_*∈ℝ^(D×D);Q/K/V∈(B,N,D) 步骤2-来源:自注意力 Q/K/V来自同层输入X∈(B,N,D) 步骤3-多头拆分:d_k=D/h Q_i/K_i/V_i∈(B,N,d_k) reshape→(B,h,N,d_k) 步骤4-△Q·Kᵀ∈(B,h,N,N) 表示每token对其他token的关注度 V_i不参与分数计算 只被加权聚合作为输出值 步骤5-单头: head_i=Softmax(Q_i·K_iᵀ/√d_k)·V_i 步骤6-Concat(h1..hh)→(B,N,D) 步骤7-·W_O+b_O∈ℝ^(D×D) out:(B,N,D)
② 残差加法①
x'←x+attn_out (B,N,D)
③ LayerNorm①(作用在残差之后)
x=(x-μ)/√(σ²+ε)·γ+β
④ Linear升维
W∈ℝ^(D×4D) out:(B,N,4D)
⑤ GELU
GELU(x)=x·Φ(1.702x)
⑥ Linear降维
W∈ℝ^(4D×D) out:(B,N,D)
⑦ 残差加法②
x'←x+ffn_out
⑧ LayerNorm②(第二个残差之后)
x=(x-μ)/√(σ²+ε)·γ+β
x = LN(x + Attn(x))
x = LN(x + FFN(x))
BERT全系 原始Transformer(2017)
对比维度Pre-LNPost-LN
LN位置子层输入前(Attn/FFN之前)残差输出后(每个残差块末尾)
残差路径干净、梯度直通主路经过LN、梯度有缩放
训练稳定性✓ 稳定、可不用warm-up深层不稳定、需要warm-up
最终LNBlock堆叠后额外加一次LN每层末尾已有LN,无需额外加
代表模型ViT / GPT-2 / LLaMA / PaLMBERT全系 / Transformer(2017)
现代偏好✓ 主流、现代大模型首选历史经典、新模型较少采用