文字长度: ★★★★★
阅读难度: ★★☆☆☆
原创程度: ★★★★☆
Transformer是2017年的一篇论文《Attention is All You Need》提出的一种模型架构,这篇论文里只针对机器翻译这一种场景做了实验,全面击败了当时的SOTA,并且由于encoder端是并行计算的,训练的时间被大大缩短了。
它开创性的思想,颠覆了以往序列建模和RNN划等号的思路,现在被广泛应用于NLP的各个领域。目前在NLP各业务全面开花的语言模型如GPT, BERT等,都是基于Transformer模型。因此弄清楚Transformer模型内部的每一个细节就显得尤为重要。
鉴于写Transformer的中英文各类文章非常之多,一些重复的、浅显的东西在本文里都不再赘述。在本文中,我会尽可能地去找一些很核心也很细节的点去剖析,并且将细节和整体的作用联系起来解释。
本文尽量做到深入浅出,力求覆盖我自己学习时的每一个困惑,做到“知其然,且知其所以然”。我相信通过我抽丝剥茧的分析,大家会对Transformer每个部分的作用有一个更加深入的认识,从而对这个模型架构整体的认知上升到一个新的台阶,并且能够深刻理解Transformer及其延伸工作的动机。
0. Transformer整体架构
这里就不啰嗦encoder, decoder各自的含义以及模块了,直戳细节。以下将会重点解答的问题有:
想要深度理解Attention机制,就需要了解一下它产生的背景、在哪类问题下产生,以及最初是为了解决什么问题而产生。
首先回顾一下机器翻译领域的模型演进历史:
机器翻译是从RNN开始跨入神经网络机器翻译时代的,几个比较重要的阶段分别是: Simple RNN, Contextualize RNN, Contextualized RNN with attention, Transformer(2017),下面来一一介绍。
这种模型有2个主要的问题:
但是这样依然有一个问题: context对于每个timestep都是静态的(encoder端的final hidden states,或者是所有timestep的output的平均值)。但是每个decoder端的token在解码时用到的context真的应该是一样的吗?在这样的背景下,Attention就应运而生了:
在每个timestep输入到decoder RNN结构中之前,会用当前的输入token的vector与encoder output中的每一个position的vector作一个"attention"操作,这个"attention"操作的目的就是计算当前token与每个position之间的"相关度",从而决定每个position的vector在最终该timestep的context中占的比重有多少。最终的context即encoder output每个位置vector表达的加权平均。
context的计算公式我们来介绍一下attention的具体计算方式。attention可以有很多种计算方式: 加性attention、点积attention,还有带参数的计算方式。着重介绍一下点积attention的公式:
如上图所示,
一个完整的attention层涉及到的参数有:
Query和Key作用得到的attention权值作用到Value上。因此它们之间的关系是:
在经典的Transformer结构中,我们记线性映射之前的Query, Key, Value为q, k, v,映射之后为Q, K, V。那么:
而每一层线性映射参数矩阵都是独立的,所以经过映射后的Q, K, V各不相同,模型参数优化的目标在于将q, k, v被映射到新的高维空间,使得每层的Q, K, V在不同抽象层面上捕获到q, k, v之间的关系。一般来说,底层layer捕获到的更多是lexical-level的关系,而高层layer捕获到的更多是semantic-level的关系。
下面这段我会以机器翻译为例,用通俗的语言阐释一下attention的作用,以及query, key, value的含义。
Transformer模型Encoder, Decoder的细节图(省去了FFN部分)query对应的是需要被表达的序列(称为序列A),key和value对应的是用来表达A的序列(称为序列B)。其中key和query是在同一高维空间中的(否则无法用来计算相似程度),value不必在同一高维空间中,最终生成的output和value在同一高维空间中。上面这段巨绕的话用一句更绕的话来描述一下就是:
序列A和序列B在高维空间中的高维表达的每个位置分别和计算相似度,产生的权重作用于序列B在高维空间中的高维表达,获得序列A在高维空间中的高维表达
Encoder部分中只存在self-attention,而Decoder部分中存在self-attention和cross-attention
【self-attention】encoder中的self-attention的query, key, value都对应了源端序列(即A和B是同一序列),decoder中的self-attention的query, key, value都对应了目标端序列。
【cross-attention】decoder中的cross-attention的query对应了目标端序列,key, value对应了源端序列(每一层中的cross-attention用的都是encoder的最终输出)
Transformer模型属于自回归模型(p.s. 非自回归的翻译模型我会专门写一篇文章来介绍),也就是说后面的token的推断是基于前面的token的。Decoder端的Mask的功能是为了保证训练阶段和推理阶段的一致性。
论文原文中关于这一点的段落如下:
We also modify the self-attention sub-layer in the decoder stack to prevent from attending to subsequent positions. This masking, combined with the fact that the output embeddings are offset by one position, ensures that the predictions for position i can depend only on the known outputs at positions less than i.
在推理阶段,token是按照从左往右的顺序推理的。也就是说,在推理timestep=T的token时,decoder只能“看到”timestep < T的 T-1 个Token, 不能和timestep大于它自身的token做attention(因为根本还不知道后面的token是什么)。为了保证训练时和推理时的一致性,所以,训练时要同样防止token与它之后的token去做attention。
Attention是将query和key映射到同一高维空间中去计算相似度,而对应的multi-head attention把query和key映射到高维空间
为什么要做multi-head attention?论文原文里是这么说的:
Multi-head attention allows the model to jointly attend to information from different representation subspaces at different positions. With a single attention head, averaging inhibits this.
也就是说,这样可以在不改变参数量的情况下增强每一层attention的表现力。
Multi-head Attention示意图Multi-head Attention的本质是,在参数总量保持不变的情况下,将同样的query, key, value映射到原来的高维空间的不同子空间中进行attention的计算,在最后一步再合并不同子空间中的attention信息。这样降低了计算每个head的attention时每个向量的维度,在某种意义上防止了过拟合;由于Attention在不同子空间中有不同的分布,Multi-head Attention实际上是寻找了序列之间不同角度的关联关系,并在最后concat这一步骤中,将不同子空间中捕获到的关联关系再综合起来。
从上图可以看出,
每一层经过attention之后,还会有一个FFN,这个FFN的作用就是空间变换。FFN包含了2层linear transformation层,中间的激活函数是ReLu。
曾经我在这里有一个百思不得其解的问题:attention层的output最后会和
其实,FFN的加入引入了非线性(ReLu激活函数),变换了attention output的空间, 从而增加了模型的表现能力。把FFN去掉模型也是可以用的,但是效果差了很多。
位置编码层只在encoder端和decoder端的embedding之后,第一个block之前出现,它非常重要,没有这部分,Transformer模型就无法用。位置编码是Transformer框架中特有的组成部分,补充了Attention机制本身不能捕捉位置信息的缺陷。
position encodingPositional Embedding的成分直接叠加于Embedding之上,使得每个token的位置信息和它的语义信息(embedding)充分融合,并被传递到后续所有经过复杂变换的序列表达中去。
优势1
不得不说,使用Positional Encoding作为每个token位置的唯一表示,这一思路很NB,为什么呢?
* 对inference阶段而言
* 对train阶段而言(针对learned postional encoding的情况)
优势2
论文中使用的Positional Encoding(PE)是正余弦函数,位置(pos)越小,波长越长,每一个位置对应的PE都是唯一的。同时作者也提到,之所以选用正余弦函数作为PE,是因为这可以使得模型学习到token之间的相对位置关系:因为对于任意的偏移量k,
上面两个公式可以由
p.s. 后续有一个工作在attention中使用了“相对位置表示” (Self-Attention with Relative Position Representations) ,有兴趣可以看看。
在每个block中,最后出现的是Layer Normalization。Layer Normalization是一个通用的技术,其本质是规范优化空间,加速收敛。
当我们使用梯度下降法做优化时,随着网络深度的增加,数据的分布会不断发生变化,假设feature只有二维,那么用示意图来表示一下就是:
数据的分布发生变化,左图比较规范,右图变得不规范为了保证数据特征分布的稳定性(如左图),我们加入Layer Normalization,这样可以加速模型的优化速度。
本文只是重点介绍了一下Transformer,当前基于Transformer的各类后续研究正在自然语言处理的各大领域里大放异彩,本人还有一些其他的文章与Transformer有关:
潘小小:【论文串讲】从GPT和BERT到XLNetzhuanlan.zhihu.com 潘小小:【论文串讲】从BERT和XLNet到MPNet 潘小小:【论文串讲】从GPT和BERT到XLNetzhuanlan.zhihu.com 潘小小:【论文串讲】从BERT和XLNet到MPNetzhuanlan.zhihu.com本文已独家授权公众号浅梦的学习笔记发布在微信公众平台。
终于写完啦~撒花
大家好,我叫潘小小(不是真名),是字节跳动AI-lab的一枚算法攻城狮~我的文章中绝大部分的图文都是原创,行文风格比较偏我个人学习和思考的习惯。欢迎大家关注我的技术专栏【小小的机器世界】