Attention Is All You Need论文阅读笔记

Attention is All You Need是如今机器学习研究者必读的论文,该文章提出的Transformer架构是如今很多机器学习项目的基础,说该文章极大推动了机器学习领域的研究也不为过。

但这么重要,也是必读的文章对初学者来说其实并不友好,很多前置知识和背景可能因为篇幅原因并没有详细介绍,故本文参考周奕帆的解读Transformer注意力以及illustrated transformer的同时,再补充更多基础知识,希望让机器学习的初学者也能很快读懂这篇文章。

前置知识

循环神经网络RNN

普通神经网络的大致结构为输入层=>隐含层=>输出层,层与层之间全连接,但层内的节点互相没有连接,所以该网络只能处理顺序递进的任务,而无法处理前后相关联的,比如翻译等任务。

为解决同一层次节点的关联问题,RNN诞生了,该网络会记忆前面节点的信息并用于当前输出的计算。即隐藏层之间的节点不再无连接而是有连接的,并且隐藏层的输入不仅包括输入层的输出还包括上一时刻隐藏层的输出。

针对翻译任务,其解决过程大致如下:

复制代码
I want to eat a hamburger, it is so delicious
-->我想吃
-->我想吃汉堡
-->我想吃汉堡,它/他/她(代指谁要看前面语境,RNN的主要结构创新,用前面的输出作为下一层的输入)
-->我想吃汉堡,汉堡实在太好吃了

该网络的多种结构如下图,这些不同结构的应用与详解可见RNN详解

编码器与解码器Encoder-Decoder

原始RNN结构在处理翻译任务时只能实现等长的输入输出 ,然而翻译任务的输入输出在大多数情景下都是不等长的。

为此人们设计了一种新的架构,该架构将RNN网络分成两部分,前半段只有输入,后半段只有输出,中间通过一个状态来转递信息,这就是编码器解码器结构Encoder-Decoder

该结构不是具体的网络,而是一种框架的统称,编码器Encoder负责将输入转换为固定长度的向量,解码器Decoder负责将固定长度的向量转换成输出,因为该结构不限制输入和输出长度,所以应用十分广泛,应用场景有:

1,机器翻译:Encoder-Decoder的最经典应用,事实上该结构就是在机器翻译领域最先提出的。

2,文本摘要:输入是一段文本序列,输出是这段文本序列的摘要序列。

3,阅读理解:将输入的文章和问题分别编码,再对其进行解码得到问题的答案。

4,语音识别:输入是语音信号序列,输出是文字序列。

注意力模型

经过上面的介绍我们可能想到,输入和输出之间只有一个固定长度的中间向量作为连接,当输入较长时,该定长向量还能否保证信息完整性,这就是RNN的不足。

为此,有人提出了注意力机制attention mechanism,该机制仍然使用编码器和解码器,但在不同时间输入多个中间向量来解决问题,解码器的输入是编码器结果的加权和,而非简单的中间向量,每个输入对输出的权重叫注意力,注意力的大小取决于输入输出的相关性。

注意力框架从结构上的变化如下图:

以翻译为例,数学计算上的结构如下图,其中 a i j a_{ij} aij表示相关性, h i h_i hi为 i i i阶段输入, c i c_i ci为 i i i阶段中间向量:

注意力机制优化了解码器与编码器的信息交流方式,处理长文章时更有效,但所有基于RNN的结构也都面临同一个问题:因为本轮输入取决于上一轮的状态,所以训练过程必须是线性执行的,RNN的训练速度较慢

基于上述研究现状,放弃RNN,完全使用注意力机制的Transformer问世了。

文章摘要

摘要中提到序列传导模型中性能最好的是用注意力机制连接编码器和解码器的框架,但该框架仍基于复杂的递归和卷积神经网络,故文章提出了一种完全基于注意力机制,无需递归和卷积网络的框架。实验结果显示模型的质量上乘,并且训练时间明显减少。

由前置知识中的注意力模型我们知道,RNN网络虽然解决了元素相关依赖的问题,但是其输入取决于上一轮状态,训练过程的效率较低。

本文引言中将该问题描述为:"这种固有的 Sequences 性质排除了训练样本中的并行化,这在较长的序列长度下变得至关重要,因为内存约束限制了样本之间的批处理。最近的工作通过因式分解技巧和条件计算实现了计算效率的显著提高,同时也提高了后者情况下的模型性能。但是,顺序计算的基本约束仍然存在。"

