一句话总结:残差连接在子层旁边留出一条恒等路径,让信息和梯度不必只走变换分支,因此深层网络更容易优化;Dropout 则在训练时随机把一部分激活值置零,作为一种可选的正则化手段。


13.1 回顾:Transformer Block 的结构

在深入残差连接和 Dropout 之前,让我们先把一个 Pre-Norm decoder block 写成最紧凑的形式:

u = X + Dropout(Attention(LayerNorm(X)))
y = u + Dropout(FFN(LayerNorm(u)))

Attention 和 FFN 各有一条残差路径,所以这里有两次相加。图中的两次 Dropout 是一种常见训练配置,并不是 Transformer 的硬性规定:有些模型还会对 attention weights 或输入嵌入使用 Dropout,也有些大模型把 Dropout 率设为 0。GPT-2 这类 Pre-Norm 模型还会在整叠 Block 之后再放一个最终 Norm;它不属于单个 Block 内的这两次相加。


13.2 残差连接:信息的"高速公路"

13.2.1 深度网络的问题

Pre-Norm Transformer 中的两条残差路径,以及恒等路径如何帮助梯度传播

网络变深以后,优化会变得困难。反向传播要连续乘上许多层的 Jacobian;这些乘积可能让梯度变得很小,也可能让它变得很大。深层网络还可能出现“多加几层,训练误差反而更高”的退化问题。残差连接不能包治所有这些问题,但它给优化器多留了一条简单路径。

想象信息从第 1 层传到第 12 层:

Layer 1 → Layer 2 → Layer 3 → ... → Layer 12

如果每一层都只有一条变换路径,信息和梯度就必须连续穿过所有变换。层数一多,这条乘法链就会很难训练。

13.2.2 残差连接的解决方案

残差连接的核心思想非常简单:让输入可以直接"跳过"某些层。

输入 X ─────────────────────┐
    ↓                       │
  Layer                     │(跳跃连接)
    ↓                       │
  输出 ←────────────────────┘ + X

公式表示:

输出 = Layer(X) + X

不是只输出 Layer(X),而是加上原始输入 X。

13.2.3 图解残差连接

看图中右侧的教学数值(用来说明逐元素相加,并不是某个已发布模型的运行日志):

Attention 输出(经过 Dropout 后):

[4, 16, 512] 的张量
第一个值:-0.07005, 0.09600, 0.03522, ...

原始输入 X:

[4, 16, 512] 的张量
第一个值:0.50748, -1.96800, 5.14941, ...

残差连接后:

输出 = Attention输出 + X
     = [-0.07005 + 0.50748, 0.09600 + (-1.96800), ...]
     = [0.43743, -1.87200, ...]

就是简单的逐元素相加!

13.2.4 为什么残差连接有效?

1. 梯度直通

设 y=x+F(x)y=x+F(x),用向量写法,反向传播是:

∇xL=(I+JF(x))T∇yL\nabla_x \mathcal{L} = \left(I + J_F(x)\right)^T \nabla_y \mathcal{L}

这里的 II 是恒等路径带来的直接项,JFJ_F 是变换分支的 Jacobian。它通常会改善梯度传播;但它不保证梯度永不消失或永不爆炸,因为两条分支仍可能相互抵消,很多层的乘积也仍然重要。

2. 恒等映射

如果某一层"不知道该学什么",它可以学习成恒等映射:

Layer(X) ≈ 0
输出 = 0 + X = X

相当于这一层"什么都不做",信息原封不动传过去。这比学习一个完美的恒等变换容易多了。

3. 信息保留

每个 Block 都把子层输入直接加到更新量上,因此模型不必在每一层都重新构造恒等映射。这提供了信息的直通路径,但不意味着最初的输入在任意深度都能被完整还原——后续更新仍会不断修改 residual stream。

13.2.5 在 Transformer 中的位置

图中左侧的架构图清楚地标注了两个残差连接的位置:

第一个残差连接:在 Attention 之后

