Transformer 详解:自注意力、多头与位置编码

2 分钟阅读
·

没有机器学习背景的工程师补大模型原理的第四站:自注意力的 Q/K/V 检索直觉与点积打分,手算一个三词句子的注意力矩阵,以及多头、位置编码、残差、因果掩码各自解决什么问题。

本文是「零基础学大模型原理」系列的第 4 篇。这个系列记录一个没有任何机器学习背景的工程师,在 ChatGPT 发布之后从零补原理的过程。

上一篇结尾留了两个问题:2017 年的 Attention is All You Need 去掉循环结构后,顺序信息从哪里来?逐词生成如何实现?这两周我读完了这篇论文。论文本体只有十几页,但对没有阅读习惯的人来说密度很高。我结合两份材料阅读:Jay Alammar 的 The Illustrated Transformer 用图解释结构,Harvard NLP 的 The Annotated Transformer 用 PyTorch 逐行实现,对照代码核对每个张量的形状。这篇是读完后的笔记。前置是上一篇,记得 Bahdanau 注意力的打分、softmax、加权求和三步就够。

自注意力中的查询来源

Bahdanau 注意力中,解码器状态发起打分,编码器各位置的隐状态提供被查询的信息。Transformer 论文中的自注意力(self-attention)让查询方和被查询方来自同一个序列。每个位置以自己的表示生成查询,与序列中所有位置(包括自身)的键计算分数,再按分数对各位置的值加权,得到新的表示。

这项改动回应了上一篇中 RNN 的两个限制。第一,任意两个位置之间的依赖路径长度为一步。RNN 中,第 1 个词的信息需要经过中间时刻传到第 50 个词;自注意力中,第 50 个词可以直接与第 1 个词计算点积。第二,整层计算可以并行。每个位置的新表示只依赖这一层的输入向量,不依赖其他位置先完成计算,因此 n 个位置的打分和加权可同时进行。自注意力层不再有 RNN 在时间步上的串行依赖。

Q、K、V:查询、键与值

同一个位置的输入表示通过三个可学习的线性映射,投影为三类向量:

  • Query(查询):我这个位置在找什么。
  • Key(键):我被别人检索时拿出来的索引,说明我这个位置有什么。
  • Value(值):我这个位置实际存放的内容,别人查到之后取走的是它。

这三类向量组成一次加权检索:query 与每条记录的 key 计算匹配分数,再按分数对对应的 value 加权。这里用点积计算分数;在向量长度相同且已归一化时,方向越一致,点积越大。

为什么需要三个投影,而不直接让词向量互相计算?我当时的理解是,「找什么」「提供什么匹配线索」「传递什么内容」对应不同需求。代词的 query 可以用于寻找其指代的名词;它作为被查询对象时的 key,以及被加权汇聚的 value,可以使用不同表示。若反复使用同一个向量,三个角色只能共用一套表示。映射矩阵 是训练参数,训练过程决定各自的投影方式。

打分、缩放、softmax:注意力的完整公式

把整句所有位置的 q、k、v 分别堆成三个矩阵 Q、K、V,一整层自注意力就是一个式子:

拆开读: 一次矩阵乘法算出所有位置两两之间的打分,得到一个 n×n 的矩阵,第 i 行第 j 列是「位置 i 查位置 j」的分数;除以 缩放;softmax 按行归一化,每行变成一组和为 1 的权重;最后乘 V,按权重对所有位置的 value 加权求和。整层就是两次矩阵乘法夹一个 softmax,没有任何循环。

除以 的理由需要单独说明。论文假设 q 和 k 的各分量独立、均值为 0、方差为 1,则点积的方差随维度 线性增长。维度增大时,打分的量级也会增大,softmax 可能进入饱和区,输出接近 one-hot,梯度变小。除以 后,打分的方差回到 1 附近。这个统计论证依赖的前提我当时无法逐一验证;softmax 输入过大导致梯度变小的现象,则与第 1 篇手算过的 sigmoid 导数 σ(z)(1−σ(z)) 属于同类问题。