该描述引出了Transfomer要解决的问题------提高并行训练效率

随后介绍了注意力机制:"注意力机制已成为各种任务中引人注目的序列建模和转导模型不可或缺的一部分,允许对依赖关系进行建模,而不考虑它们在输入或输出序列中的距离。然而,除了少数情况外,这种注意力机制都与循环网络结合使用。在这项工作中,我们提出了 Transformer,这是一种避免重复出现的模型架构,而是完全依赖注意力机制来绘制输入和输出之间的全局依赖关系。Transformer 允许显著提高并行化水平,并且在 8 个 P100 GPU 上经过短短 12 小时的训练后,就可以达到翻译质量的新水平。"

上述内容指出注意力机制可以无视序列中的距离,作者依据该机制提出了一种全新的名为Transformer的架构,可以绘制输入输出的依赖关系,训练速度更快,表现也更好。

也就是放弃RNN网络,仅使用注意力机制构造新的结构,以绘制全局依赖关系

注意力机制

感性认识

论文自顶向下介绍设计,但读者可能并不了解模块,一下引入过多新概念容易劝退读者,所以本文跟随周奕帆的思路,介绍顺序修改为自底向上,首先介绍论文的关键机制------注意力。

论文首先对注意力作了大致解释:注意力函数可以描述为将查询和一组键值对映射到输出,其中查询、键、值和输出都是向量。其中输出由值的权重和构成。像是数据库的查询操作。

在学习具体算法之前我们通过一个案例对注意力机制先形成一个感性认识:

比如有如下键值对姓名key-年龄value的数据集合张三:18, 李四:22, 张五:25,要执行查询query为:姓张年龄的平均数,查询条件为key[0]=='张'

但在神经网络中很多操作可能并没有现实意义,只是单纯的数学运算,所以我们可以将一切都转换为数字和向量。比如原有的数据集合可转变为[1,0,0]:18, [0,2,1]:22, [1,3,2]:25,假设表示为1,那原有对姓张的查询就可以表示为向量[1,0,0],使用该查询向量与集合向量作点积可得到权重向量[1,0,1],如果该权重之和大于1,可用激活函数softmax进行归一化处理,结果为[1/2,0,1/2],获得的权重向量中的数值就是对不同key的注意力

该过程用数学表示如下:

复制代码
[1,0,0]:18 # 张三
[0,2,1]:22 # 李四
[1,3,2]:25	# 张五

# 查询向量[1,0,0]
# 查询过程,最后获取权重
dot([1,0,0],[1,0,0])=1 
dot([0,2,1],[1,0,0])=0
dot([1,3,2],[1,0,0])=1

# 归一化处理,获对每个key的注意力
softmax([1,0,1])=[1/2,0,1/2]
dot([1/2,0,1/2],[18,22,25])=21.5
平均年龄为21.5

到这里我们也会有感觉,这注意力明明是一次查询匹配的归一化结果,重点应该在查而不在注意上,周也认为该机制称为"全局信息查询"才更合理。

缩放点积注意力Scaled Dot-Product Attention

Q Q Q代表查询向量组,可由多个查询如 q = [ 1 , 0 , 0 ] q=[1,0,0] q=[1,0,0]的组成;
K K K是键key的向量组, V V V则是键值value的向量组,用数学符号表示感性认识中的操作为:
m y a t t e n t i o n ( q , K , V ) = s o f t m a x ( q K T ) V myattention(q,K,V)=softmax(qK^T)V myattention(q,K,V)=softmax(qKT)V

有关softmax的知识可见深度学习基础,该算法用于多分类问题,将结果归一化成概率可能性,归一化后的结果数值为正和为1。

论文中的注意力机制与我们的感性认识大致相同,文章将其称为"缩放点积注意力",大名鼎鼎的注意力公式如下:
A t t e n t i o n ( Q , K , V ) = s o f t m a x ( Q K T d k ) V Attention(Q,K,V)=softmax(\frac{QK^T}{\sqrt{d_k} } )V Attention(Q,K,V)=softmax(dk QKT)V

