第 03 章 / 第 07 课

因果注意力:每个位置应该看见谁

用三个位置的小矩阵,把 Q/K/V、缩放、softmax 和因果遮罩一步步算清楚。

中文讲解 · 约 3 分钟两道自测 · 可重复作答第 7 / 15 课
这一课,你会学到
  • 跟踪注意力计算的张量形状
  • 解释 softmax 的作用
  • 测试未来 token 不影响过去位置
术语速查与实践准备
因果遮罩
阻止当前位置读取未来位置的信息。
logits
概率转换之前的词表分数。
残差连接
把子层输出和输入相加,给信息与梯度留出通路。
检查点
为保存/恢复实验而记录的权重与必要状态。

浏览器概念实验可以直接做。运行文中的 PyTorch 代码前,按官方安装说明准备独立环境;完整模型训练的时间与内存按实际数据、模型和硬件测量。

MLP 把固定窗口的向量拼接起来;注意力则为每个位置计算一组信息权重。对自回归语言模型来说,它还有一个约束:预测下一个 token 时,不能看到未来位置。

Q、K、V 分别做什么

把输入向量 X 乘上三组可训练矩阵,得到 Q、K、V。可以把 Q 理解为当前位置提出的查询,K 是各位置提供的匹配信息,V 是按权重汇总的内容。这是理解计算的比喻,不意味着模型里存在自然语言问答。

若 X 的形状是 [B,T,C],单头 Q/K/V 都可以是 [B,T,D]。Q×Kᵀ 得到 [B,T,T],其中每一行代表某个查询位置对所有键位置的分数。

缩放、遮罩与 softmax

点积通常除以 √D,然后把未来位置的分数置为负无穷,再沿最后一个维度做 softmax。这样每行合法位置的权重和为 1,未来位置的权重为 0。加权乘 V 后得到 [B,T,D]。

三个位置的合法关系是:第一个位置只能看自己,第二个可以看前两个,第三个可以看前三个。因此保留对角线和下三角,而不是只保留对角线以下。

import math
import torch

def causal_attention(q, k, v):
    length = q.shape[-2]
    scores = q @ k.transpose(-2, -1)
    scores = scores / math.sqrt(q.shape[-1])
    allowed = torch.ones(length, length, dtype=torch.bool,
                         device=q.device).tril()
    scores = scores.masked_fill(~allowed, float("-inf"))
    weights = scores.softmax(dim=-1)
    return weights @ v, weights

这是无 dropout 的教学版本,假设查询和键有相同序列长度。生产实现还需要处理 padding、多头拆分、缓存等条件,不能把这个函数直接当成所有场景的完整实现。

一个能发现泄漏的测试

固定前三个输入,先做一次前向。只修改最后一个位置,再前向一次。若模型没有随机 dropout,前面位置的输出应在数值容差内保持不变。否则先检查遮罩方向、目标对齐和位置索引。

还要检查注意力权重每行求和是否接近 1、未来位置是否为 0。仅看输出形状正确,无法证明没有信息泄漏。

下一步是把注意力放进 block

这一课以 Raschka 的注意力实现章节和 Transformer 原论文为延伸资料。多头注意力会并行计算多个子空间的权重,再组合输出;它并不取消因果约束。

下一课把注意力、前馈网络和残差连接放进完整 GPT。保留你这次的因果测试,随后让整个模型也通过同样的检查。

读完之后,给理解一次反馈。

写一个没有 dropout 的单头因果注意力,修改序列最后一个输入,比较前面位置的输出。

本课参考资料

文章、例子与练习为本站原创讲解;官方视频与延伸资料保留作者来源。

核对日期 2026-10-14
核对实验结果,再留下完成记录。

完成记录与自测结果分别保存,不自动推断掌握程度。