论文:Attention Is All You Need
作者:Ashish Vaswani, Noam Shazeer, Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N. Gomez, Lukasz Kaiser, Illia Polosukhin
机构:Google Brain
链接:https://arxiv.org/abs/1706.03762
代码:https://github.com/tensorflow/tensor2tensor
文章目录
- 1、算法概述
- 2、Transformer细节
- 2.1 Attention
- 2.2 Position-wise Feed-Forward Networks
- 2.3 Positional Encoding
- 2.4 Seq2seq with Attention
- 3、训练
- 4、实验
1、算法概述
这篇论文是transformer的开山之作,最早transformer是用于机器翻译的,也就是NLP领域,但是随着2020年DETR和ViT的出现,它在视觉领域的应用也大火了起来,为了后续解读transformer在视觉领域的其他应用算法,有必要解读一下transformer的理论基础。
作者在论文摘要中指出,之前的处理序列信号的任务例如机器翻译都是基于复杂的循环神经网络(RNN)、长短时记忆(LSTM)或者卷积神经网络(CNN)组成的编码器和解码器,为了使其表现好点,在编码的时候还可以结合注意力机制。这篇论文,作者完全摒弃了RNN和CNN结构,只基于注意力机制,相比于RNN和LSTM的串行处理结构,作者提出的transformer结构可以实现并行处理,大大减小了处理序列的时间。如下图是传统用RNN及CNN处理序列的示意图(图片来自台湾国立大学李宏毅老师的transformer课件ppt,侵删)
由上图可见,RNN和LSTM这类循环神经网络是串行处理,输出一串序列,耗时长,CNN虽然可以并行处理,但它关联到序列之间的关系范围有限,需要通过不断加深网络层数来扩大范围,使其能处理更长的序列。
而自注意力是一种将单个序列的不同位置联系起来以计算该序列的表示的注意机制。在处理序列问题上,它可以完全替代RNN及CNN的角色,如下图:
2、Transformer细节
Transformer整体架构如上图所示,它使用堆叠的自注意力层和point-wise层,由编码器和解码器两部分组成。论文中编码器和解码器中的N均设置为6。
编码器中一个block由两部分组成,第一个是多头自注意机制,第二个是一个简单的、位置明智(point-wise)的全连接前馈网络。其中的Add & Norm操作为LayerNorm(x + Sublayer(x)),这里的Sublayer(x)及代表Multi-Head Attention或Feed Forward模块。
解码器中一个block则由三部分组成,除了编码器中的Multi-Head Attention和Feed Forward模块,它还包含了Masked Multi-Head Attention模块,它负责对编码器堆栈的输出执行多头注意。为了确保位置i的预测只能依赖于位置小于i的已知输出。作者修改了解码器堆栈中的自注意子层,以防止关注后续位置。
可以看出本文的创新点在于Multi-Head Attention部分,下面详细阐述这个模块的计算方式。
2.1 Attention
注意函数可以描述为将查询(query)和一组键值对(key-value pairs)映射到输出,其中查询、键、值和输出都是向量。输出以值(value)的加权和形式计算得到,其中分配给每个值(value)的权重由查询与相应键的匹配度函数计算得到。
-
Scaled Dot-Product Attention
如下图是Q,K,V的操作示意图
用公式可表示如下:
下面以李宏毅老师的ppt来展示对于序列 (x1,x2,x3,x4) 如何一步一步计算self-attention的。
首先xi经过矩阵W变换得到ai,通过ai得到对应的qi、ki及vi。如下图:
对于q1,它和每一个ki进行点积(dot product)计算并做scale操作得到a1,i,如下图:
对a1,i做softmax操作,得到a^1,i,这里就得到计算第一个输出值的b1所需要的各个vi的权重了,如下图:
第一个输出值b1可由权重a^1,i与vi加权求和得到,如下图:
同理,第二个节点b2也可以计算得到:
主要是b1,b2,b3,b4可以利用GPU进行并行计算,如下图:
-
Multi-Head Attention
多头注意允许模型在不同位置共同注意来自不同表示子空间的信息。对于单一注意力头,平均会抑制这一点,如下图所示:
用公式可以表示为:
论文中h取8,dk=dv=dmodel/h=64。
下面还是以李宏毅老师的ppt图片来展示两个注意力头的计算方式,非常直观。
图中两个注意力头,红色椭圆框住的是第一个头,绿色椭圆框住的是第二个头,对于第一个头输出的bi,1只需对第一个头的q,k,v进行相关计算即可。第二个头的输出结果同理,如下图:
两个头最终的输出结果bi由各个头的输出结果进行concat然后通过矩阵Wo相乘得到。如下图:
多个注意力头对语句关注点可视化如下,可见每个注意力头关注点都不一样。
2.2 Position-wise Feed-Forward Networks
除了注意子层之外,编码器和解码器中的每一层都包含一个全连接的前馈网络,该网络分别相同地应用于每个位置。它包括两个线性连接,中间有一个ReLU激活。用公式表示为:
2.3 Positional Encoding
由于作者设计的模型不包含递归和卷积,为了使模型有效利用序列的顺序,需向模型引入一些关于序列中标记的相对或绝对位置的信息。为此,作者在编码器和解码器底部的输入嵌入向量(embedding)中添加了“位置编码”。位置编码与嵌入向量具有相同的维数,因此可以对两者进行求和。
位置编码有很多选择,有通过学习获得也有直接设置的,本论文作者选择了后者,采用的位置编码公式为:
由于公式的三角函数特性,对于固定偏移位置k,PEpos+k都可以被PEpos线性表示出来:
s i n ( a + b ) = s i n a c o s b + c o s a s i n b sin(a+b)=sina cosb+cosa sinb sin(a+b)=sinacosb+cosasinb
c o s ( a + b ) = c o s a c o s b − s i n a s i n b cos(a+b)=cosa cosb-sina sinb cos(a+b)=cosacosb−sinasinb
而李宏毅老师的ppt中位置编码是通过学习获得的,我们可以直观感受到位置编码如何与单词embedding相加得到的,如下图,李宏毅老师中定义每个单词位置pi为one-hot编码,然后通过矩阵变换Wp得到位置编码ei,这里ei的维度和单词的embedding向量ai维度需保持一致,最后相加得到最终的单词嵌入向量进入后续的自注意力模块。
2.4 Seq2seq with Attention
接下来看看对于seq2seq任务中,如何应用transformer中的自注意力机制的,把Encoder-Decoder中的RNN用self-attention取代掉,如下图:
3、训练
训练采用WMT 2014 英语-德语数据集,它由450万个句子对,具有大约37000个标记的源-目标词汇表。而且,作者还采用了WMT 2014英语-法语数据集,它的数据量更大,包含3600百万个句子对,包含大约32000个单词,25000个源-目标词汇对应表标记。
作者用了8个NVIDIA P100 GPUs训练模型,对于base model,训练了10万个steps用了12小时,对于big model,训练了30万个steps用了3.5天。作者采用Adam优化器,warmup设置了4000个step并且采用线性变化到初始学习率,然后按步长平方根的倒数成比例递减。
对于模型正则化,作者采用了三种方式:Residual Dropout,每个sub-layer的输出应用dropout,还有在编码器和解码器中的单词embedding和位置编码之和处应用dropout,在base model中,drop概率设置为0.1;还有就是label smoothing,概率设置为0.1。
4、实验
机器翻译的实验结果如下:
参考:
[1] Vaswani, A., Shazeer, N., Parmar, N., Uszkoreit, J., Jones, L., Gomez, A.N., Kaiser, L., Polosukhin, I.: Attention is all you need. In: NeurIPS (2017)
[2]https://www.bilibili.com/video/av71295187/?spm_id_from=333.788.videocard.8&vd_source=dde073a03801571dd0b077e3e88ccfb7
[3] https://zhuanlan.zhihu.com/p/340149804
[4] https://zhuanlan.zhihu.com/p/308301901