多个查询 q q q的组合就是 Q Q Q,我们的感性认识和该公式只差一步 d k d_k dk;

论文还引入了两个变量,分别是键的维度 d k d_k dk,键值的维度为 d v d_v dv,在该公式中,因为 Q Q Q和 K K K要作点积预算,所以 Q Q Q的维度要和 d k d_k dk一致,而 d v d_v dv则无要求。

所以 a t t e n t i o n attention attention的本质就是在我们感性认识的基础上用 k k k的维度对注意力进行了缩放,那为什么要进行这一步操作呢?这涉及深度学习中激活函数的特性,周的解释为:"softmax在绝对值较大的区域梯度较小,梯度下降的速度比较慢。因此,我们要让被softmax的点乘数值尽可能小。而一般dk在较大时,也就是向量较长时,点乘的数值会比较大。除以一个和dk相关的量能够防止点乘的值过大。"

注意力函数除了本文提到点积的方法,还有加性注意力,效率上点积更快一些,故该论文选了这种方法。

缩放点积注意力的执行流程图如下:

1,输入 Q , K , V Q,K,V Q,K,V, M a t M u l MatMul MatMul矩阵乘法,计算查询 Q Q Q和键 K K K的相关度,多采用点积计算;

2, S c a l e Scale Scale缩放,除 d k \sqrt{d_k} dk ;

3, M a s k Mask Mask掩码,屏蔽后续信息,将在整体框架中介绍;

4, S o f t M a x SoftMax SoftMax归一化;

5,最后将查询归一化结果与键值 V V V作乘法,计算注意力结果。

自注意力Self-Attention

自注意力在文中介绍很少,但在注意力机制中又是很关键的内容,所以展开学习一下。

1,感性认识

在翻译场景下,注意力机制用于实现英文到中文的翻译转换,自注意力则是完成序列内词义的确定, ,比如"The animal didn't cross the street because it was too tired",如何确定后面的it是指animal还是street呢?通过自注意力机制可确定it的翻译要重点关注animal

有关该部分详细解释可参考一文搞定自注意力机制

公式上变为如下形式:
s e l f − a t t e n t i o n ( X ) = s o f t m a x ( x x T d k ) X self-attention(X)=softmax(\frac{xx^T}{\sqrt{d_k} } )X self−attention(X)=softmax(dk xxT)X

其中 X X X是序列中的所有元素, d k d_k dk是向量的维度。

所以自注意力本质是注意力机制的一种特殊形式,每个输入元素与序列中的其他元素进行交互,计算得出自己的自身的表示,其实就是输入token[i]和整个输入token的注意力计算

2,具体算法

1,自注意力中, Q K V QKV QKV分别由输入 x x x和三个随机矩阵作点积得到,这三个随机矩阵是网络的参数之一,会在训练中不断调整。

2,获取 Q K V QKV QKV矩阵后,使用注意力公式计算得到注意力 S S S,以animal为例,注意力矩阵 S S S经过softmax归一化操作后可能是[0.88,0.02,0.05,0.05,0]

3,此时与整个序列作点积,该操作会获得一个向量并冲淡与该词关联性不强的其他单词。

4,将第三步获得的序列相加就是最终得到的注意力结果。

举一个具体例子:

有三个输入分别为: i n p u t 1 = [ 1 , 0 , 1 ] i n p u t 2 = [ 1 , 1 , 0 ] i n p u t 3 = [ 0 , 0 , 1 ] input1=[1,0,1] input2=[1,1,0] input3=[0,0,1] input1=[1,0,1]input2=[1,1,0]input3=[0,0,1],组合形成的输入为 i n p u t = [ 1 0 1 1 1 0 0 0 1 ] input=\begin{bmatrix} 1 & 0 & 1\\ 1 & 1 & 0\\ 0 & 0 &1 \end{bmatrix} input= 110010101 随机初始化的参数矩阵假设为
W Q = [ 1 0 3 2 1 0 0 0 1 ] W K = [ 1 1 0 2 1 1 1 0 1 ] W V = [ 1 0 0 0 1 1 1 1 0 ] W^Q=\begin{bmatrix} 1 & 0 & 3\\ 2 & 1 & 0\\ 0 & 0 &1 \end{bmatrix} W^K=\begin{bmatrix} 1 & 1&0 \\ 2& 1& 1\\ 1 & 0&1 \end{bmatrix} W^V=\begin{bmatrix} 1& 0 & 0\\ 0& 1 &1 \\ 1& 1&0 \end{bmatrix} WQ= 120010301 WK= 121110011 WV= 101011010