X → LayerNorm → Attention → Dropout → (+X) → 输出1

第二个残差连接:在 FFN 之后

输出1 → LayerNorm → FFN → Dropout → (+输出1) → 输出2

13.2.6 PyTorch 实现

from torch import nn

class TransformerBlock(nn.Module):
    def __init__(self, d_model, num_heads, d_ff, dropout=0.1):
        super().__init__()
        self.attention = MultiHeadAttention(d_model, num_heads)
        self.ffn = FeedForward(d_model, d_ff)
        self.norm1 = nn.LayerNorm(d_model)
        self.norm2 = nn.LayerNorm(d_model)
        self.dropout1 = nn.Dropout(dropout)
        self.dropout2 = nn.Dropout(dropout)

    def forward(self, x, mask=None):
        # 第一个残差连接
        attn_output = self.attention(self.norm1(x), mask)
        x = x + self.dropout1(attn_output)  # 残差连接!

        # 第二个残差连接
        ffn_output = self.ffn(self.norm2(x))
        x = x + self.dropout2(ffn_output)   # 残差连接!

        return x

这里沿用前面章节定义的 MultiHeadAttention 和 FeedForward。核心就是那两行 x = x + ...;两个 Dropout 实例也让配置和调试更清楚。


13.3 Dropout:用随机置零做正则化

13.3.1 过拟合问题

训练时的 inverted Dropout:随机掩码、按保留率缩放,以及推理时直通

神经网络有一个常见问题:过拟合。

过拟合是指模型在训练数据上表现很好,但在新数据上表现很差。就像一个学生:

  • 把所有考试题都背下来了(训练数据)
  • 但遇到新题就不会做(测试数据)

模型"记住"了训练数据的细节,而不是学到了通用的规律。

13.3.2 Dropout 的解决方案

Dropout 的想法很有趣:训练时随机把激活张量中的一些元素置零。

每次 forward pass 都会重新采样掩码。这里没有删除权重,也没有永久关闭某个神经元;下一次 forward pass,被置零的位置通常会不同。

13.3.3 Dropout 的直觉

为什么随机置零一部分激活值可能缓解过拟合?

类比:团队协作

想象一个公司:

  • 没有 Dropout:某个员工特别能干,所有工作都依赖他
  • 有 Dropout:每天随机让一些员工休假

结果:

  • 没有 Dropout:如果那个能干的员工离职,公司就瘫痪了
  • 有 Dropout:每个员工都学会了多种技能,团队更健壮

在神经网络中,这个类比想表达的是:Dropout 会扰动固定的协作关系,抑制过强的 co-adaptation。它是一种随机正则化,不保证每个神经元真的“独立工作”,也不保证在所有数据集和模型上都能改善泛化。

13.3.4 Dropout 的数学

Dropout 的操作很简单:

设丢弃率为 pp,保留率为 q=1−pq=1-p。PyTorch 使用的是 inverted Dropout:

mi∼Bernoulli⁡(q),yi=mixiqm_i \sim \operatorname{Bernoulli}(q), \qquad y_i = \frac{m_i x_i}{q}

例如,dropout_rate = 0.1。下面五个位置里恰好丢了一个;这是一次随机抽样,并不是说每一小组都必须精确丢 10%:

input = [0.5, 0.3, 0.8, 0.2, 0.6]
mask  = [1,   1,   0,   1,   1  ]  # 随机生成,0.8 被丢弃
output = [0.5, 0.3, 0, 0.2, 0.6] / 0.9
       = [0.56, 0.33, 0, 0.22, 0.67]

推理时:

output = input  # 不做任何丢弃

13.3.5 为什么要缩放?

你可能注意到训练时有个 / (1 - dropout_rate) 的缩放。

原因:对每个固定输入元素,保持期望值不变。

假设 dropout_rate = 0.1:

  • 训练时:每个激活值平均有 90% 的概率保留;保留下来的值放大 1/0.9 ≈ 1.11
  • 推理时:所有激活值直接通过,不再缩放

