《Attention Is All You Need》Transformer 论文阅读
简介
- 顺序计算:
循环模型的计算是沿着输入和输出序列的符号位置(symbol positions)逐步进行的。
每个时间步 $t$ 的隐藏状态 $h_t$ 是前一个隐藏状态 $h_{t-1}$ 和当前输入的函数。
这种计算是顺序的,即必须一步一步地进行,无法跳过或并行处理。
- 并行化困难:
由于顺序计算的特性,循环模型在训练过程中无法对单个样本进行并行化。
当序列长度较长时,这种限制会变得尤为严重,因为内存限制会进一步限制跨样本的批处理(batching)。
第二部分就介绍了一下Transformer的效果。
背景
这一章节进一步说明Transformer的创新点,同时还说明该工作所研究的自注意力机制具有重要的价值,以及现有解决方案的缺点。
一些用来减少序列计算的工作都是使用的卷积神经网络作为基本构建块,并行计算所有输入和输出位置的隐藏表示。然而,在这些模型中,关联两个任意输入或输出位置信号所需的操作次数会随着位置之间的距离增加而增加——对于ConvS2S是线性增长,对于ByteNet是对数增长。
图1 Transformer模型架构
模型架构
编码器和解码器
-
编码器
编码器部分是由N=6相同的架构堆叠而成的。每一层都由自注意力模块和前馈神经网络两个子层组成,且两个子层都采用残差连接以及LayerNorm进行处理。所有子层和嵌入层都是512的输出维度。这里面的LayerNorm是可以进行偏置的,LayerNorm(x+Sublayer(x)),Sublayer(x)就是除了多头注意力模块之外的那个箭头。
-
解码器
解码层与编码层相似,也是由6层堆叠而成。与编码器部分的区别是其添加了一个 Masked Multi-Head Attention 结构。乍一看跟 Multi-Head Attention 相似,不同之初在于,他增加了掩码机制。掩码的作用是防止解码器在生成当前词时看到未来的信息,确保自回归性质。
自注意力机制
$$\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right) V$$-
缩放点积注意力
这里的注意力机制与点积注意力机制(还有一种是加法注意力,但是它没有点积快)思路一致,但是增加了缩放因子:${\frac{1}{\sqrt{d_k}}}$。其中${d_k}$就是输入的维度,就是前面提到的512。使用它的原因是:作者认为,${d_k}$较小的时候点积注意力和加法注意力有相似的效果,但是当${d_k}$较大时点积注意力差于加法注意力。在点积注意力中,查询 $Q$ 和键 $K$ 的点积 $QK^T$ 的幅度会随着 $d_k$(键和查询的维度)的增大而增大。当 $d_k$ 较大时,点积的绝对值会变得非常大,导致 Softmax 函数的输入值过大。
Softmax 函数的梯度在输入值较大时会变得非常小,这是因为 Softmax 会将较大的输入值映射到接近 1 的输出值,而较小的输入值映射到接近 0 的输出值。当点积值过大时,Softmax 函数的梯度会接近 0,导致梯度消失问题,从而影响模型的训练效果。
图2 缩放点积注意力机制
- 多头注意力机制
图3 多头注意力机制结构图
多头注意力机制是这篇文章的核心创新,在标准的注意力机制中,查询(Query)、键(Key)和值(Value)都是 $d_{\text{model}}$ 维的向量。注意力函数通过计算查询和键的相似度,然后对值进行加权求和,得到输出。
为了提升注意力机制的表现,作者提出了 多头注意力机制,其核心思想是:
- 将查询、键和值分别通过 不同的线性投影 映射到更低维的空间($d_k$ 和 $d_v$ 维)。
- 对这些投影后的查询、键和值 并行地执行注意力函数,得到多个输出。
- 将这些输出 拼接 起来,再通过一个线性投影得到最终的结果。
这样设计的多头注意力机制有三个优势:
- 捕捉不同的特征:每个“头”可以关注输入序列的不同部分或不同特征,从而增强模型的表达能力。
- 并行计算:多个注意力头可以并行计算,提高计算效率。
- 灵活性:通过调整头的数量 $h$ 和每个头的维度 $d_k$、$d_v$,可以灵活地控制模型的容量。
多头注意力计算流程如下:
1. 多头注意力公式
多头注意力的计算过程可以表示为:
$$\text{MultiHead}(Q, K, V) = \text{Concat}(head_1, head_2, ... , head_h) W^O$$其中:
- $Q$ 是查询矩阵,维度为 $\mathbb{R}^{n \times d_{\text{model}}}$。
- $K$ 是键矩阵,维度为 $\mathbb{R}^{m \times d_{\text{model}}}$。
- $V$ 是值矩阵,维度为 $\mathbb{R}^{m \times d_{\text{model}}}$。
- $\text{head}_i$ 是第 $i$ 个注意力头的输出,维度为 $\mathbb{R}^{n \times d_v}$。
- $W^O$ 是最终的线性投影矩阵,维度为 $\mathbb{R}^{h \cdot d_v \times d_{\text{model}}}$。
2. 每个注意力头的计算
每个注意力头 $\text{head}_i$ 的计算公式为:
$$\text{head}_i = \text{Attention}(Q W_i^Q, K W_i^K, V W_i^V)$$其中:
- $W_i^Q$ 是查询的投影矩阵,维度为 $\mathbb{R}^{d_{\text{model}} \times d_k}$。
- $W_i^K$ 是键的投影矩阵,维度为 $\mathbb{R}^{d_{\text{model}} \times d_k}$。
- $W_i^V$ 是值的投影矩阵,维度为 $\mathbb{R}^{d_{\text{model}} \times d_v}$。
- $\text{Attention}$ 是标准的注意力函数(如点积注意力)。
3. 注意力函数
标准的注意力函数(点积注意力)的计算公式为:
$$\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{Q K^T}{\sqrt{d_k}}\right) V$$其中:
- $Q K^T$ 是查询和键的点积,维度为 $\mathbb{R}^{n \times m}$。
- $\text{softmax}$ 用于归一化注意力权重。
- $V$ 是值矩阵,维度为 $\mathbb{R}^{m \times d_v}$。
4. 参数矩阵的维度
- 查询投影矩阵:$W_i^Q \in \mathbb{R}^{d_{\text{model}} \times d_k}$
- 键投影矩阵:$W_i^K \in \mathbb{R}^{d_{\text{model}} \times d_k}$
- 值投影矩阵:$W_i^V \in \mathbb{R}^{d_{\text{model}} \times d_v}$
- 最终投影矩阵:$W^O \in \mathbb{R}^{h \cdot d_v \times d_{\text{model}}}$
- 注意力不同应用细节
a. 编码器-解码器注意力(Encoder-Decoder Attention)
在编码器-解码器注意力层中,查询(queries)来自解码器的前一层,而键(keys)和值(values)则来自编码器的输出。
b. 编码器中的自注意力(Self-Attention in the Encoder)
编码器包含自注意力层,其中所有的键(keys)、值(values)和查询(queries)都来自同一个地方,即编码器中前一层的输出。
c. 解码器中的自注意力(Self-Attention in the Decoder)
解码器中也包含自注意力层,但与编码器中的自注意力层有所不同。解码器中的每个位置只能关注解码器中直到该位置的所有位置(即不能关注未来的位置)。为了防止信息从左向右流动(即防止解码器在生成当前词时看到未来的词),需要屏蔽(mask)掉与非法连接对应的值。具体来说,在缩放点积注意力中,这些非法连接的值会被设置为 −∞,从而在 Softmax 计算中被忽略。
位置前馈网络
每一层都有,位置相同,参数不同,都由两个现行变换中间夹一个ReLU激活。输入和输出都是512维,中间是2048维度。
$$\text{FFN}(x) = \max(0, xW_1 + b_1)W_2 + b_2$$嵌入和SoftMax
嵌入(Embedding)用来进行将输入转换为向量,缩放因子就是在这里直接做的。
SoftMax用来预测下一个Token的概率
位置编码
正弦位置编码是Transformer原始论文中提出的一种固定编码方式,它使用正弦和余弦函数来生成位置编码。具体来说,对于序列中的每个位置 $pos$ 和每个维度 $i$,位置编码的计算公式如下:
$$PE_{(pos, 2i)} = \sin\left(\frac{pos}{10000^{\frac{2i}{d_{\text{model}}}}}\right)$$$$PE_{(pos, 2i+1)} = \cos\left(\frac{pos}{10000^{\frac{2i}{d_{\text{model}}}}}\right)$$其中:
- $pos$ 是序列中的位置索引(从0开始)。
- $i$ 是维度索引,$d_{\text{model}}$ 是模型的隐藏层维度。
- $10000$ 是一个超参数,控制频率的变化。
对着维度的增加,频率不不断见效,波长逐渐曾大。正弦位置编码是三角函数,是存在周期的,对某一个维度而言,随着Pos增加,很可能变成相同的值。但是模型有512个维度,每个维度的频率都不相同,让这512个不同的频率三角函数,在两个不同的Pos全部对位相同,这非常困难。
论文作者尝试过Learned Positional Embeddings,但是效果一样。但是正弦编码不受训练影响,因此作者它可能允许模型推断出比训练期间遇到的序列长度更长的序列。
复杂度分析
1. Self-Attention(自注意力层)
-
复杂度(Complexity per Layer) :$O(n^2 \cdot d)$
- 自注意力机制需要计算所有位置对之间的注意力分数,因此复杂度与序列长度 $n$ 的平方成正比,同时与表示维度 $d$ 成正比。
-
顺序操作(Sequential Operations) :$O(1)$
- 自注意力机制可以并行计算所有位置对之间的注意力分数,因此顺序操作的数量是常数。
-
最大路径长度(Maximum Path Length) :$O(1)$
- 自注意力机制允许任意两个位置直接交互,因此最大路径长度为 1。
分析:
自注意力机制的计算复杂度较高,尤其是对于长序列($n$ 较大),但它具有极强的全局建模能力,且可以并行计算。
2. Recurrent(循环层,如RNN)
-
复杂度(Complexity per Layer) :$O(n \cdot d^2)$
- 循环层需要按顺序处理序列中的每个位置,每次计算涉及 $d \times d$ 的矩阵乘法,因此复杂度与序列长度 $n$ 和表示维度 $d$ 的平方成正比。
-
顺序操作(Sequential Operations) :$O(n)$
- 循环层必须按顺序处理序列中的每个位置,因此顺序操作的数量与序列长度 $n$ 成正比。
-
最大路径长度(Maximum Path Length) :$O(n)$
- 循环层的信息传递是顺序的,因此序列中第一个位置和最后一个位置之间的路径长度为 $n$。
分析:
循环层的计算复杂度较低,但无法并行计算,且信息传递路径较长,可能导致长程依赖问题。
3. Convolutional(卷积层)
-
复杂度(Complexity per Layer) :$O(k \cdot n \cdot d^2)$
- 卷积层需要对每个位置进行卷积操作,卷积核大小为 $k$,因此复杂度与卷积核大小 $k$、序列长度 $n$ 和表示维度 $d$ 的平方成正比。
-
顺序操作(Sequential Operations) :$O(1)$
- 卷积操作可以并行计算,因此顺序操作的数量是常数。
-
最大路径长度(Maximum Path Length) :$O(\log_k(n))$
- 卷积层通过多层堆叠逐步扩大感受野,因此最大路径长度与序列长度 $n$ 的对数成正比。
分析:
卷积层的计算复杂度较低,且可以并行计算,但需要多层堆叠才能捕捉长程依赖关系。
4. Self-Attention (restricted)(受限自注意力层)
-
复杂度(Complexity per Layer) :$O(r \cdot n \cdot d)$
- 受限自注意力机制只计算每个位置与周围 $r$ 个邻居的注意力分数,因此复杂度与邻居大小 $r$、序列长度 $n$ 和表示维度 $r$ 成正比。
-
顺序操作(Sequential Operations) :$O(1)$
- 受限自注意力机制可以并行计算,因此顺序操作的数量是常数。
-
最大路径长度(Maximum Path Length) :$O(n/r)$
- 受限自注意力机制的信息传递需要经过多个邻居跳转,因此最大路径长度与序列长度 $n$ 和邻居大小 $r$ 的比值成正比。
分析:
受限自注意力机制通过限制注意力范围降低了计算复杂度,但信息传递路径变长,可能影响长程依赖建模能力。
总结
| 层类型 | 复杂度 | 顺序操作 | 最大路径长度 | 特点 |
|---|---|---|---|---|
| Self-Attention | $O(n^2 \cdot d)$ | $O(1)$ | $O(1)$ | 全局建模能力强,计算复杂度高 |
| Recurrent | $O(n \cdot d^2)$ | $O(n)$ | $O(n)$ | 无法并行,长程依赖问题 |
| Convolutional | $O(k \cdot n \cdot d^2)$ | $O(1)$ | $O(\log_k(n))$ | 可并行,需要多层堆叠捕捉长程依赖 |
| Self-Attention (restricted) | $O(r \cdot n \cdot d)$ | $O(1)$ | $O(n/r)$ | 计算复杂度低,信息传递路径较长 |
疑问解决
掩码自注意力机制实现方法
这里在softmax之ian将数值设置为负无穷大,下面的SoftMax的图像显示,他们计算后无限接近于0。因此不会影响后续的计算。
正弦编码意义
传统的循环神经网络(RNN)在计算过程中天然地带有时序和位置信息,因为它们的计算是逐步进行的,每个时间步都依赖于前一个时间步的输出。然而,Transformer模型在计算时是批量处理的,模型本身无法直接感知到输入序列中不同位置的信息。因此,为了弥补这一缺陷,Transformer引入了位置编码(Positional Encoding),以便模型能够区分序列中不同位置的单词。
假设输入的词向量矩阵为(5,3),其中3表示词向量的维度,5表示单词的数量。在进行位置编码时,不同维度的频率是不同的(即对于每个维度i,奇数位置使用正弦函数,偶数位置使用余弦函数),同时不同位置的单词的pos(位置索引)也不同。通过这种方式,位置信息被编码并添加到词嵌入矩阵中,使得矩阵能够携带位置信息。在后续的自注意力机制等网络计算中,模型通过足够的数据和强大的表达能力,能够自动提取和处理这些嵌入在词向量中的位置信息。
如果你仍然难以理解,可以将原始的词嵌入看作一个向量,而额外添加的正弦位置编码看作另一个向量。在向量空间中,这两个向量相加得到一个新的向量,这个新向量不仅包含了单词的语义信息,还包含了它在序列中的位置信息。通过这种方式,Transformer模型能够在处理序列数据时,有效地利用位置信息。
正弦编码之间的表示
先学习正弦余弦公式
$$$$$$\cos(\alpha + \beta) = \cos\alpha \cdot \cos\beta - \sin\alpha \cdot \sin\beta \quad$$对于位置 pos+k 的编码:
因此pos+k 的编码可以被pos 的编码表示:
进一步整理:
$$\begin{bmatrix} PE(pos+k, 2i) \\ PE(pos+k, 2i+1) \end{bmatrix} = \begin{bmatrix} u & v \\ -v & u \end{bmatrix} \times \begin{bmatrix} PE(pos, 2i) \\ PE(pos, 2i+1) \end{bmatrix} \quad$$其中,$u = \cos(w_i \cdot k)$,$v = \sin(w_i \cdot k)$ 为常数。
计算 $PE_{pos}$ 和 $PE_{pos+k}$ 的内积:
$$PE_{pos} \cdot PE_{pos+k} = \sum_{i=0}^{\frac{d}{2}-1} \sin(w_i \cdot pos) \cdot \sin(w_i \cdot (pos+k)) + \cos(w_i \cdot pos) \cdot \cos(w_i \cdot (pos+k))$$$$= \sum_{i=0}^{\frac{d}{2}-1} \cos(w_i \cdot (pos - (pos+k))) = \sum_{i=0}^{\frac{d}{2}-1} \cos(w_i \cdot k) \quad$$其中,$w_i = \frac{1}{10000^{2i/d_{model}}}$。
内积会随着相对位置 k 的增加而减小,从而表征位置的相对距离。
知识点补充
残差连接
残差连接(Residual Connection)是一种在深度神经网络中常用的技术,主要用于解决深层网络训练中的梯度消失和网络退化问题。它最早由何恺明等人在2015年提出的ResNet(Residual Network) 中引入,并成为深度学习领域的重要创新。
残差连接的核心思想是让网络学习残差(Residual)而不是直接学习目标映射。具体来说,假设我们希望网络学习一个映射 $H(x)$,残差连接将其分解为:
$$H(x) = F(x) + x$$其中:
$x$ 是输入。
$F(x)$ 是网络需要学习的残差部分。
$H(x)$ 是目标映射。
通过这种方式,网络只需要学习 $F(x) = H(x) - x$,即输入与目标之间的差异(残差),而不是直接学习复杂的映射 $H(x)$。
LayerNorm
在NLP训练过程中中,进行batch归一化是没有意义的,因为不同的句子的同一个句子的分布大概率是不相同的,而且不同的句子的长度也不一致。
所谓批次归一化是指进行归一化的时候是对批次内所有数据的维度逐个划分,每一个维度都进行归一化。而层归一化是对一个数据的所有特征进行归一化。

