Transformer 架构:自注意力与多头机制
Transformer 架构核心思想
Transformer 抛弃了传统的循环或卷积结构,完全基于注意力机制来建模序列数据。它的核心优势在于并行计算能力强,能高效捕捉长距离依赖关系,这使其成为现代大语言模型(如 GPT、BERT 等)的基石。
整个架构由编码器(Encoder)和解码器(Decoder)堆叠而成,但二者共享一个关键组件:多头自注意力机制。理解这一机制,是理解 Transformer 的灵魂。
自注意力机制:序列内的动态关联
自注意力允许模型在处理一个词时,动态地“关注”同一个句子中的其他词,从而为每个词生成富含上下文信息的表示。
单头注意力的计算流程
对于输入序列中的每个词,我们创建三个向量:查询(Query, Q)、键(Key, K)和值(Value, V)。这三个向量由输入嵌入矩阵分别乘以三个权重矩阵 $W^Q, W^K, W^V$ 得到。
注意力计算分为四步:
-
计算得分:用当前词的查询向量 $Q$ 与序列中所有词的键向量 $K$ 做点积,得到原始注意力分数。点积越大,表示两个词关联越强。
$\text{score}(Q, K) = Q \cdot K^\top$ -
缩放:为防止点积过大导致 softmax 梯度消失,将分数除以键向量维度 $d_k$ 的平方根。
$\text{scaled_score} = \frac{QK^\top}{\sqrt{d_k}}$ -
归一化:对缩放后的分数应用 softmax,得到总和为 1 的注意力权重。
$\alpha = \text{softmax}\left(\frac{QK^\top}{\sqrt{d_k}}\right)$ -
加权聚合:将注意力权重与值向量 $V$ 相乘并求和,得到最终的自注意力输出。
$\text{Attention}(Q, K, V) = \alpha \cdot V$
直观理解
可以把它想象成一个检索系统:
- 查询 是你想了解的单词,“我想知道我与上下文中哪些词最相关。”
- 键 是所有单词提供的索引或标签,“如果我与查询相关,我会给出高匹配度。”
- 值 是每个单词实际携带的内容信息,注意力权重决定了哪些值应该被聚合进来。
这样,每个词的输出不再是孤立的词向量,而是整个序列中相关信息的加权混合。
多头注意力机制:并行关注不同子空间
单头注意力只能捕获一种关联模式,但语言中的关系是多层面的:语法结构、语义角色、指代关系等。多头注意力通过并行运行多组自注意力,让模型同时关注不同表示子空间的信息。
实现方式
- 将输入的 $Q, K, V$ 分别线性投影到 $h$ 个不同的低维空间中(每个头的维度 $d_{\text{head}} = d_{\text{model}} / h$)。
- 在每个投影后的子空间上并行计算缩放点积注意力,得到 $h$ 个输出头。
- 将所有头的输出拼接(Concat)在一起,再通过一个线性变换 $W^O$ 融合信息。
$$ \text{MultiHead}(Q, K, V) = \text{Concat}(\text{head}_1, \ldots, \text{head}_h) W^O $$
其中每个头独立计算: $$ \text{head}_i = \text{Attention}(Q W_i^Q, K W_i^K, V W_i^V) $$
为什么用多头?
- 多样化的关系捕获:一个头可能专注句法依存,另一个头可能专注共指消解,第三个头可能处理长距离语义关联。
- 学习稳定性:多头提供多个“视角”,平均效果更稳健。
- 信息融合:最后的线性层能够整合来自不同子空间的信息,生成更强大的最终表示。
实际应用中,典型的数量是 8 或 16 个头,比如原始 Transformer 采用 $h=8$,每个头维度为 64。
编码器–解码器中的注意力类型
在完整的 Transformer 中,注意力有三种使用方式:
编码器自注意力
- 查询、键、值全部来自编码器前一层的输出。
- 每个位置都能关注到输入序列的所有位置(完整上下文)。
解码器带掩码的自注意力
- 为防止信息“泄露”,在解码器中使用了因果掩码(causal mask)。
- 计算时掩码掉当前位置之后的词,确保预测只依赖已生成的部分。
编码器–解码器注意力
- 查询来自解码器上一层输出,而键和值来自编码器的最终输出。
- 这让解码器在生成每个词时都能“查阅”整个输入序列的表示。
位置编码:弥补顺序信息缺失
自注意力本身对位置无感知,交换两个词的顺序输出不变。为了注入顺序信息,Transformer 在输入嵌入上叠加了位置编码。
原始论文使用正弦和余弦函数生成固定位置编码:
$$ \begin{aligned} PE_{(pos, 2i)} &= \sin\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right) \ PE_{(pos, 2i+1)} &= \cos\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right) \end{aligned} $$
这样模型能够区分不同位置,并捕捉相对位置关系。后续的变体也常使用可学习的位置嵌入。
动手实现的关键细节
如果你从零实现,需注意:
- 输入形状:通常是
(batch_size, seq_length, d_model)。 - Q、K、V 的维度:线性投影前都是
d_model,投影后每个头变为d_model // h。 - 掩码设置:在解码器自注意力中构建上三角为
-inf的矩阵,使得 softmax 后对应位置权重为 0。 - Dropout:常施加在注意力权重上,提高泛化能力。
掌握自注意力与多头机制后,Transformer 的其他组件(前馈网络、残差连接、层归一化)就变成了清晰的辅助结构,整个架构的蓝图将变得通透。