因此 E[yi∣xi]=xi\mathbb{E}[y_i\mid x_i]=x_i。这里保持的是逐元素条件期望,不是保证每次抽样的向量范数都不变。

13.3.6 在 Transformer 中的位置

在本章这套简化的 residual Dropout 配置里,位置是:

  1. Attention 之后:Attention → Dropout → 残差连接
  2. FFN 之后:FFN → Dropout → 残差连接

也就是先扰动子层的更新量,再与 residual stream 相加。原始 Transformer 还对 embedding 与位置编码之和使用 Dropout;不少实现也会对 attention weights 使用另一种 Dropout。还有一些模型完全不用 Dropout,所以不能把“总是在这里”当成所有 Transformer 的普遍定律。

13.3.7 PyTorch 实现

import torch
import torch.nn as nn

x = torch.tensor([0.5, 0.3, 0.8, 0.2, 0.6])
dropout = nn.Dropout(p=0.1)

dropout.train()
train_output = dropout(x)  # 随机掩码;保留下来的值除以 0.9

dropout.eval()
eval_output = dropout(x)  # 与 x 相同

如果 Dropout 是某个 model 的子模块,调用 model.train() / model.eval() 会递归切换它的模式;单独拿一个 Dropout 层演示时,则像上面这样直接切换它。


13.4 Pre-Norm vs Post-Norm

13.4.1 两种 LayerNorm 位置

一个重要的架构选择,是 Norm 放在 residual addition 的哪一边:

Post-Norm(原始 Transformer,2017):

u = LayerNorm(X + Dropout(Attention(X)))
y = LayerNorm(u + Dropout(FFN(u)))

LayerNorm 在残差连接之后。

Pre-Norm(GPT-2 使用的布局):

u = X + Dropout(Attention(LayerNorm(X)))
y = u + Dropout(FFN(LayerNorm(u)))

LayerNorm 在残差连接之前(在每个子层的输入处)。

GPT-2 还在整叠 Block 的最后加了一个最终 LayerNorm。LLaMA 延续的是 Pre-Norm 的位置关系,但把 LayerNorm 换成了 RMSNorm。

13.4.2 为什么 Pre-Norm 常见?

Pre-Norm 的恒等路径不经过 Norm。理论分析和实践都表明,它在初始化时通常有更规整的梯度,对很深的堆叠更容易优化,也能降低对精细 warmup 的依赖。

但这不是“Pre-Norm 在任何意义上都更好”。Post-Norm 配合合适的初始化、warmup 或其他改造也能训练得很好;Pre-Norm 自己也可能出现 residual stream 尺度随深度增长等问题。现代模型还有 RMSNorm、并行分支和其他 Norm 布局。因此更准确的说法是:Pre-Norm 是现代 decoder-only LLM 的常见起点,而不是唯一标准答案。


13.5 残差连接 + Dropout 的协同作用

13.5.1 完整的数据流

让我们追踪一次完整的数据流:

输入 X [4, 16, 512]
        ↓
LayerNorm(X)                    # 标准化
        ↓
Attention(LayerNorm(X))         # 注意力计算
        ↓
Dropout(Attention(...))         # 随机丢弃(训练时)
        ↓
X + Dropout(...)                # 残差连接
        ↓
输出 [4, 16, 512]               # 形状不变

13.5.2 为什么这个组合有效?

技术解决的问题机制
残差连接深层优化困难提供恒等信息与梯度路径
Dropout过拟合风险用随机掩码做可选正则化
Norm激活尺度与训练动态在每个 token 的特征维度上控制尺度

三者配合:

  1. LayerNorm 稳定输入
  2. Attention/FFN 学习特征
  3. 如果配置了 Dropout,它对更新量增加随机正则化
  4. 残差连接把更新量加回 residual stream

这里真正接近架构必需品的是 residual path 和某种稳定化方案;Dropout 是否有益要看模型、数据和训练目标,不能把三者写成“缺一不可”。


13.6 实际训练中的参数

