最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Attention 机制 02 - Add&Norm 残差机制
时间:2026-07-10 09:36:48 编辑:袖梨 来源:一聚教程网
残差连接与 LayerNorm 数值推导:接续 bank 词向量的完整计算过程
步骤 0 — 衔接上一步
上一步自注意力结束后,bank 产生了两个不同的输出向量(句子 A/B)。现在这两个向量要经过残差连接再经过 LayerNorm,才算完成编码器一层的第一个子层。

论文公式写法(每个子层都长这样):
输出 = LayerNorm( x + Sublayer(x) )
其中 x 是子层的输入,Sublayer(x) 是子层(这里是自注意力)的计算结果。
我们手头的三个向量(d_model = 4)
| d₀ | d₁ | d₂ | d₃ | 说明 | |
|---|---|---|---|---|---|
| x(输入) | 0.80 | 0.40 | 0.60 | -0.10 | ← bank 的原始 embedding |
| Attn_A | 0.44 | 0.12 | 0.12 | 0.31 | ← 句子 A 注意力输出(river) |
| Attn_B | 0.32 | 0.19 | 0.28 | 0.23 | ← 句子 B 注意力输出(street) |
步骤 1 — 残差连接:x + Sublayer(x)
做法极简:把注意力输出和原始输入逐元素相加。
residual = x + Attn(x)
句子 A 的计算
x = [0.80, 0.40, 0.60, -0.10]
Attn_A = [0.44, 0.12, 0.12, 0.31]
─────────────────────────────
res_A = [1.24, 0.52, 0.72, 0.21] ← 残差结果
句子 B 的计算
x = [0.80, 0.40, 0.60, -0.10]
Attn_B = [0.32, 0.19, 0.28, 0.23]
─────────────────────────────
res_B = [1.12, 0.59, 0.88, 0.13]
步骤 2 — 为什么需要残差连接?
这是一个设计选择,不是数学必须。但它解决了一个训练层数越多越容易失败的根本问题。
问题:梯度消失
神经网络靠反向传播来学习:计算损失对每个参数的梯度,然后更新参数。梯度从最后一层往前传,每经过一层都要乘以那一层的导数。
如果导数普遍小于 1,乘 6 次之后梯度就会变得极小——趋近于 0。参数几乎不更新,网络学不动了。这叫梯度消失。
没有残差 vs. 有残差的梯度对比
没有残差连接
输出 = F(x)
∂Loss/∂x = ∂Loss/∂F · ∂F/∂x
梯度只能走"穿过 F"这一条路。如果 F 的导数小,梯度就衰减。6 层叠下来,第 1 层收到的梯度可能已经乘了六次小数 → 接近 0。
| 层 | 梯度保留比例 |
|---|---|
| 层 6 | 1.000 |
| 层 5 | 0.600 |
| 层 4 | 0.360 |
| 层 3 | 0.216 |
| 层 2 | 0.130 |
| 层 1 | 0.078 |
有残差连接
输出 = x + F(x)
∂Loss/∂x = ∂Loss/∂输出 · (1 + ∂F/∂x)
导数里多了一个 +1。即使 ∂F/∂x 趋近于 0,整个导数还剩 1——梯度可以"原封不动"地穿过这一层继续往前传。
| 层 | 梯度保留比例 |
|---|---|
| 层 6 | 1.000 |
| 层 5 | 0.970 |
| 层 4 | 0.941 |
| 层 3 | 0.913 |
| 层 2 | 0.885 |
| 层 1 | 0.858 |
残差连接由 ResNet(2015,图像识别)引入,Transformer 直接借用了这个设计。它是让网络能堆到 6 层、甚至后来几百层的关键。
步骤 3 — Layer Normalization
残差之后,向量要过 LayerNorm。它把向量重新拉到均值 0、方差 1 附近,然后用两个可学习参数微调。
LayerNorm(z) = γ · (z − μ) / (σ + ε) + β
符号含义
| 符号 | 含义 |
|---|---|
| z | 输入向量(这里是残差结果) |
| μ | z 各维度的均值 |
| σ | z 各维度的标准差 |
| ε | 极小数(防止除以 0,取 1e-6) |
| γ | 可学习缩放参数(初始化为 1) |
| β | 可学习偏移参数(初始化为 0) |
对句子 A 的 res_A = [1.24, 0.52, 0.72, 0.21] 完整计算
第一步:算均值 μ
μ = (1.24 + 0.52 + 0.72 + 0.21) / 4
= 2.69 / 4
= 0.6725
第二步:算方差 σ²,再开方得 σ
各分量减均值: [0.568, -0.153, 0.048, -0.463]
各分量平方: [0.323, 0.023, 0.002, 0.214]方差 σ² = (0.323 + 0.023 + 0.002 + 0.214) / 4 = 0.1405
标准差 σ = √0.1405 ≈ 0.3748
第三步:归一化 (z − μ) / (σ + ε)
z_norm = [0.568, -0.153, 0.048, -0.463] / 0.3748
≈ [1.516, -0.408, 0.128, -1.235]
第四步:乘 γ 加 β(初始 γ=1,β=0,训练后会变)
LN_A = 1 × [1.516, -0.408, 0.128, -1.235] + 0
= [1.516, -0.408, 0.128, -1.235]
步骤 4 — 为什么需要 LayerNorm?
归一化是为了稳定训练。我们来看不 Norm 会发生什么。
问题:Internal Covariate Shift(内部协变量偏移)
每一层的输出分布会随着训练变化——前一层参数一更新,后一层收到的输入分布就变了,后一层又得重新适应新分布。层数越多,这种"地基不停动"的现象越严重,导致训练不稳、需要极小的学习率、收敛慢。
归一化把每一层的输入强制拉到稳定的分布(μ≈0,σ≈1),让后面的层不用操心"输入的尺度变了"这件事,可以安心学习真正有用的特征变换。
LayerNorm vs BatchNorm — 为什么 Transformer 选 LayerNorm
| BatchNorm(CNN 常用) | LayerNorm(Transformer 用) | |
|---|---|---|
| 归一化方向 | 同一维度、跨 batch 内所有样本 | 同一个样本、跨所有维度 |
| batch 依赖 | 需要足够大的 batch 才统计稳定 | 和 batch 大小无关 |
| 序列长度 | 序列长度不固定时,跨样本对齐很麻烦 | 和序列长度无关 |
| 推理阶段 | 需要维护"移动均值" | 训练推理行为完全一致,无移动统计量负担 |
γ 和 β 为什么要可学习?
纯归一化会破坏向量原有的信息——比如某个维度本来就应该比其他维度大。γ 和 β 让模型在归一化之后自己决定把哪个维度缩放到多大、偏移多少。初始化成 γ=1,β=0(相当于"先不做任何额外变换"),然后在训练中学出最合适的值。
步骤 5 — 合起来:完整子层公式
把三步串成一条流水线,就是论文里那行公式的完整含义:
输出 = LayerNorm( x + Attention(x) )
bank 经过完整子层后的最终向量
| d₀ | d₁ | d₂ | d₃ | 说明 | |
|---|---|---|---|---|---|
| 输入 x | 0.80 | 0.40 | 0.60 | -0.10 | 两句相同 |
| 句子 A | 1.516 | -0.408 | 0.128 | -1.235 | ← river 语境 |
| 句子 B | 1.312 | -0.201 | 0.447 | -1.558 | ← street 语境 |
一层的完整数据流
x ──→ [Multi-Head Attention] ──→ Attn(x)
x ──────────────────────────────────┐
↓ 相加
x + Attn(x)
↓ LayerNorm
z = LN(x + Attn(x)) ← 传给 FFN
z ──→ [Feed-Forward Network] ──→ FFN(z)
z ──────────────────────────────────┐
↓ 相加
z + FFN(z)
↓ LayerNorm
本层最终输出
接下来可以深入哪里
- 下一步:FFN 数值推导
- 转成 PyTorch 代码
- 多头拼接过程
相关文章
- 维普论文检测系统官网入口在哪 07-10
- 如何免费下载漫蛙漫画app 07-10
- 水月影评app如何搜索电视剧 07-10
- 望月角色技能连招盘点 青乌照天恋狐云翊青门隐连招指南 07-10
- 失控进化手游好玩吗 失控进化玩法内容详细介绍 07-10
- 智能时代官网Geo内容优化策略:构筑AI可信赖的信息枢纽 07-10