计算得到的 Q , K , V Q,K,V Q,K,V分别为:
Q = [ 1 0 4 3 1 3 0 0 1 ] K = [ 2 1 1 3 2 1 1 0 1 ] V = [ 2 1 0 1 1 1 1 1 0 ] Q=\begin{bmatrix} 1 & 0 & 4\\ 3 & 1 & 3\\ 0 & 0 &1 \end{bmatrix} K=\begin{bmatrix} 2 & 1 & 1\\ 3 & 2 & 1\\ 1 & 0 &1 \end{bmatrix} V=\begin{bmatrix} 2 & 1 & 0\\ 1 & 1 & 1\\ 1 & 1 &0 \end{bmatrix} Q= 130010431 K= 231120111 V= 211111010

使用注意力公式 Q K T V QK^TV QKTV可得所有输入的自注意力结果,为了简化计算,只使用 i n p u t 1 input1 input1的查询 q 1 q_1 q1作为输入进行计算,过程如下
q 1 × K T = [ 1 , 0 , 4 ] × [ 2 3 1 1 2 0 1 0 1 ] = [ 6 , 3 , 5 ] q_1\times K^T=[1, 0, 4]\times\begin{bmatrix} 2& 3&1 \\ 1& 2&0 \\ 1& 0 &1 \end{bmatrix}=[6, 3 ,5] q1×KT=[1,0,4]× 211320101 =[6,3,5]

将该向量 [ 6 , 3 , 5 ] [6, 3, 5] [6,3,5]softmax处理后再与V点积运算并相加求和即获得 i n p u t 1 input1 input1的自注意力结果,也就是其更新后的自身表示。

自注意力计算过程示例图如下:

通过对自身所在序列进行注意力计算有什么作用 呢?

背景中我们提到,注意力机制的出现是为了弥补EncoderDecoder之间用于联系的定长向量过于脆弱,在长程输入下的失效问题。

我的理解是,自注意力利用注意力机制使每个输入都能获得自己与输入整体中其他元素的关联,使单个内容与上下文的联系更加紧,单独元素也携带上下文信息。

多头注意力Multi-Head Attention

自注意力模式下,所有输入都只关注序列中其他位置的向量与自身的关系,也就是注意力都在自身 ,对整个序列信息的关注就可能相对不足,论文作者提出了多头注意力机制解决这一问题,即将学习到不同线性投影的查询、键和值,线性投影到 dk、dk 和 dv 维度是有益的。多头注意力允许模型共同关注来自不同位置的不同表示子空间的信息,缓和单个注意力头的波动

其实就是作者发现组合多个自注意力结果的效果更好 ,通过 C o n c a t Concat Concat组合器将多个缩放点积注意力组合起来生成效果,修改后的数学表示为:
h e a d i = A t t e n t i o n ( Q W i Q , K W i K , V W i K ) head_i=Attention(QW_i^Q, KW^K_i, VW_i^K ) headi=Attention(QWiQ,KWiK,VWiK)
M u l t i H e a d ( Q , K , V ) = C o n c a t ( h e a d 1 , . . . , h e a d i ) W O MultiHead(Q, K, V )=Concat(head_1, ... , head_i)W^O MultiHead(Q,K,V)=Concat(head1,...,headi)WO

其中 d m o d e l d_{model} dmodel为输出长度,即每个输入会映射为 d m o d e l d_{model} dmodel个输出,默认设置为512, n n n个输入的维度为 n × d m o d e l n\times d_{model} n×dmodel。
W Q , W K W^Q, W^K WQ,WK形状为 d m o d e l × d k d_{model}\times d_k dmodel×dk, W V W^V WV形状为 d m o d e l × d v d_{model}\times d_v dmodel×dv, W O W^O WO形状为 h d v × d m o d e l hd_{v}\times d_{model} hdv×dmodel。