13.6.1 常见的 Dropout 率

公开训练配方Dropout 率备注
原始 Transformer base0.1residual 与 embedding/position 的和
BERT0.1论文中的预训练与微调配置
LLaMA0.0参考实现的 Block 不使用 Dropout

这几行不能推出“模型越大,Dropout 一定越低”。Dropout 率是训练配方的一部分,受数据规模与重复度、训练时长、任务、其他正则化以及优化稳定性共同影响。大规模自回归预训练有时会选择 0,但微调或较小数据集完全可能需要重新调参。

13.6.2 残差连接的变体

有些模型会在残差连接上做一些变化:

缩放 residual branch(示意):

x = x + alpha * sublayer(x)

门控残差:

gate = sigmoid(linear(x))
x = x + gate * sublayer(x)  # 学习残差的权重

不同方法会固定、初始化或学习 alpha,门控形式也各不相同。原始 Transformer 使用直接相加;后来的模型不一定都坚持这一种形式,所以这里的代码只用来说明设计空间。


13.7 本章总结

13.7.1 核心概念

概念作用公式
残差连接改善深层优化,提供恒等路径output = x + F(x)
Dropout可选的随机正则化训练时随机置零并按 keep rate 缩放
Pre-Norm常见、较易优化的布局Norm 在子层之前,整叠之后通常还有最终 Norm

13.7.2 在 Transformer Block 中的位置

输入 X
    ↓
LayerNorm ──→ Attention ──→ Dropout ──→ (+X) ──→ 输出1
                                         ↑
                                    残差连接

输出1
    ↓
LayerNorm ──→ FFN ──→ Dropout ──→ (+输出1) ──→ 输出2
                                     ↑
                                残差连接

13.7.3 核心认知

残差连接让每个子层学习“在现有 residual stream 上加什么”,而不是每次都从头重写全部表示;恒等路径通常让深层网络更容易优化。Dropout 则是在训练配方需要时,对激活施加随机掩码来正则化。它们作用不同,而且 Dropout 不是每个 Transformer 都必须有。


本章交付物

学完这一章,你应该能够:

  • 解释残差连接为什么通常改善梯度传播,以及它为什么不是绝对保证
  • 理解 inverted Dropout 的随机掩码、缩放和训练/推理差异
  • 说出残差连接和 Dropout 在 Transformer Block 中的位置
  • 区分 Pre-Norm 和 Post-Norm 的区别

下一章预告

每个 Block 的残差连接加回的是该子层当前的输入,不是永远加回最初的词嵌入。不过在第一个 Block 之前,residual stream 的起点确实来自 词嵌入(Embedding) 和 位置编码(Positional Encoding) 的结合。

下一章,我们来深入理解词嵌入和位置信息是如何结合的,以及这种设计背后的深层逻辑。

引用本文 / Cite
Zhang, Wayland (2026). 第 13 章:残差连接与 Dropout - 训练稳定的秘密. In Transformer 架构:从直觉到实现. https://waylandz.com/llm-transformer-book/%E7%AC%AC13%E7%AB%A0-%E6%AE%8B%E5%B7%AE%E8%BF%9E%E6%8E%A5%E4%B8%8EDropout-%E8%AE%AD%E7%BB%83%E7%A8%B3%E5%AE%9A%E7%9A%84%E7%A7%98%E5%AF%86/
@incollection{zhang2026transformer_13_-_Dropout-,
  author = {Zhang, Wayland},
  title = {第 13 章:残差连接与 Dropout - 训练稳定的秘密},
  booktitle = {Transformer 架构:从直觉到实现},
  year = {2026},
  url = {https://waylandz.com/llm-transformer-book/%E7%AC%AC13%E7%AB%A0-%E6%AE%8B%E5%B7%AE%E8%BF%9E%E6%8E%A5%E4%B8%8EDropout-%E8%AE%AD%E7%BB%83%E7%A8%B3%E5%AE%9A%E7%9A%84%E7%A7%98%E5%AF%86/}
}