注意力机制

作为一个堂堂正正的中国人,用英文做的那一版笔记是在难以下咽,因此用中文重新做一遍

1. 背景

1.1 前浪:RNN / LSTM 时代

在 Transformer 出现之前,序列建模任务(机器翻译、文本摘要、语音识别等)几乎都依赖 RNN 及其变体 LSTM / GRU。它们按时间步依次处理序列:

即第 个位置的隐状态 依赖前一个位置的隐状态 和当前输入

这种设计带来两个根本问题:

问题具体表现
无法并行 步必须等第 步算完,序列越长,训练越慢
长距离依赖困难梯度会随着序列长度衰减或爆炸,远距离词之间的关系很难稳定保留

Example

在句子 “The animal didn’t cross the street because it was too tired.” 中,理解 “it” 指的是 “animal” 而不是 “street”,需要模型建立较长距离的依赖。RNN 在这类场景中常常吃力。


1.2 过渡:注意力机制的萌芽

2015 年,Bahdanau 等人在 Seq2Seq 翻译模型中引入了 Attention
解码器在生成每个词时,不再只依赖编码器最后一个隐状态,而是会对编码器所有位置的隐状态进行加权汇总。

这让模型可以“动态聚焦”到源句中最相关的部分,显著改善了长句翻译效果。

但此时的注意力机制只是 挂在 RNN 上的外挂,并没有解决 RNN 的顺序计算瓶颈。


1.3 破局:Transformer 的诞生

2017 年,Vaswani 等人在论文 Attention Is All You Need 中提出 Transformer,核心思想极其激进:

完全抛弃循环结构,只用注意力机制来建模序列。

这意味着:

  • 不再按时间步串行处理
  • 让序列中任意两个位置都能直接交互
  • 整个序列可以并行计算

Transformer 的几个关键创新:

  1. Self-Attention:每个位置都能直接关注整个序列中的所有位置
  2. Multi-Head Attention:并行使用多个注意力头,从不同子空间捕捉不同关系
  3. Positional Encoding:显式注入位置信息,弥补注意力本身对顺序不敏感的问题
  4. Residual + LayerNorm:让深层网络稳定训练

1.4 原始 Transformer 与 Modern Transformer

原始论文中的 Transformer 是一个 Encoder-Decoder 架构,主要面向机器翻译:

  • Encoder:读入源序列,输出上下文表示
  • Decoder:在读取编码器输出的基础上,自回归生成目标序列

而现代大语言模型(GPT、LLaMA、Qwen、DeepSeek 等)大多采用 Decoder-Only 架构,即只保留解码器。

Note

原始 Transformer 是“先读后写”;现代 LLM 更常见的是“边读边续写”。


2. 核心思路

2.1 Transformer 到底想解决什么

RNN 的根本问题是:信息必须沿着时间步一级一级传递

如果句首的词要影响句尾的词,信息必须穿过很多中间状态,路径很长,容易衰减。

Transformer 的思路是:

让每个位置直接和所有位置交互。

这样一来:

  • 任意两个位置的信息传递路径长度都是
  • 所有位置可以同时计算
  • 长距离依赖不再依赖“多步传话”

2.2 Q / K / V 的直觉

注意力机制可以理解成一个“信息检索”过程。

符号直觉类比含义
Q(Query)我在找什么当前这个位置发出的查询
K(Key)我是什么标签每个位置暴露出来的索引信息
V(Value)我真正携带的信息被取出来并聚合的内容

整个过程就是:

  1. 当前 token 发出一个 Query
  2. 用 Query 和所有 Key 算相似度
  3. 相似度越高,对应位置的 Value 权重越大
  4. 最后把所有 Value 按权重加权求和,得到新的表示

Tip

Q 决定“找谁”,K 决定“匹不匹配”,V 决定“真正取什么”。


2.3 Self-Attention 与 Cross-Attention

Self-Attention(自注意力)

Q、K、V 来自 同一个序列

也就是说,序列中每个位置都会去看整个序列,从而获得上下文信息。

例如:

“我 / 爱 / 北京 / 天安门”

其中“北京”这个位置可以关注“我”“爱”“天安门”,综合上下文更新自己的表示。

Cross-Attention(交叉注意力)

Q 来自一个序列,K 和 V 来自 另一个序列

在原始 Transformer 中:

  • Q 来自解码器当前状态
  • K、V 来自编码器输出

也就是说,解码器在生成目标词时,会去“查询”源句里最相关的部分。

Note

区别就一句话:
Self-Attention 是自己查自己,Cross-Attention 是一个序列去查另一个序列。


2.4 编码器和解码器各自做什么

编码器(Encoder)

编码器负责:

读完整个输入序列,生成每个位置的上下文表示。

每一层包含两个子层:

  1. Multi-Head Self-Attention
  2. Position-wise Feed Forward Network

并且每个子层外面都包着:

  • 残差连接(Residual Connection)
  • 层归一化(LayerNorm)