通常注意力头个数 h h h选择为8,维度 d k = d v = d m o d e l / h = 64 d_k=d_v=d_{model}/h=64 dk=dv=dmodel/h=64, h e a d i head_i headi的维度为 n × d k × d k × n × n × d v = n × d v n\times d_{k}\times d_k \times n\times n\times d_v=n\times d_v n×dk×dk×n×n×dv=n×dv,最后得到的 M u l t i H e a d MultiHead MultiHead维度为 n × d m o d e l n\times d_{model} n×dmodel。

而如果不适用多头缩小 h h h倍,单头计算维度为 n × d m o d e l × d m o d e l × d m o d e l = n × d m o d e l n\times d_{model} \times d_{model}\times d_{model}=n\times d_{model} n×dmodel×dmodel×dmodel=n×dmodel,可见多头将维度缩小为原来的 1 h \frac{1}{h} h1,但组合了 h h h个结果,所以总计算成本与全维的单头部注意力相似。

多头注意力计算组合如下图:

该过程可同时训练多组 W Q , W K , W V W^Q, W^K, W^V WQ,WK,WV,提高关联性的同时增加了自注意力表示的丰富度

Transformer模型

了解了注意力机制,我们回过头来学习Transformer的整体架构,Transformer 遵循这种整体架构,编码器和解码器都使用堆叠式自注意力层和逐点全连接层,分别如图的左半部分和右半部分所示

主干结构

输入输出的处理我们暂且搁置,先只看主干结构:

图中橙色部分的Multi-Head Attention我们已经了解了,文中提到编码器解码器分别由 N = 6 N=6 N=6个相同层组成,主干结构的大致流程为:

输入 i n p u t s inputs inputs经过编码器处理进入解码器,上一轮的输出 O u t p u t s Outputs Outputs直接进入解码器,经过单独一层处理后与编码器输入一同处理生成新的输出。

但对模型的主干结构还有三个疑问:

1,Add&Norm是做什么的?

2,Feed Forward的功能是什么?

3,右图下方的多头注意力为什么加了Masked?

原文中提到:

编码器部分第一个是多头自注意力机制,第二个是简单的、位置完全连接的前馈网络。我们在两个子层中的每一个周围采用残差连接,然后进行层归一化

而解码器部分除了每个编码器层中的两个子层之外,解码器还插入了第三个子层,该子层对编码器堆栈的输出执行多头注意。我们还修改了解码器堆栈中的 self-attention 子层,以防止 positions 关注后续位置。这种掩码,再加上输出嵌入向量偏移一个位置的事实,确保对位置 i 的预测只能依赖于小于 i 的位置的已知输出

也就是说:
Add&Norm是残差连接和归一化;
Feed Forward是完全连接的前馈网络;
Masked是为了保证输出不受预测影响。

下面依次对这些知识进行补充介绍。

残差连接add&Norm

本小节参考ResNet核心思想

残差连接的基础是跳跃连接(skip connection),指的是越过某些中间层,将数据直接添加到中间节点上。

该操作使得信息可以更自由地流动,并且保留了原始输入数据中的细节和语义信息。 使信息更容易传播到后面的层次,避免了信息丢失。

比如网络层层递进的结构中,尤其卷积操作,输入细节可能不断丢失,随着层数的深入,学习效果反而可能变差。

此时添加一个跳跃连接,将输入与最后一层拼接起来,可以保留输入的更多原始语义和信息。

跳跃连接示意图如下:

残差网络ResNet则是专门用于解决网络层数过深导致的梯度消失和训练困难问题,其核心思想是引入残差块构建网络 ,并使用跳跃连接将输入直接添加到输出层上

该部分并非Transformer核心内容,有关原理讲解可见ResNet模型详解

对该模型作大致介绍,输入 x x x,经过卷积层、批归一化(BN)、激活函数(ReLU)等一通操作构成 F ( x ) F(x) F(x),输出为 H ( x ) = F ( x ) + x H(x)=F(x)+x H(x)=F(x)+x通过跳跃连接将输入与之相加,最后归一化操作。

本文使用的方法与之类似,子层的输出是 L a y e r N o r m ( x + S u b l a y e r ( x ) ) LayerNorm(x + Sublayer(x)) LayerNorm(x+Sublayer(x)),其中 S u b l a y e r ( x ) Sublayer(x) Sublayer(x)是由子层本身实现的函数, L a y e r N o r m LayerNorm LayerNorm是归一化方法。

