第一部分:为什么要引入注意力机制?(打破瓶颈)
1. 传统 Seq2Seq 模型的瓶颈
在传统的编码器-解码器(RNN)架构中,所有输入序列的信息都被压缩成最后一个隐藏状态向量 C,然后传给解码器。
- 致命缺陷 :如果输入句子非常长(如 100 个单词),强制把这么多信息塞进一个固定长度(比如 1024 维)的向量里,信息一定会严重丢失(瓶颈)。解码器翻译时,无法"回看"之前的原文。
2. 注意力机制的直观灵感
不要再把输入强塞到一个固定向量里。每次解码器生成一个词时,都让它"回看"一遍整个输入序列,动态挑选当前最需要的部分。这就好像你读一篇长文,虽然记不住全文,但当你需要翻译某个词时,你会回头找原文对应的重点词。
第二部分:Seq2Seq 中的 Attention 具体计算流程
-
保持编码器不变:编码器输出全部隐藏状态 h1,h2,h3,h4。
-
初始化解码器:解码器的第一个隐藏状态 s0 可以由编码器的最后一个状态转化得到,或全零初始化。
-
计算对齐分数(Alignment Scores) :
对于解码器的第 1 步,我们需要知道当前该关注输入序列的哪个词。
- 公式 :
。这里的
是一个简单的线性层,拼接
和
后,通过权重矩阵压缩为一个标量分数。
- 公式 :
-
Softmax 归一化获得注意力权重 :
因为分数是任意的(可正可负),我们需要将其转化为概率分布。
-
公式 :
这个 a 就是指"在生成第一个词时,第 i 个输入词的重要程度"。(对应幻灯片1中的数值:
...)
-
-
生成上下文向量(Context Vector) :
用刚才算出的注意力权重,对编码器的隐藏状态进行加权求和。
-
公式 :
-
比喻:这就像在说"我现在要翻译'vediamo',所以我需要把 h1 和 h2 的信息放大拉过来,忽略 h3 和 h4"。
-
-
输入解码器更新 :
将新的上下文向量 c1、上一时刻的输出词 y0、上一状态 s0,一起送入 RNN 单元:
- 公式 :
- 公式 :
-
重复上述过程 :每一步都重新计算
。注意:每一步使用的
权重是共享的,且整个过程端到端可微,不需要人为监督注意力权重,网络自己靠梯度下降学习。
💡 可视化理解
幻灯片2是一张经典的注意力权重矩阵图(英文翻译成法文)。
-
横轴是英文输入词,纵轴是法文输出词。
-
对角线是亮的,说明大多数词是顺序对应的。
-
偏离对角线 的方块(如框出的"European Economic Area" vs "zone économique européenne"),说明模型学会了调整语序!这一步完美证明了注意力机制的作用。
第三部分:通用的 Attention Layer(Q, K, V 机制的诞生)
当我们把注意力从 RNN 中剥离出来,它就变成了一个独立的算子。我们不再使用 ,而是引入了现代 Transformer 中著名的"查询-键-值" (Query-Key-Value) 机制。
1. 核心公式:缩放点积注意力 (Scaled Dot-Product Attention)
-
输入定义:
-
查询矩阵 Q (Query) :×,代表"我当前想找什么"。
-
数据矩阵 X (Data) :×,代表"我手头有什么数据"。
-
-
引入线性投影(幻灯片5) :为了让数据以不同的角色参与计算,我们给数据加上两个可学习的权重矩阵
和
。
-
键矩阵 K (Key) :K=
,形状为 ×。Keys 是数据的"索引标签"。
-
值矩阵 V (Value) :V=
,形状为 ×。Values 是数据的"实际内容"。
-
-
相似度计算 (矩阵乘法):
-
E=
,形状为 ×。
-
为什么要除以
? 。当向量维度 D 变大时,点积数值会变得很大,经过 Softmax 后会变成极端的 0 或 1,导致梯度消失。除以 D 能将分数控制在合理范围内,保持梯度平滑。
-
-
注意力权重 (Softmax):A=softmax(E,dim=−1),按行归一化。
-
输出 (加权求和) :Y=AV,形状为 ×。
- 相当于每一个 Query 行向量,都对所有的 Value 列向量进行线性组合。
💡 搜索引擎比喻 :
Query 是你输入搜索框的词;Key 是所有网页的标题(用来匹配);Value 是网页正文内容(被提取的信息)。
第四部分:Cross-Attention 与 Self-Attention
1. 交叉注意力 (Cross-Attention)
当 Query 和 Data 来自两个完全不同的输入集时,称为交叉注意力。
-
例子:机器翻译时,Query 来自解码器(法文),Data 来自编码器(英文)。
-
这允许一个序列去查询另一个序列的特定信息。
2. 自注意力 (Self-Attention)
当只有一个输入序列 X 时,我们将同一个 X 分别投影成 Query、Key、Value。
-
公式 :Q=
,K=
,V=
。
-
注意尺寸 :通常设置
=
=
=
。
-
核心性质:置换等变性 (Permutation Equivariance) :
如果打乱输入向量的顺序,由于点积和 Softmax 只关注值本身,输出的内容也会按同样的顺序被打乱。这意味着自注意力本身完全不知道顺序!
-
解决办法:位置编码 (Positional Embedding)。在原向量上直接加上或者拼接一个能代表位置(如 1,2,3...)的向量,告诉模型这些词的先后顺序。
-
掩码自注意力 (Masked Self-Attention) :
在生成文本时,你不能让模型偷偷看到未来的词。做法是:把当前时刻之后位置的分数(EE 中右上角的元素)设为 负无穷大,Softmax 后概率就变成 0。这被称为 Masked Self-Attention。
第五部分:多头自注意力与矩阵乘法优化
1. 多头自注意力 (Multi-Head Self-Attention)
一组 Q, K, V 只能学到一种"关系",模型觉得不够。于是:
-
设置 H 个独立的头,每个头有自己的
。
-
每个头独立输出 N×Dhead 的结果。
-
将这些头沿着特征维度拼接(堆叠),再乘上一个输出投影矩阵
混合信息,得到最终的输出。
-
作用:不同的头可以让模型关注不同的位置(比如头1关注语法,头2关注词汇关系)。
2. 高效矩阵运算(四步走)
整个多头自注意力实际上就是四步强大的矩阵乘法(极度适合 GPU 并行):
-
QKV 投影 :XN×D×WD×3→N×3(拼接后拆分)。
-
QK 相似度 :Q×
,得到 H×N×N。
-
V 加权 :A×V,得到 H×N×,再 Reshape 回 N×。
-
输出投影 :Y×
,得到 N×D。
第六部分:三种基本算子的终极对比(为什么是注意力?)
| 算子 | 处理方式 | 优点 | 缺点 |
|---|---|---|---|
| RNN (循环神经网络) | 依次处理,串行 | 能处理任意长序列,有状态记忆 | 无法并行(必须等前一步算完),长距离信息容易丢失 |
| CNN (卷积神经网络) | 局部滑动窗口 | 高度并行,运算快 | 感受野受限,需堆叠很多层才能看到全局 |
| Self-Attention (自注意力) | 全局两两交互 | 全局感知 (一步到位),高度并行(仅靠矩阵乘法),计算复杂度虽为 O(N2)O(N2),但在现代硬件上效率极高 | 计算和内存成本随序列长度呈平方级增长(序列太长会爆内存) |
第七部分:Transformer Block(积木式终极架构)
之前讲的自注意力只是一个"算子"。如果把自注意力、MLP(全连接层)和归一化组合在一起,加上残差连接 ,就构成了一个完整的 Transformer Block。这就是构建现代大模型的基本"积木"。
1. 完整结构拆解
输入是一组向量 x1,x2,x3,x4,输出是一组维度相同的向量 y1,y2,y3,y4。大部分计算仅由 6 次矩阵乘法 构成:
第一层:Self-Attention(4次矩阵乘法)
-
将输入 X 分别乘以
,
(3次),生成 Q,K,V。
-
计算注意力输出 Y=Softmax
,再经过
输出投影(第4次矩阵乘法)。
-
这一步是 向量之间唯一的交互方式,类似于"开会讨论",大家交换信息。
残差连接 ①:将原始的 XX 直接加到 Self-Attention 的输出上(X+Attn(X))。这解决了深层网络梯度消失的问题。
层归一化 ①(Layer Normalization):
-
与 CNN 中常用的 Batch Norm(按批次算均值/方差)不同,LayerNorm 是对每一个单独的样本独立计算均值和方差。
-
为什么必须用 LayerNorm? 因为 NLP 序列长度经常变化,且训练时 Batch Size 可能很小,BatchNorm 会极其不稳定。LayerNorm 不依赖批次大小,极度稳定。
第二层:MLP(多层感知机,2次矩阵乘法)
-
这是两个全连接层(前馈网络),中间夹着一个非线性激活函数(如 GELU)。通常做的是"先放大4倍维度,再缩小回来"(例如 D=512→2048→512)。
-
直观比喻:注意力是"开会讨论",MLP 就是"各自回家独立思考"。MLP 对每个向量的作用是完全独立的(Pointwise),处理该向量更深的语义特征。
残差连接 ② 和 层归一化 ②:再次重复上述操作,然后输出最终的 y。
2. 为什么说它"高度可并行化"?
RNN 必须等前一个时间步算完才能算当前时间步,是串行的。而 Transformer 的输入是整句话一起打包成矩阵,这 6 次矩阵乘法 完全可以在 GPU 上并行执行。这就是为什么它能吃掉海量数据和算力,训练出超大模型。
第八部分:大模型的"暴力美学"(模型扩展)
本质:自 2017 年提出以来,它的核心结构就几乎没有变过!只是无脑地堆叠相同的 Transformer Block。
这是一个典型的"参数暴力"时代。图片 2 展现了原始 Transformer 到 GPT-3 的发展史:
| 模型名称 | 堆叠块数 (Blocks) | 模型维度 (D) | 多头数 (H) | 上下文长度 (N) | 参数量 |
|---|---|---|---|---|---|
| 原始 Transformer (2017) | 12 层 | 1024 | 16 | 512 | 2.13 亿 |
| GPT-2 (2019) | 48 层 | 1600 | 25 | 1024 | 15 亿 |
| GPT-3 (2020) | 96 层 | 12288 | 96 | 2048 | 1750 亿 |
💡 核心参数详解:
-
D (Model Dimension):代表每个单词被转换成的向量长度。GPT-3 的 D=12288,意味着每个词都被极其丰富地表示为一个 1.2 万维的向量。
-
H (Heads):多头注意力机制的头数。GPT-3 有 96 个头,意味着在开会时,有 96 个不同视角的专家在同时寻找不同维度的关系。
-
N (Context Length):模型一次能处理多少个词。GPT-3 的 N=2048 说明它一次能看 2048 个词。
-
参数量:从 2 亿到 1750 亿,翻了几千倍。
一句话总结:
大模型的本质,就是用高度平行的矩阵乘法 (6次大矩阵乘法)和极深的堆叠 ,来暴力地拟合人类语言中的复杂规律。这也是为什么现在大家常说**"大力出奇迹"**!
✨ 总结补充给你的笔记:
-
为什么用线性层做对齐:因为简单且可微,方便反向传播。
-
为什么把 Key 和 Value 分开:这允许模型在处理同一个数据时,既能作为"被搜索的标尺",也能作为"被提取的内容"。这是一种强大的解耦。
-
为什么原始注意力有位置编码:因为自注意力像一袋散乱的珠子的集合,不告诉它位置,它就分不清谁是"主语"、谁是"谓语"。位置编码就是给珠子上贴上"第几号"的标签。