结构可写成:

输入

Multi-Head Self-Attention

Add & Norm

Feed Forward

Add & Norm

输出

解码器(Decoder)

解码器负责:

根据已经生成的部分,自回归地生成下一个 token。

每一层包含三个子层:

  1. Masked Multi-Head Self-Attention
  2. Multi-Head Cross-Attention
  3. Position-wise Feed Forward Network

结构可写成:

输入

Masked Multi-Head Self-Attention

Add & Norm

Cross-Attention

Add & Norm

Feed Forward

Add & Norm

输出

2.5 为什么现代模型多是 Decoder-Only

现代大语言模型大多采用 Decoder-Only,主要原因有:

  1. 架构更简单:只保留一种主干模块
  2. 训练目标统一:直接做 next-token prediction
  3. 更适合规模化:更容易堆大模型、喂更多数据
  4. In-Context Learning 能力强:只靠续写目标就能完成很多任务

典型三类 Transformer 变体:

架构代表模型特点
Encoder-OnlyBERT擅长理解任务
Encoder-Decoder原始 Transformer、T 5、BART擅长显式输入→输出映射
Decoder-OnlyGPT、LLaMA、Qwen擅长统一建模和生成

Tip

原始 Transformer 更像“翻译机”;现代 LLM 更像“超大规模续写机”。


3. 机制

3.1 输入表示:Embedding + Positional Encoding

注意力机制本身不感知顺序,因此必须把位置信息显式加到词向量中。

设输入序列长度为 ,模型维度为
词嵌入矩阵记为:

位置编码与词嵌入逐元素相加后,作为真正输入:

原论文采用的是固定的正弦/余弦位置编码:

Note

现代模型中常见的位置信息方案还有 RoPEALiBi 等,但原论文使用的是正余弦位置编码。


3.2 Scaled Dot-Product Attention

3.2.1 先定义维度

最一般地,设:

  • Query 序列长度为
  • Key / Value 序列长度为

则:

这些量来自线性投影:

其中:

若是 Self-Attention,则:

于是通常有

若是 Cross-Attention,则:

  • 来自解码器
  • 来自编码器

所以此时一般


3.2.2 第一步:计算相似度分数

矩阵中的每个元素:

表示第 个 Query 对第 个 Key 的匹配程度。


3.2.3 第二步:缩放

为什么要除以

核心假设: 假设所有 是独立同分布(i.i.d)的随机向量,每个分量均值为 0,方差为 1。

计算乘积方差:

既然

那么

既然独立,就有

期望与求和可以交换,于是

,得

因此,不难看出

很大时(如 512),点积值可能非常大,导致 softmax 输出接近 one-hot 向量,梯度几乎为 0。

缩放后可以让数值更稳定。


3.2.4 第三步:归一化

Softmax 是按行做的,即每个 Query 对所有 Key 的权重和为 1。

其中 表示:第 个位置对第 个位置的注意力权重。


3.2.5 第四步:对 Value 加权求和

因此:

最终完整公式为:


3.2.6 维度总结

Self-Attention

若输入序列长度为

则:

最后输出:

Cross-Attention

若 Query 长度为 ,Key / Value 长度为

则:

输出:

Tip

注意力输出的“行数”永远跟 Query 一致,因为“有多少个 Query,就会产出多少个输出位置”。


3.3 Multi-Head Attention

3.3.1 为什么需要多头

如果只有一个注意力头,模型只能用一种方式去衡量“相关性”。

但真实语言中的关系很多:

  • 句法依赖
  • 指代关系
  • 时态关系
  • 语义搭配
  • 长距离依赖

所以 Transformer 并不是只算一次注意力,而是同时算多次,让不同头学习不同模式。


3.3.2 具体计算

设头数为 ,通常有:

原论文中:

  • 所以

对每个头 ,分别学习不同的投影矩阵:

然后独立计算注意力:

最后把所有头拼接起来,再做一次线性变换:


3.3.3 维度变化

假设输入是:

则每个头看到的是:

每个头输出:

拼接后:

再经过 ,输出仍然保持:

这样就能层层堆叠。


3.4 Mask(掩码)

Mask 的作用是:

在 softmax 之前,把不该看的位置强行屏蔽掉。

常见做法是把这些位置加上 (实现时常用很大的负数如 ),这样 softmax 后这些位置的权重就接近 0。


3.4.1 Padding Mask

在 batch 训练中,句子长度不同,通常需要补 <pad> 到同一长度。

这些 pad 位置没有语义,不应该参与注意力计算。

因此要构造一个 Padding Mask,把 pad 对应位置屏蔽掉。

若某个位置是 pad,则:

否则:

然后:

Note

Padding Mask 在编码器和解码器里都可能出现,因为两边的输入都可能被 pad。


3.4.2 Causal Mask(因果掩码)

解码器在生成第 个 token 时,不能看到未来位置,否则就相当于“作弊”。