残差连接要求 x x x与 F ( x ) + x F(x)+x F(x)+x等长,所以在Transformer中模型子层和嵌入层的输入都是 d m o d e l = 512 d_{model}=512 dmodel=512。

前馈网络Feed Forward

就是一个网络,其中包括两个线性变换,中间有一个 ReLU 激活,执行公式为:
F N N ( X ) = m a x ( 0 , x W 1 + b 1 ) W 2 + b 2 FNN(X)=max(0,xW_1+b_1)W_2+b_2 FNN(X)=max(0,xW1+b1)W2+b2

其中隐藏层维数 d f f = 2048 d_{ff}=2048 dff=2048

因为注意力机制本质是线性的矩阵变换,该网络 F N N FNN FNN通过激活函数引入非线性特征,使模型能拟合复杂函数关系;同时将 d m o d e l = 512 d_{model}=512 dmodel=512维上升到 d f f = 2048 d_{ff}=2048 dff=2048维,扩展特征空间,方便更深层次提取特征。

右移操作shifted right

在讲掩码多头注意力之前不得不转到主干结构之外,解码器的另一个输入来自上一个解码器的输出,但该 o u t p u t s outputs outputs使用了一次shifted right操作,这步操作有什么含义?

首先看一下Transformer对注意力机制的使用:

1,在编码器解码器层中,查询 Q Q Q来自前一个解码器,键 K K K和值 V V V来自编码器。编码器与输入 i n p u t input input一一对应。

2,编码器使用自注意力。该层注意力的 Q , K , V Q, K, V Q,K,V都来自前一层编码器。

3,解码器使用自注意力,该机制使整个序列对当前生成的元素都可见。

这种机制有两个问题

1,当编码器接受第0个字符时,上一层的输出该如何设置使编码器解码器处理对齐?

2,Transformer并行训练时,序列 t 0 , . . . , t k t_0, ..., t_k t0,...,tk都进入解码器,但此时才输出到 t 2 t_2 t2,如何避免后续序列对输出的干扰。

shiftedright右移操作解决第一个对齐问题。

该操作将输出序列整体右移一位,解码器训练数据为 1 , 2 , 3 1,2,3 1,2,3,整体右移变为 < s o s > , 1 , 2 , 3 <sos>,1,2,3 <sos>,1,2,3,此时编码器处理第0个数据, < s o s > <sos> <sos>就可以作为上一个解码器的结果输出给当前解码器,实现对齐

掩码多头注意力Masked Multi-Head Attention

该机制解决前面提到的第二个问题,输出序列当前步 i i i预测输出应该只根据该步以前的结果,即 i − 1 i-1 i−1实现,但用于解码器训练的输出序列全部输入解码器中,为防止后续元素对解码过程的干扰,应该把后续元素给"盖住",类似如下过程:

掩码注意力的mask就是实现"盖"的功能,论文中使用将注意力 s o f t m a x softmax softmax的输入设置为 − ∞ -\infty −∞实现,该设置导致权重为0,被遮住的输出就全为0。

训练并行,推理串行

首先声明一个结论,Transformer是训练并行,推理串行的结构

前面提到的第二个问题我反反复复看了好几遍,假如有输入序列 < s o s > , 1 , 2 , 3 <sos>, 1, 2, 3 <sos>,1,2,3要进入Transformer,编码器输出 K i , V i K_i, V_i Ki,Vi给解码器,解码器接收上一步解码器输出 Q i − 1 Q_{i-1} Qi−1与本次编码输出 K i , V i K_i, V_i Ki,Vi得出本次输出 Q i Q_i Qi,这样一个串行执行的结构怎么会涉及避免后续元素的干扰问题?

我忽略了一个关键问题,Transformer就是为了改进RNN串行训练速度慢才诞生的,所以其训练过程一定是并行 的。

对于这个问题很多资料一带而过,本节单独对该内容进行详细说明。

传统RNN网络的训练过程应该是输入序列 X X X输入编码器,生成 K , V K, V K,V给解码器,解码器从 < s o s > <sos> <sos>开始不断推理生成预测 P P P,最后与正确输出 P P P进行比较,使用损失函数更新编码器解码器参数,大致流程如下:

