跳转至

15.6   转换器与注意力机制

晚饭桌上,大家同时聊天。小率发现,理解一句话时不能只看前一个词:听到“她把相机放在桌上,然后拿起它”,要知道“它”指相机,就得回头看前面的词。均哥用彩色线把相关词连起来:“注意力机制(Attention)就是让每个位置去看所有相关位置。”

Transformer 不按时间一步步递推,而是让序列里的元素彼此建立联系。它是现代大语言模型的重要基础。

均哥和小率在晚饭桌旁理解注意力机制

15.6.1   注意力先问:我该看谁

自注意力(Self-Attention)会给每个词生成三种向量:

  • Query:我正在寻找什么信息。
  • Key:我能提供什么线索。
  • Value:如果被关注,我真正传递什么内容。

注意力权重来自 Query 和 Key 的相似度:

\[ \text{Attention}(Q,K,V) = \text{softmax}\left(\frac{QK^{\mathsf T}}{\sqrt{d_k}}\right)V \]

除以 \(\sqrt{d_k}\) 是为了防止点积过大,让 Softmax 不至于过早变得极端。

15.6.2   多头注意力像多种阅读角度

多头注意力(Multi-Head Attention)会并行计算多组注意力。一个头可能关注指代关系,一个头可能关注语法结构,还有一个头可能关注位置邻近。

位置编码(Positional Encoding)也很重要。因为 Transformer 本身同时看所有词,如果不告诉它顺序,“今天我请你吃饭”和“你请我今天吃饭”会缺少位置差异。

15.6.3   用几行代码算缩放点积注意力

import torch
import torch.nn.functional as F

torch.manual_seed(0)

Q = torch.randn(2, 4)  # 2 个词, 每个词 4 维 query
K = torch.randn(2, 4)
V = torch.randn(2, 4)

scores = Q @ K.T / (Q.shape[-1] ** 0.5)
weights = F.softmax(scores, dim=-1)
context = weights @ V

print("attention weights:")
print(weights)
print("context:")
print(context)

输出的 weights 可以理解为“每个词把注意力分给其他词的比例”。

注意力不是万能解释器

注意力权重能提供一些线索,但不能简单等同于模型的完整因果解释。真实模型里还有残差连接、层归一化、前馈网络和多层组合。

小率的笔记本

Transformer 的关键是让序列中每个位置直接查看其他位置。注意力解决“该看谁”的问题,多头机制解决“从哪些角度看”的问题,位置编码补上顺序信息。