Attention is all you need
#deepLearning/attention
Attention is all you need
Abstract
sequence transduction: 序列转录,序列到序列的生成。input一个序列,output一个序列。e.g. 机器翻译:输入一句中文,输出一句英文。
- 主流的序列转录模型
包括一个 encoder
和 一个 decoder
的 RNN
或者 CNN
架构。
表现好的序列转录模型:用了
attention
表现好的sequence transduction 模型在
encoder
和decoder
之间使用了attention
。提出基于
attention
的Transformer
实验总结 - 并行化、更少时间训练
实验 BLEU
提分介绍
2 个机器翻译任务的实验结果
英 - 德:提高 2 BLEU 英 - 法:SOTA,41.8 BLEU,只需8GPUs的3.5天的训练
- 能很好的泛化到其他任务
本文是从机器翻译的角度写的,后续 图片、视频 transformer出圈了。
Conclusion
介绍了Transformer模型,第一个仅仅使用注意力、做序列转录的模型,把之前在 encoder - decoder 的结构换成了 multi-headed self-attention.
机器翻译任务
SOTA,比其他结构训练快
纯注意力的模型其他任务的应用
图片、音频、视频;使生成不那么时序化 less sequential
代码:本文在结论部分,目前推荐放在摘要最后,方便了解论文详细内容和复现。
相关工作
联系:
- CNN(局部像素–>全部像素;多通道 –> multi-head)
- Self-attention 他人提出和应用
- Memory network 使用 recurrent attention mechanism 而不是 sequence-aligned recurrence
区别:Transformer 仅依赖 self-attention 计算输入输出的表征,没有使用 sequence-aligned RNNs or convolution.
CNN:
(cons) CNN 替换 RNN 来减少时序的计算,但 CNN 对较长的序列难以建模。因为卷积计算的时候看一个比较小的窗口,i.e., 3 * 3 窗口,如果 2 个像素隔得比较远,需要用很多 3 * 3 的卷积层、一层一层的叠加上去,才能把隔得很远的 2个像素联系起来。
Transformer 的 attention mechanism 每一次看到所有的像素,一层能够看到整个序列。
(pros) 多个输出通道,每个通道可以识别不同的模式。
Transformer 的 multi-head self-attention 模拟 CNNs 多通道输出的效果。
Self-attention 别人提出, 17年memory nework也是一个研究热点,不知道可跳过。
区别:fiirst transduction model relying entirely on self-attention to compute representations of its input and output without using sequencealigned RNNs or convolution.
Model Architecture
第一段
encoder-decoder
架构 + auto-regressive
in
decoder
sequence transduction models
比较好的架构是 encoder-decoder
Encoder
encoder
将 $x_1, x_2, … , x_n$(原始输入) 映射成 $z_1, z_2, …, z_n$(机器学习可以理解的向量)
i.e., 一个句子有 n
个词,$x_t$ 是第 t
个词,$z_t$ 是第 t
个词的向量表示。
Decoder
decoder
拿到 encoder
的输出,会生成一个长为 m
的序列$y_1, y_2, … , y_m$
n
和 m
可以一样长、可以不一样长。
i.e., 中英互译:Hello World 你好世界
encoder
和 decoder
的区别:decoder
的输出词是一个一个生成的,auto-regressive
的模型
encoder
一次性很可能看全整个句子。i.e., 翻译的时候,看到整句英语:Hello World
decoder
在解码的时候,只能一个一个的生成。 auto-regressive
,输入又是你的输出。
i.e., 给定 z
向量 $(z_1, …, z_n)$ $生成$ $y_1$,在得到 $y_1$ 之后可以生成 $y_2$。在生成 $y_t$ 的时候,要把之前的 $y_1$到 $y_{t-1}$ 都拿到。在翻译的时候,一个词一个词往外蹦。
过去时刻的输出会作为你当前时刻的输入,自回归 auto-regressive
。
第二段
Transformer
使用了 encoder-decoder
架构
堆叠的 stacked self-attention and point-wise, fully-connected layers
i.e., 中 译 英
Inputs
: 中文句子
Outputs
: decoder
在做预测的时候 是没有输入的。Shifted right
指的是 decoder
在之前时刻的一些输出,作为此时的输入。一个一个往右移。
Inputs —- Input Embedding
输入经过一个 Embedding
层, i.e., 一个词进来之后表示成一个向量。得到的向量值和 Positional Encoding
(3.5)相加。
Encoder 的核心架构
Nx
:N 个 Transformer 的 block 叠在一起。
i.e., ResNet 中 N 个残差块 的叠加。
Transformer 的 block
Multi-Head attention
Add & Norm
: 残差连接 + Layernorm
Feed Forward
: 前馈神经网络 MLP
encoder
的输出 作为 decoder
的输入
encoder
和 decoder
大部分是相同的,decoder
中多了一个 Masked Multi-Head Attention
右边三部分组成一个块重复 Nx
次得到decoder
decoder
的输出进入一个 Linear
层,做一个 softmax
,得到输出。
Linear + softmax
: 一个标准的神经网络的做法
总结:Transformer
是一个比较标准的 encoder - decoder
架构。
区别:encoder
, decoder
内部结构不同,encoder
的输出如何作为 decoder
的输入有一些不一样。
Encoder and Decoder Stacks
Encoder 结构:重复 6 个图中红色的 layer
每个 layer
有 2 个 sub-layers
。
第一个 sub-layer
是 multi-head self-attention
第二个 sub-layer
是 simple, position-wise fully connected feed-forward network
, 简称 MLP
每个 sub-layer 的输出做 残差连接 和 LayerNorm
公式:$LayerNorm( x + Sublayer(x) )$
$Sublayer(x) $指 self-attention 或者 MLP
residual connections 需要输入输出维度一致,不一致需要做投影。简单起见,固定 每一层的输出维度$dmodel = 512$
简单设计:只需调 2 个参数 dmodel 每层维度有多大 和 N 多少层,影响后续一系列网络的设计,BERT、GPT。
Remark:和 CNN、MLP 不一样。MLP 通常空间维度往下减;CNN 空间维度往下减,channel 维度往上拉。
LayerNorm 和 BatchNorm 的对比
BatchNorm
每次把一列变成,均值为 0、方差为 1 的标准化。
How:减去均值除以方差
$$
y = \frac{x - \mu}{\sqrt{\sigma(x)}} + \beta
$$
BatchNorm 还会学 lambda1 beta,BatchNorm 可以通过学习将向量放缩成任意均值、任意方差的一个向量。
LayerNorm 跟 BatchNorm 在很多时候几乎是一样的,除了实现的方法有点不一样之外。
LayerNorm
对每个样本做 Normalization(把每一行变成 均值为 0、方差为 1),不是对每个特征做 normalization。
LayerNorm 在操作上 和 BatchNorm (二维输入) 的关系
LayerNorm 整个把数据转置一次,放到 BatchNorm 里面出来的结果,再转置回去,基本上可以得到LayerNorm的结果。
Decoder 架构
decoder 和 encoder 很像,6 个 相同 layer 的堆叠、每个 sub-layer 的 residual connections、layer normalization。
每个 layer 里有 2个 encoder 中的 sub-layers, decoder 有第 3 个 sub-layer,对 encoder 的输出做 multi-head attention。
decoder 是 auto-regressive 自回归: 当前时刻的输入集是之前一些时刻的输出。做预测时,decoder 不能看到之后时刻的输出。
attention mechanism: 每一次能看完完整的输入,要避免这个情况的发生。
在 decoder 训练的时候,在预测第 t 个时刻的输出的时候,decoder不应该看到 t 时刻以后的那些输入。它的做法是通过一个带掩码 masked 的注意力机制。保证训练和预测时行为一致。
解码器堆栈中的自注意力(self-attention)子层被修改,以防止位置关注到后续的位置。这种掩码技术,结合输出嵌入(output embeddings)被向后偏移一个位置的事实,确保了对于位置i的预测只能依赖于小于i的位置上已知的输出。简而言之,这意味着在生成当前位置的预测时,解码器只能考虑到当前位置之前的信息,确保了信息的按顺序处理。
Attention
注意力函数是 一个将一个 query 和一些 key - value 对 映射成一个输出的函数,其中所有的 query、key、value 和 output 都是向量。
具体来说,output 是 value 的一个加权和 –> 输出的维度 == value 的维度。
output 中 value 的权重 = 查询 query 和对应的 key 的相似度 or compatibility function
权重等价于 query 和对应的 key 的相似度
虽然 key-value 并没有变,但是随着 query 的改变,因为权重的分配不一样,导致 输出会有不一样,这就是注意力机制。
Scaled Dot-Product Attention
缩放点积注意力机制的简易性:
- 被认为是最简单的注意力机制,因为它的实现相对直接,主要依赖于矩阵乘法和softmax函数。
相似度函数:
- 不同的相似度函数会导致不同类型的注意力机制。在缩放点积注意力中,使用内积作为相似度函数。
向量维度:
- 查询(Query)和键(Key)向量的长度相等,都是 ( $d_k$ )。
- 值(Value)向量和输出向量的维度是 ( $d_v$ )。
向量内积:
- 对每个查询和键向量进行内积运算,以此来计算它们之间的相似度。
- 如果两个向量的内积较大(并且向量的范数一致),它们的余弦相似度越大,表示它们的相似度高。
- 内积为0表示两个向量正交,没有相似度。
计算注意力:
- 使用softmax函数处理每个查询对所有键向量的内积得分,并除以 ( $\sqrt{d_k}$ ) 进行缩放。
- softmax函数输出一组权重,每个权重对应一个键-值对。
- 将这些权重应用于值(Value)矩阵,通过加权求和得到最终的注意力输出。
$$attention = softmax( \frac{两个向量的内积值} {\sqrt{dk}}) * V, dk: 向量的长度$$
实际运算:
- 在实践中,为了效率,通常不会单独对每个查询进行计算,而是将多个查询组成一个矩阵,利用矩阵运算进行并行化处理。
- ( Q ) 和 ( K ) 的矩阵乘法 ( $QK^T$ ) 会得到一个 ( $n \times m$ ) 的矩阵,其中每个元素代表一个查询和键的内积。
- 对 ( $QK^T$ ) 每一行进行softmax处理,得到权重。
- 这些权重与值(Value)矩阵 ( V ) 相乘,得到一个 ( $n \times d_v$ ) 的矩阵,即为最终的注意力输出。
$$Q \times K^T:(n \times dk) * (m \times dk)^T = (n \times m)$$
$$softmax( \frac{Q K^T} {\sqrt{dk}}) V = (n * m) * (m * dv)= (n * dv)$$
Scaled Dot-Product Attention 和 其他注意力机制的区别
加性注意力机制(Additive Attention):
- 它通过一个可学习的权重矩阵来计算查询(query)和键(key)之间的相似度。
- 适用于处理长度不同的查询和键向量。
点积注意力机制(Dot-Product Attention):
- 直接通过计算查询和键的点积来衡量它们之间的相似度。
- 采用缩放因子(除以$( \sqrt{d_k} )$),称为
缩放点积注意力(Scaled Dot-Product Attention)
。
选择点积注意力机制的原因:
- 实现简单:它比加性注意力更易于实现,因为它仅涉及矩阵乘法,不需要额外的参数学习。
- 高效:从计算的角度来看,点积注意力比加性注意力更快,尤其是在使用硬件加速时(如GPU)。
采用缩放点积注意力机制的原因:
- 当 ( $d_k$ )(键向量的维度)较大时,未缩放的点积会导致非常大的数值,这可能会造成softmax函数在计算梯度时的数值不稳定(梯度消失问题)。
- 缩放因子 ( $\frac{1}{\sqrt{d_k}}$ ) 能够缓和这个问题,让softmax函数的输出更加稳定,避免梯度过小。
梯度消失问题:
- 如果点积值非常大,softmax的输出会倾向于有一个值非常接近1而其他都接近0。
- 这导致模型在训练过程中的梯度变小,从而使学习变得非常缓慢或者停滞不前。
Softmax函数的特点:
- Softmax函数会将一个实数向量转换为一个概率分布。
- 在这个转换过程中,较大的数值(相对于其他分量)会被映射到接近1的概率,而较小的数值会接近0。这种效果被描述为“放大”差距。
对于训练的影响:
- 当softmax函数的输出极端化(即接近0或1)时,对应的梯度可能会非常小。这是因为softmax函数的梯度与输出概率之间的差距有关:当输出概率接近1或0时,关于输入的梯度就会小。
- 这个小的梯度(也称为梯度消失)会导致在训练过程中更新权重的步长变小,使得训练过程变慢或甚至停滞。
在Transformer中的应用:
- Transformer模型中,( $d_k$ )(键的维度)通常设定为一个较大的值,例如512。这是为了使得模型能够学习到更加丰富和细致的表示。
- 由于( $d_k$ )的值较大,直接使用点积注意力机制可能会导致softmax函数的输入过大,从而使梯度消失问题更加严重。
- 因此,在Transformer模型中,通过将点积的结果除以( $\sqrt{d_k}$ )来进行缩放,这样可以减小softmax函数输入的数值范围,使得梯度更加稳定,从而使训练过程更加高效和稳定。
总结:
在Transformer架构中,采用缩放点积注意力机制是为了缓解因为( d_k )较大而导致的梯度消失问题,使得模型训练过程中的权重更新更加稳定。这种缩放有助于维持梯度在一个合理的范围内,从而避免训练过程中的停滞,确保了模型能够有效学习。
遮掩操作 (Masking)
遮掩操作:
- 创建一个遮掩矩阵(mask),它与注意力分数矩阵(即 ( QK^T ))具有相同的维度。
- 在遮掩矩阵中,时刻 ( t ) 以后的所有位置都设为0,其余位置设为1。
- 避免在 t 时刻,看到 t 时刻以后的输入。
- 在计算权重的时候, t 时刻只用了 $k_1, …, k_{t-1}$ 的结果,不要用到 t 时刻以后的内容。
应用遮掩:
- 将遮掩矩阵应用于未缩放的注意力分数矩阵 ( $QK^T$ )。在实践中,这通常是通过对遮掩矩阵中为0的位置在分数矩阵中对应的位置上减去一个非常大的数值(例如,( $-e^{10}$ ))来实现的。这个非常大的负数在经过softmax函数后会接近0。
计算权重:
- 在计算权重的时候, t 时刻只用了 $k_1, …, k_{t-1}$ 的结果,不要用到 t 时刻以后的内容。
- 计算softmax函数,此时 t 时刻以后的权重会变得非常小(接近于0)。
- 这样,在计算最终的加权值(即 $\text{softmax}(QK^T)V$ )时, t 时刻以后的值基本上不会对输出产生影响。
Multi-head attention
多头注意力机制不单是执行单一的注意力函数那么简单。相反,它涉及将整个查询(query)、键(key)和值(value)映射到一个较低维度的空间中,这一映射过程会进行 h 次。接着,对每一次映射后的结果执行一次缩放点积注意力计算,将这些计算的输出拼接起来,再通过另一个线性层进行映射,最终形成多头注意力的输出。
具体步骤如下:
- 原始的查询(query)、键(key)和值(value)通过一个线性层进行映射,对于每个头,将Q、K、V通过可学习的线性变换(分别是($W^Q$)、($W^K$)、($W^V$))投影到低维空间。
- 每个变换的输出维度是 ($d_v = \frac{d_{\text{model}}}{h}$),其中 ($d_{\text{model}}$) 是模型的维度,($h$) 是头的数量。
- 这一层将它们投影到一个较低的维度空间。
- 在这个较低维度空间内,执行 h 次缩放点积注意力的计算,每次计算都独立进行。
- 将这 h 次注意力计算的输出向量进行合并(拼接),形成一个长向量。
- 这个长向量再次通过一个线性层进行映射,将所有头的输出拼接(concat)起来,然后通过另一个可学习的线性变换 ($W^O$),以生成多头注意力机制 ( Multi-head attention ) 的最终输出。
- 采用8个头的情况下,每个头处理的维度降低到原始维度的1/8,即64维(假设$d_{model}=512$)。
Applications of attentions in our model
encoder 的注意力层:
i.e., 句子长度是 n,encoder 的输入是一个 n 个长为 d 的向量。
假设 pn 大小设成 1 了,每一个输入词对应的是一个长为 d 的向量。
encoder 的注意力层,有三个输入,它分别表示的是key、value 和 query。
一根线过来,它复制成了三下:同样一个东西,既 key 也作为 value 也作为 query,所以叫做自注意力机制。key、value 和 query 其实就是一个东西,就是自己本身。
输入了 n 个 query,每个 query 会得到一个输出,那么会有 n 个输出。
输出 是 value 加权和(权重是 query 和 key 的相似度),输出的维度 == d – > 输入维度 == 输出维度
相似度越高,权重也会高一些
不考虑 multi-head 和 有投影的情况:
- 输出是 输入的加权和,其权重来自 每个向量与其它向量的相似度。
multi-head 和 有投影的情况:
- 学习 h 个不一样的距离空间,使得输出有变化。
decoder 的 masked multi-head attention
输入和 encoder 一样复制 3 份。
和 encoder 不一样的地方是 mask,所以 t 时刻以后的输入要设为 0
decoder 的 multi-head attention
不再是 self-attention,而是 key - value 来自 encoder 的输出。
query 是来自 decoder 里 masked multi-head attention 的输出。
encoder 的输出作为 value 和 key 输入,decoder 下一层的输出作为 query 输入
encoder 最后一层的输出: n 个 长为 d 的向量
decoder 的 masked multi-head attention + Add & Norm 的输出: m 个 长为 d 的向量
根据 query 输出: value 的加权和(权重取决于encoder 和 decoder 输出的相似度)
第 3 个 attention 层: 根据 query 去有效的提取 encoder 层输出
例子:
- 当计算“好”(假设是句子中的一个词)的表示时,“好”作为query,会与序列中的每个词(包括“hello”、“world”等)作为key的相似度进行比较。
- 如果“好”与“hello”向量相近,那么在计算“好”的表示时,“hello”会被赋予较大的权重。这意味着“hello”的信息在形成“好”的上下文表示时会被更多地考虑。
- 相反,如果“world”与“好”的相似度不高,那么在计算“好”的表示时,“world”将被赋予较小的权重。
- 当处理另一个query,比如“世”时,如果“世”与“world”的相似度较高,那么“world”将会被赋予较大的权重,反映在“世”的上下文表示中。
根据解码器的输入的不一样,会根据当前的 query 向量,去在编码器的输出里面去挑 (query) 感兴趣的东西。
attention:query 注意到 当前的 query 感兴趣的东西,对当前的 query的不感兴趣的内容,可以忽略掉。 –> attention 作用:在 encoder 和 decoder 之间传递信息
Position-wise Feed-Forward Networks
作用在最后一个维度的 MLP
MLP: applied to each position separately and identically.
Point-wise: 把一个 MLP 对每一个词 (position)作用一次,对每个词作用的是同样的 MLP
FFN: Linear + ReLU + Linear
单隐藏层的 MLP,中间 W1 扩维到4倍 2048,最后 W2 投影回到 512 维度大小,便于残差连接。
pytorch 实现:2个线性层。pytorch 在输入是3d的时候,默认在最后一个维度做计算。
最简单情况:没有残差连接、没有 layernorm、 attention 单头、没有投影。看和 RNN 区别
attention 对输入做一个加权和,加权和 进入 point-wise MLP。(画了多个红色方块 MLP, 是一个权重相同的 MLP)
point-wise MLP 对 每个输入的点 做计算,得到输出。
attention 作用:把整个序列里面的信息抓取出来,做一次汇聚 aggregation
图中红色填充块,已经就有了,序列中感兴趣的东西
以至于我在做投影,在做 MLP 的时候映射成我更想要的那个语义空间的时候,因为这个东西已经含有了我的序列信息,所以每个 MLP 只要在对每个点独立做就行了。
历史信息,因为这个地方序列信息已经被汇聚完成,所以 MLP 是可以分开做的,也就整这个 transformer 是如何抽取序列信息,然后把这些信息加工成我最后要的语义空间,向量的过程
对比 RNN 怎么做的。
图中 绿色 表示之前的信息
RNN 跟 transformer 异:如何传递序列的信息
Transformer 通过一个 attention 层,去全局的拿到整个序列里面信息,再用 MLP 做语义的转换。
RNN 是把上一个时刻的信息输出传入下一个时候做输入。
- 全局信息处理:Transformer 能够通过其注意力机制 (attention) 一次性考虑整个序列的信息。
- RNN 则通过逐步处理序列并在每个时间点传递信息,把上一个时刻的信息输出传入下一个时候做输入来实现。
RNN 跟 transformer 同:语义空间的转换 + 关注点
- 语义空间的转换:无论是Transformer还是RNN,都需要通过某种形式的变换(线性层或MLP)来做语义空间的转换。
- 序列信息的利用:两者都旨在有效利用序列信息,尽管它们采取的技术路线和机制不同。
Embeddings and Softmax
Embedding层
- 目的:Embedding层的主要目的是将输入的词或词语标记(token)映射成一个固定长度 d(在这里是512维)的向量。这个向量旨在捕捉和表示词语的语义特征。
- 权重共享:在Transformer模型中,编码器、解码器以及 softmax 层之前的embedding层共享权重。这意味着同一个词语无论出现在输入、输出还是模型内部的任何位置,都会被映射到相同的向量表示。权重共享简化了训练过程,并有助于模型更好地学习和理解语言的一致性。
- 缩放因子:为了保持embedding向量的尺度合理,模型会乘以一个缩放因子($\sqrt{d_{model}}$)(这里($d_{model}=512$))。这个缩放操作有两个目的:
- 保持L2范数的大小:确保学习到的向量在L2范数上相对较小(比如接近1),这有助于避免在高维空间中的距离度量问题。i.e., 学成 1, 不论维度多大,最后的值都会 = 1。
- 平衡尺度:由于positional encoding的值不会随着维度的增加而变化,乘以($\sqrt{d_{model}}$)有助于使embedding向量和positional encoding在 scale 上保持一致,使得两者可以直接相加。
Softmax层
- 作用:在模型的最后阶段,softmax层用于将解码器输出的向量转换成一个概率分布,表示每个可能的下一个词语的概率。这个概率分布随后用于选择最可能的词语作为输出。
- 与Embedding权重共享:在某些Transformer实现中,softmax层之前的线性层的权重与embedding层的权重共享。这种共享策略是基于这样一个假设:如果模型能够将词语有效地映射到一个高维空间中,那么相反的映射(从高维空间映射回词语)也应该使用相同的权重结构。
Positional Encoding
Transformer模型由于其自注意力机制的特性,本身不具备处理序列中时序信息的能力。这是因为自注意力机制在计算时只关注词之间的相互关系,而不考虑它们在序列中的位置。这意味着,如果不加以处理,模型将无法区分相同词语的不同排列顺序。
为了解决这个问题,Transformer模型引入了位置编码(positional encoding)机制,目的是在不改变自注意力机制的基础上,向模型输入中加入关于单词位置的信息。
output 是 value 的 加权和(权重是 query 和 key 之间的距离,和 序列信息 无关)。
根本不看 key - value 对在序列哪些地方。一句话把顺序任意打乱之后,attention 出来,结果都是一样的。
在处理时序数据的时候,一句话里面的词完全打乱,那么语义肯定会发生变化,但是 attention 不会处理这个情况。 所以加入了时序信息。
如何实现位置编码:
原理:位置编码通过为每个位置生成一个独特的向量,并将这个向量加到对应位置的词向量(embedding)上,从而实现位置信息的编码。这样,即使词的顺序改变,改变后的位置向量也会反映出来,从而使模型能够捕捉到序列中词的顺序变化。
计算方法:位置编码向量的生成通常使用正弦和余弦函数的组合来实现,这些函数以不同的频率变化,从而为序列中的每个位置生成独特的位置向量。具体来说,对于位置($pos$)和维度($i$),位置编码($PE(pos, i)$)使用如下的正弦和余弦函数计算:
- $PE(pos, 2i) = \sin(pos / 10000^{2i/d_{model}})$
- $PE(pos, 2i+1) = \cos(pos / 10000^{2i/d_{model}})$
这里,($d_{model}$)是模型的维度,($i$)是维度索引,($pos$)是词在序列中的位置。
目的:这种方式生成的位置向量能够让模型根据词的相对或绝对位置进行学习,并保持位置向量的维度与词向量的维度一致,使得两者可以通过简单的加法操作结合在一起。
位置编码的作用:
- 时序信息的引入:通过加入位置编码,Transformer模型能够观察到词在序列中的位置,进而理解词序变化带来的语义变化。
- 保持尺度一致性:正如之前提到的,输入嵌入向量会乘以($\sqrt{d_{model}}$)以保持其尺度,位置编码的设计(使用($[-1, +1]$)范围内的值)确保了加入位置信息后,整个向量的尺度仍然适合模型处理。
实现时序信息的添加
- RNN与时序信息:RNN通过将上一时刻的输出作为下一个时刻的输入来自然地保持时序信息。这种逐步处理的方式使得每个时刻的输出都依赖于之前时刻的信息,从而在序列处理中保留了时间顺序的概念。
- Transformer中的Positional Encoding:与RNN不同,Transformer通过向每个输入元素的嵌入向量添加位置编码来注入时序信息。位置编码是一个与嵌入向量同维度的向量(在这里是512维),它代表了元素在序列中的位置信息。这样,即使在自注意力层中元素的处理是并行且独立的,模型也能够通过这些加入的位置信息来理解序列中元素的顺序。
如何实现Positional Encoding
当输入数据进入Transformer模型的嵌入层(embedding layer)时,每个词语都被转换为一个512维的向量。为了在模型中加入序列的时序信息,位置编码(positional encoding)被引入。每个词语在句子中的位置都通过一个同样长度为512维的向量来表示,该向量是通过周期性变化的正弦(sin)和余弦(cos)函数生成的,确保了每个位置的唯一性。因此,位置编码的值在[-1, +1]之间波动。
为了使词嵌入向量与位置向量在尺度上一致,输入的词嵌入向量会先乘以一个缩放因子($\sqrt{d}$),其中($d$)是模型的维度(本例中为512)。这一步骤确保了乘积后的向量数值也大约在$[-1, +1]$的范围内。随后,词嵌入向量和位置编码向量相加,从而将时序信息直接融入到每个词的表示中。
结果
- 顺序敏感性:通过加入位置编码,即使输入序列被打乱,Transformer也能够通过学习到的位置信息来恢复元素间正确的顺序关系。这保证了模型在处理如翻译、文本生成等依赖于序列信息的任务时的效能。
Why Self-attention
在这段文字中,作者讨论了为什么选择自注意力(self-attention)机制作为模型的核心组成部分,并与循环层(recurrent layers)和卷积层(convolutional layers)进行了比较。让我们一一解释这些观点。
模型设计理念:
- 计算复杂度:模型旨在降低每层的计算复杂度,从而提高训练和推理的效率。
- 并行计算能力:自注意力机制允许模型并行处理序列中的所有元素,这是循环层无法实现的。循环层需要按顺序依次处理每个序列元素,因此其并行度较低。
- 捕捉长距离依赖:自注意力能够捕捉长距离依赖关系,而这通常是序列转换任务中的一个挑战。这是因为自注意力机制允许模型在任何两个输入和输出位置之间直接建立联系,从而学习这些依赖。
Table 1 解释:
在表格1中,自注意力(self-attention)、循环层(recurrent)、卷积层(convolutional)和受限自注意力(self-attention(restricted))在不同的性能指标上进行了比较:
Complexity per Layer:
- 自注意力的复杂度是($O(n^2 \cdot d)$),主要是因为每个query都要和所有的key进行比较和乘法运算,其中($n$)是序列长度,($d$)是向量维度。
- 循环层的复杂度是($O(n \cdot d^2)$),因为每个时间点上都要执行一个复杂度为($O(d^2)$)的dense layer运算,并且要连续执行($n$)次。
- 卷积层的复杂度取决于卷积核的宽度和层数,但通常与循环层相似。
- 受限自注意力则是对近邻元素进行自注意力计算,复杂度降低到($O(n \cdot r \cdot d)$),其中($r$)是考虑的邻域大小。
Sequential Operations:
- 自注意力的并行度最高,为($O(1)$),因为矩阵乘法可以完全并行化。
- 循环层必须顺序执行,因此并行度最低,为($O(n)$)。
- 卷积层和受限自注意力的并行度介于两者之间。
Maximum Path Length:
- 自注意力可以直接连接任何两个位置,因此路径长度为($O(1)$)。
- 循环层需要通过中间状态传递信息,因此路径长度为($O(n)$)。
- 卷积层和受限自注意力的路径长度取决于卷积核大小和近邻的范围。
Training
Optimizer
在训练Transformer模型时,通常使用Adam优化器,它是一种自适应学习率优化算法,非常适合处理大规模和高维度的数据集。Adam优化器有两个重要的超参数:($\beta_1$)和($\beta_2$)。其中,($\beta_2$)通常设置为0.99或0.999,这个参数控制着二阶矩估计的衰减速率,影响模型参数的更新速度,这里其超参数($\beta_1$)设置为0.9,($\beta_2$)设置为0.98,($\epsilon$)设置为($10^{-9}$)。
学习率的调整遵循以下公式:
$$\text{lrate} = d_{\text{model}}^{-0.5} \cdot \min(\text{step_num}^{-0.5}, \text{step_num} \cdot \text{warmup_steps}^{-1.5}) $$
这个公式意味着学习率会在训练开始的一段时间内线性增加,这个时间段就是预热(warm-up)阶段。具体来说,在前4000个训练步骤中(即warmup_steps = 4000
),学习率会从一个很小的值逐步增加到较大的一个值。预热阶段之后,学习率将按照步数的平方根的倒数逐步减小。
在Transformer的训练过程中,学习率的设定遵循特定的公式,而不是简单地手动设置一个固定的值。Transformer使用了一种基于模型维度( $d_{\text{model}}$ )和训练步数(step number)的动态学习率调整策略:
学习率与模型宽度的关系:学习率与模型的维度成反比,即 ( $\text{学习率} \propto \frac{1}{\sqrt{d_{\text{model}}}}$)。这意味着模型宽度越大(维度( $d_{\text{model}}$ )越高),学习率就越低。这个设计考虑了更宽的模型在参数更新时可能需要更小的学习步长,以避免过大的参数更新。
学习率预热(Warm-up):Transformer使用了学习率预热的策略,即在训练初期,学习率从一个较小的值逐渐增加到一个预定的值。这有助于模型在训练初期稳定地学习,并避免因学习率过高导致的训练不稳定。
学习率衰减:达到预定的warm-up步骤数后,学习率会根据训练步数的平方根逐渐衰减,即 ($ \text{学习率} \propto \frac{1}{\sqrt{\text{step number}}}$ )。这个衰减策略确保了在训练后期,随着模型逐渐收敛,学习率能够逐步降低,以细化模型参数的调整。
Regularization
在这里,Transformer模型使用了三种正则化策略:
- 残差Dropout(Residual Dropout):在每个子层的输出上应用dropout,然后将其与该子层的输入相加,并进行归一化处理。Dropout是一种正则化技术,它在训练期间随机地将网络中的一些输出单元置零,可以减少模型对训练样本的依赖,从而增加模型的泛化能力。残差dropout是特指在添加残差连接之前对子层的输出应用dropout。
- 对Embeddings和Positional Encodings的和进行Dropout:不仅仅是在子层的输出上使用dropout,Transformer还在将embeddings和位置编码相加之后的结果上也使用dropout。这样做可以进一步增加模型在编码输入序列时的鲁棒性。
- Dropout率:基础模型中使用的dropout率是0.1,这意味着在每个训练步骤中,每个单元有10%的概率会被随机丢弃。
Label smoothing
Label smoothing是一种在训练深度学习模型时常用的技术,特别是在分类问题中。它的核心思想是让模型不要过于自信地预测一个类别,而是给予一定的概率给其他类别,即使这些类别可能是错误的。这种方法最早是在Inception V3模型中使用的,并被证明可以提高模型的泛化能力。
在没有label smoothing的情况下,如果我们使用硬标签(hard labels),即标签是0或1,那么模型在训练时会被鼓励去预测非常极端的概率,比如接近0或1。然而,这会导致模型在预测时过于自信,可能会忽略输入数据中的细微差别,从而导致泛化性能下降。
使用label smoothing后,正确类别的标签不再是1,而是略低于1的值(比如0.9),而其他错误类别的标签则分摊剩余的概率值(假设有N个类别,则每个错误类别分摊到的概率为(0.1/(N-1)))。这样做的效果是降低了模型输出的自信度,使得模型在预测时更加谨慎。
在评估模型性能时,困惑度(perplexity)是衡量模型不确定性的一个指标,它是对交叉熵损失(cross-entropy loss)的指数。当使用label smoothing时,即使模型对正确类别的预测概率只有0.1,模型的交叉熵损失也会减少,因为模型不再被迫去预测非常小或非常大的概率值。这可以减少模型的困惑度,因为模型不需要对每个样本都非常确定。
超参数的对比:只调 N层数、dmodel模型的宽、注意力的head数 h
在深度学习和特别是在Transformer模型中,超参数的选择对模型性能有显著影响。以下是对Transformer模型中几个关键超参数的作用及其如何影响模型复杂度的解释:
$N$(层数):指的是Transformer模型中堆叠的编码器和解码器层数。每增加一层,模型能够学习更复杂的特征表示,但同时也增加了计算复杂度和训练难度。
($d_{\text{model}}$)(模型宽度):表示每个词或token输入后被嵌入成的向量的维度。更宽的模型可以捕获更丰富的信息,但也需要更多的参数和计算资源。
($d_{\text{ff}}$)(前馈网络维度):是指在模型中每个注意力机制之后的前馈网络的中间层的维度。这个参数决定了前馈网络能够处理的信息量。
$h$(头数):即注意力机制中的头(head)数目。多头注意力允许模型在不同的表示子空间中并行地学习信息。每个头学习到的是不同方面的信息,增加头数可以增加模型的表示能力。
($d_k$)和($d_v$):分别是注意力机制中key和value的维度。通常情况下,它们被设置为($d_{\text{model}} / h$)。
($P_{\text{drop}}$):是dropout技术中的丢弃概率,用于正则化以防止过拟合。增加dropout率可以让模型更加健壮,但也可能降低训练速度。
($E_{\text{ls}}$):是label smoothing中正确标签所赋予的值。通过调整这个值,可以控制模型的自信程度,防止模型过度自信于其预测。
当对一个大型模型进行调整时,如将模型宽度和中间层输出维度增加一倍,同时增加头数(但保持($d_k$)和($d_v$)的维度不变),会使模型更为复杂。为了应对这种复杂度,可能需要增加dropout率以避免过拟合,并且需要更多的训练步骤来确保模型的收敛。