该方案的缺陷是序列P要逐步 生成并代替 < s o s > <sos> <sos>,这种串行的训练模式效率十分低下。

传统RNN采用该方案的原因是当前生成的元素无法有效关联其他元素,必须逐步生成,将已有元素输入下一步预测节点。

而Transformer使用注意力机制,生成的每个元素都清楚知道自己和其他元素的关系,所以对任意元素的预测都可以独立进行。注意力允许Transformer同步生成所有序列 ,即同时生成 t 0 , t 1 , . . . , t n t_0, t_1, ..., t_n t0,t1,...,tn。

取消递推训练后的解码器上一步输入 Q Q Q又由谁决定呢?Transformer使用一种名为"教师强迫"Teacher forcing的训练模式,即每个节点都将正确的输出作为已知的序列进行预测,使用这种模式可以实现所有节点无需等待上一步预测,独立进行训练。

但正确的输出过于完整,节点 i i i应该只基于 0 − i 1 0-i_1 0−i1个序列进行预测,所以作者采用了掩码注意力机制,将i及以后的输出对当前节点隐藏

假设有一训练集为x=我想吃汉堡,p=I want to eat a hamburger,Transformer训练过程如下:

该过程比较复杂,再次简要总结:

1,注意力建立序列关联性,使训练无需等待前一次结果独立进行;

2,Teacher forcing机制让解码器将正确输出作为上一次结果,实现并行训练;

3,掩码注意力机制为当前节点屏蔽后续正确输出,使训练依据局限在当前序列。

如果还不能理解可以看transformer如何实现并行化,该文章角度中,编码器并行由注意力机制实现,解码器并行由Teacher forcing和掩码注意力共同作用实现。

但推理过程仍然是串行的,解码器不断迭代生成序列用于下一次输出。

嵌入层Embedding

主干网络之后我们来看模型对输入输出的处理:

和其他序列转换模型一样,Transformers也使用词嵌入处理输入输出,将其转换为维度 d m o d e l d_{model} dmodel的向量。

词嵌入就是将词转换为向量的方法,如猫=>[0,1,1] 狗=>[0,0,1],转换后的形式更容易被计算机识别并计算,有关具体方法可见从0开始词嵌入

随后使用通常的线性变换和softmax将解码器输出转换为预测的下一个标记概率。

文中提到:两个嵌入层和线性变换层之间共享相同的权重矩阵,并在嵌入层中将权重乘 d m o d e l \sqrt{d_{model}} dmodel 。

位置编码Positional Encoding

Transformer现在只剩下一个位置没有解读了,就是输入后的位置编码:

因为Transformer中不含递归和卷积,注意力机制为了并行计算也只具有全局查询功能,因此为了让模型利用序列的顺序,必须注入一些关于序列中标记的相对或绝对位置的信息。

为此,作者设计了一种"位置编码",将序列顺序信息直接与编码器和解码器输入的 E m b e d d i n g Embedding Embedding相加,保证位置信息参与模型的后续运算,所以真正的输入 i n p u t = e m b e d d i n g + p o s i t i o n a l e n c o d i n g input=embedding+positional encoding input=embedding+positionalencoding。

位置编码与词嵌入具有相同维度 d m o d e l d_{model} dmodel,使用 p o s pos pos表示位置, i i i表示维度,

作者使用了不同频率的正弦和余弦函数作为位置编码:
P E ( p o s , 2 i ) = s i n ( p o s / 10000 2 i / d m o d e l ) PE(pos,2i)=sin(pos/10000^{2i/d_{model}}) PE(pos,2i)=sin(pos/100002i/dmodel)
P E ( p o s , 2 i + 1 ) = c o s ( p o s / 10000 2 i / d m o d e l ) PE(pos,2i+1)=cos(pos/10000^{2i/d_{model}}) PE(pos,2i+1)=cos(pos/100002i/dmodel)

比如输入dog eat food,每个词对应的 p o s = 0 , 1 , 2 pos=0,1,2 pos=0,1,2,假设转换的 E m b e d d i n g Embedding Embedding维度是20,计算过程示例如下:

在该公式中,当 i = 0 i=0 i=0即低维情景下,频率 1 10000 2 i / d m o d e l = 1 \frac{1}{10000^{2i/d_{model}}}=1 100002i/dmodel1=1,当 i = d m o d e l i=d_{model} i=dmodel即高维场景下,频率等于 1 10000 1 2 ≈ 0.01 \frac{1}{10000^{\frac{1}{2}}}\approx 0.01 10000211≈0.01。