图4 不同归一化方案对比 ,其中N为批处理轴,C为通道轴,(H, W)为空间轴。蓝色像素通过相同的均值和方差进行归一化,这些均值和方差是通过聚合这些像素的值计算得出的
SoftMax函数
一个经典的归一化函数,具有:归一化、单调性、可导性三个性质。当输入比较大的时候可以看到曲线增长缓慢,梯度很小。
$$\text{softmax}(z_i) = \frac{e^{z_i}}{\sum_{j=1}^n e^{z_j}}$$
学习的位置嵌入(Learned Positional Embeddings)
学习的位置嵌入是一种可学习的位置编码方式。它通过为每个位置分配一个可学习的向量来表示位置信息。具体来说,模型会初始化一个位置嵌入矩阵 $E \in \mathbb{R}^{L \times d_{\text{model}}}$,其中 $L$ 是序列的最大长度,$d_{\text{model}}$ 是模型的隐藏层维度。对于序列中的每个位置 $pos$,模型会从矩阵中取出对应的嵌入向量 $E_{pos}$。
特点:
可学习:位置嵌入是模型参数的一部分,会随着训练过程更新。
灵活性:模型可以根据数据自动学习适合的位置表示。
参数依赖:需要额外的可学习参数,参数量与序列长度和模型维度相关。
作用:
学习的位置嵌入会直接加到输入嵌入上,作为模型的输入。与正弦位置编码不同,学习的位置嵌入是通过训练数据自动学习到的,因此可能更适合特定任务的数据分布。