手算一遍:三个词的完整注意力矩阵

以「我 爱 吃苹果」的三个位置为例计算。为便于手算,将向量设为 2 维,并令 都等于单位阵,因此 q = k = v = x。实际模型中的三个投影由训练得到;这里使用单位阵,仅用于展示注意力计算。

三个位置的向量:

  • 我:
  • 爱:
  • 吃苹果:

。以位置 3(吃苹果)为查询方,先算它和三个 key 的点积:

除以 1.41,得 0.71、0.71、1.41。做 softmax:e 的幂分别是 2.03、2.03、4.11,合计 8.17,归一化后:

用这组权重对三个 value 加权求和:

位置 3 的新表示就是 [0.75, 0.75]。按同样流程计算位置 1 和位置 2。位置 1 的缩放后打分是 0.71、0、0.71,位置 2 是 0、0.71、0.71。得到的注意力矩阵如下,行是查询方,列是被查询方:

每行之和为 1,可以自查。三个输出分别是

一个句子经过 Q/K/V 打分、softmax、加权求和的完整数据流

每个位置的输出是全句 value 的加权组合,组合比例由打分决定。词向量经过自注意力后形成依赖上下文的表示。第 2 篇结尾的「一词多义怎么办」在这里有了机制上的处理方式:「吃苹果」里的「苹果」和「苹果公司」里的「苹果」会与不同上下文中的 Q、K、V 共同计算,因此输出表示可以不同。例中的向量是人为设定的,不包含语义结构;由于 q、k、v 相同,部分自身点积与其他点积相等。论文附录的注意力可视化显示,训练后的部分注意力头会关注句法相关的词。

n×n 的打分矩阵意味着序列长度翻倍时,注意力层的计算量约为原来的四倍。论文的对比表给出:自注意力每层复杂度是 ,RNN 是 。当时的场景中 n 远小于 d,自注意力的计算量更低。长文本下的平方项是否会成为限制,我当时没有继续分析。

多头注意力使用多组投影

base model 使用 8 个注意力头,,每个头的 为 64。每个头用独立的 ,把 512 维输入线性投影为 64 维的 Q、K、V,独立完成注意力计算。8 个 64 维输出拼接为 512 维,再通过线性层 。这就是多头注意力。

从直觉上看,一组 Q/K/V 只使用一套匹配标准,多组投影则允许并行学习多套标准。例如,一组可能关注句法主语,另一组可能关注指代对象。附录的可视化中,不同头呈现不同模式:有的集中于相邻位置,有的跨较远位置关注句法成分。8 个头相对于 1 个 512 维头的效果差异需要实验验证;我当时只理解到多组独立投影提供了多种匹配标准。

位置编码提供顺序信息

自注意力有一个需要注意的性质:若不加入位置信息,纯自注意力层对输入位置的置换是等变的。把三个词任意打乱,打分矩阵相应地换行换列,输出也按相同方式重排。因此,「我打狗」和「狗打我」作为词的集合无法被这类层区分。去掉循环结构后,需要通过其他方式加入顺序信息。

论文的方案是位置编码:给每个位置算一个确定的向量,直接加到该位置的词向量上:

pos 是位置序号,i 是维度索引。不同维度对应不同频率的正弦和余弦:低维通道变化较快,高维通道变化较慢。将这些维度组合后,每个位置得到一个位置编码。词向量与位置编码相加后,后续自注意力层接收到的输入包含位置信息。

论文还给了两个说明。其一,对固定偏移量 k, 可以表示为 的线性函数,因此模型可能学习到相对位置。其二,作者也试过可学习的位置 embedding,结果相近,并推测正弦位置编码可以外推到比训练序列更长的位置。第二点我当时可以接受;第一点的推导没有走通。为什么 sin/cos 的组合适合表示相对位置,我当时只读懂了结论。