因此在解码器的 Self-Attention 中,需要使用 Causal Mask(也叫 Look-Ahead Mask)。

它本质上是一个上三角屏蔽矩阵:

即第 个位置只能看见:

  • 自己
  • 自己左边的位置

不能看右边尚未生成的位置。

例如长度为 4 时,mask 形状为:


3.4.3 Causal Mask 与 Causal Self-Attention 的区别

这两个不是并列概念。

  • Causal Mask:一个掩码矩阵,是实现手段
  • Causal Self-Attention:加上了因果掩码的自注意力机制,是完整模块

也就是说:

Tip

Causal Mask 是“工具”,Causal Self-Attention 是“用了这个工具之后的机制”。


3.5 Position-wise Feed Forward Network

每个注意力层后面都会接一个前馈网络(FFN):

原论文中通常取:

也就是说,先升维,再降回去。

它的作用不是处理序列关系,而是对每个位置独立做更强的非线性变换。

Note

Attention 负责“在不同位置之间交换信息”;FFN 负责“对每个位置内部做深加工”。


3.6 Residual Connection 与 LayerNorm

Transformer 很深,如果直接层层堆叠,训练会不稳定。

因此每个子层都使用:

  1. Residual Connection
  2. Layer Normalization

原论文写法是:

这样做的好处是:

  • 残差连接帮助信息和梯度直接穿过多层
  • LayerNorm 稳定每层输入输出的分布

Note

原始 Transformer 使用的是 Post-LN 风格;很多现代 LLM 更常见的是 Pre-LN,即先归一化再进子层。


4. 编码器与解码器的完整结构

4.1 编码器层(Encoder Layer)

每一层结构:

输入

Multi-Head Self-Attention

Add & Norm

Feed Forward

Add & Norm

输出

如果写成公式(原论文风格):

编码器一般堆叠 层。

最终输出一串上下文表示,供解码器查询。


4.2 解码器层(Decoder Layer)

每一层结构:

输入

Masked Multi-Head Self-Attention

Add & Norm

Multi-Head Cross-Attention

Add & Norm

Feed Forward

Add & Norm

输出

可写成公式:

其中 表示编码器输出。

Tip

解码器比编码器多的那一层,就是 Cross-Attention


4.3 原始 Transformer 总体流程

源序列

词嵌入 + 位置编码

Encoder × N

编码器输出

Decoder × N

Linear

Softmax

目标词概率分布

训练时使用 Teacher Forcing

  • 解码器输入是真实目标序列右移一位
  • 目标是预测下一个 token

5. Modern Transformer:为什么大模型多是 Decoder-Only

5.1 Decoder-Only 的结构

现代大语言模型通常只保留下面这个重复模块:

输入 token

词嵌入 + 位置编码

[Causal Self-Attention + FFN] × L

Linear / LM Head

预测下一个 token

这里没有:

  • 编码器
  • Cross-Attention

整个模型只做一件事:

给定前文,预测下一个 token。


5.2 为什么它反而成了主流

原因 1:训练目标统一

只做一个任务:

这比 Encoder-Decoder 的训练框架更直接、更统一。

原因 2:更容易规模化

Decoder-Only 模块更简单,更适合:

  • 加深层数
  • 增大参数量
  • 喂入海量数据

原因 3:Prompt 就能承载任务描述

例如:

把下面句子翻译成英文:
我是中国人。

模型直接续写即可,不一定非要显式分成 encoder 和 decoder。

原因 4:In-Context Learning 很强

随着模型规模增大,Decoder-Only 会涌现出很强的 few-shot / zero-shot 能力。


5.3 但 Encoder-Decoder 仍然没有消失

在一些任务中,Encoder-Decoder 依然非常有价值:

任务为什么适合 Encoder-Decoder
机器翻译输入输出结构明确,Cross-Attention 对齐很自然
文本摘要输入长、输出短,先编码再生成很合理
语音识别音频输入和文本输出是不同模态
多模态任务图像编码器 + 文本解码器很常见

所以并不是 Encoder-Decoder 过时了,而是:

在通用大语言模型这个方向上,Decoder-Only 更容易成为统一范式。


| Causal Self-Attention | 加了 Causal Mask 的 Self-Attention | | Padding Mask | 用于屏蔽 <pad> 位置 | | Encoder-Decoder | 原始 Transformer 架构 | | Decoder-Only | 现代大语言模型主流架构 |


6.4 Transformer 的代价

Transformer 虽然强大,但也有明显代价:

  1. 注意力矩阵大小为
  2. 时间和空间复杂度对序列长度通常是二次增长
  3. 超长上下文时代价很高

这也是后来出现各种改进(FlashAttention、稀疏注意力、线性注意力、KV Cache、MoE 等)的原因之一。

Tip

Transformer 解决了 RNN 的并行性和长距离依赖问题,但也引入了新的瓶颈:注意力的二次复杂度