也就是低维频率大,高维频率小,这进一步导致低维位置编码变化大,高维位置编码变化小 ,相加得到的结果输入网络后会使网络通过低维位置编码关注局部差异,又通过高维建立序列整体联系

这种设计同时可保证编码唯一,并且不依赖最大序列长度,支持任意长度的输入。

同时作者还尝试了可学习的位置编码函数,发现二者结果几乎相同,最终选择了该版本也是因为其支持任意长度的输入序列,可学习的位置编码只能处理训练时的序列长度。

有关位置编码更详细的介绍可参考详解自注意力机制中的位置编码

实验结果

作者对英语-德语,英语-法语两项任务进行了训练,使用8张P100显卡,每个训练步骤需要0.4s,基本模型用12小时就可以训练结束,大模型3天半也能训练完成。

Transformer使用更少的训练成本实现了最好的训练效果。

另外进行了消融实验,即分别修改实验条件和参数,确定对结果影响更大的因素。

实验A表明,头部数量 h h h和键的维度 d k d_k dk比例要适中,太大太小效果都不好,而且另外表明多头注意力要优于单头。

实验B表明,键 d k d_k dk减小会损失性能,作者认为相关性的建立比较复杂,如果能有比点积更好的方法可能会带来性能的提升。

实验CD表明,大模型效果更好,并且使用dropout是有必要的。

实验E则是证明可学习的嵌入位置编码与文章使用的结果相近。

总结

针对循环神经网络RNN串行训练效率低的问题,Transformer提出了一种完全基于注意力机制的模型结构,更适合长序列任务。

对该文章解决问题的核心方法总结如下:

自注意力关联输入序列。在该结构中,以往结合本次输入和上步预测的信息关联手段被自注意力计算取代,自注意力计算下每个输入元素都能获得自己与整个输入序列的关联性。

Teacher Forcing提供并行训练数据 。并行时仍采用迭代训练方法,训练数据采用Teacher Forcing方法,将正确输出作为上一步预测直接输入到解码器中,与自注意力一起作为并行训练的基础。

掩码注意力屏蔽后续输出干扰。当下节点的预测结果应该只根据已有数据,但Teacher Forcing将正确输出全部输入到解码器,故在解码器第一层设置掩码注意力,屏蔽当前节点以后的数据,保证预测只来自已有信息。

位置编码提供位置信息。使用自注意力只能使序列获得整体关联信息,而无法使模型利用序列顺序,将位置编码与词嵌入相加可使模型从顺序角度对序列进行关联。

总的来看,Transformer模型中包含更多信息,又摒弃了RNN串行训练的方式,提高训练效率的同时也提高了训练质量,应用领域也由自然语言处理发展到计算机视觉,有如此大的名气确实是实至名归。

相关推荐
__如果3 小时前
深度学习复习笔记
人工智能·笔记·深度学习
zdy12635746886 小时前
python37天打卡
人工智能·深度学习·算法
chicpopoo6 小时前
Python打卡DAY40
人工智能·python·机器学习
逼子格6 小时前
长短期记忆网络:从理论到创新应用的深度剖析
深度学习·神经网络·lstm·长短期记忆网络
美狐美颜sdk7 小时前
从图像处理到深度学习:直播美颜SDK的人脸美型算法详解
图像处理·深度学习·计算机视觉·美颜sdk·美颜api
Joker 0077 小时前
Ubuntu 安装 FSL 及多模态脑MRI的去颅骨处理(含 HD-BET 深度学习方法)
linux·深度学习·ubuntu
小饼干超人8 小时前
手写multi-head Self-Attention,各个算子详细注释版
人工智能·深度学习·机器学习
攻城狮7号9 小时前
谷歌Gemma模型实现智能看病、翻译手语、与海豚沟通
人工智能·深度学习·medgemma·signgemma·dolphingemma
学术交流9 小时前
ICDMC 2025:创新媒体模式,迎接数字时代的挑战
论文阅读·论文笔记·媒体
我不是小upper9 小时前
详细到用手撕transformer下半部分
算法·机器学习·transformer