残差连接与 LayerNorm

原始 Transformer 的编码器和解码器各堆叠 6 层。每个子层(自注意力或前馈网络)都使用残差连接和 LayerNorm。

残差连接的核心形式是 ,即将子层输入加到子层输出上。原始 Transformer 在子层输出和残差相加后再执行 LayerNorm。这个设计来自 ResNet。加法路径为梯度传播提供了直接路径,是深层网络更易优化的工程机制之一。

LayerNorm 对每个位置的隐藏维度计算均值和方差,归一化后再进行可学习的缩放和平移。它不跨 batch 统计数据,因此适合可变长度序列和小 batch 的训练场景。为什么深层网络需要这种归一化,以及 LayerNorm 相对 BatchNorm 的理论差异,我当时只读到工程层面的解释,理论分析没有继续展开。

每层的后半段还有前馈网络:每个位置独立经过一个两层 MLP,在 base model 中从 512 维升到 2048 维,再降回 512 维。该网络在所有位置共享参数,但逐位置计算。我当时将其理解为对每个位置单独做特征变换,没有继续分析升维再降维的设计考量。

编码器、解码器与因果掩码

论文的完整结构是编码器-解码器,用于机器翻译。编码器有 6 层,每层由自注意力和前馈网络组成,将源句编码为带上下文的表示。解码器也有 6 层,每层包含带掩码的自注意力、交叉注意力和前馈网络。交叉注意力中,Q 来自解码器子层的输入,K 和 V 来自编码器输出;解码器据此查询源句的所有位置。

掩码(mask)处理训练阶段的未来词泄露。RNN 的解码状态按时间步递推,天然不能访问未来位置。Transformer 使用 teacher forcing 时,将右移后的目标序列一次输入解码器,各位置可以并行计算。若没有掩码,位置 t 的自注意力会访问位置 t 之后的目标词,从而泄露预测目标。做法是在 softmax 前,将未来位置的打分置为负无穷,,这些位置在 softmax 后的权重为零。这样每个位置只能访问当前位置及之前的位置,因此称为因果掩码。该约束允许并行训练,同时避免访问未来词。

若任务是根据前文预测下一个词,模型不需要编码源句,只保留解码器和因果掩码即可。这条思路后来延伸到 GPT 系列,是下一篇的内容。

小结与待继续理解的问题

这篇论文的结构可以归纳为:自注意力让每个位置直接与所有位置交互,并支持整层并行计算;Q、K、V 投影分别用于查询、匹配和内容汇聚;除以 控制 softmax 输入的尺度;多头提供多组并行的投影和匹配;位置编码将顺序信息加入输入;残差连接和 LayerNorm 构成各子层的训练结构;因果掩码让解码器并行训练时不访问未来词。各组件都对应一个具体的结构约束或训练问题。

仍需继续理解的问题包括:LayerNorm 的理论依据,前馈网络升维到 2048 的考量,层数为何取 6,以及注意力机制的表达能力是否有超出实验结果的解释。 复杂度在长文本中的影响,当时也只停留在论文表格中的比较。

下一篇沿着仅使用解码器的思路阅读 GPT:从 GPT-1 到 GPT-3,讨论「预测下一个词」这一训练目标如何用于语言模型。

本篇参考的资料

  • Attention Is All You Need(Vaswani et al., 2017):Transformer 原始论文,本篇全部结构出自这里;多头、位置编码、复杂度对比表在正文,注意力可视化在附录。
  • The Illustrated Transformer(Jay Alammar, 2018):逐层图解,Q/K/V 三个向量从同一个词向量投影出来的画面来自这篇,本篇的检索读法也受它启发。
  • The Annotated Transformer(Harvard NLP, 2018):PyTorch 逐行实现加注释,用来核对每个张量的形状,掩码的实现细节(置负无穷再做 softmax)是在这篇里确认的。

832 字 · 66 段落
ximing

Written by ximingFollow onGitHub

相关文章