论文笔记:Transformer-XL: Attentive Language Models Beyond a Fixed-Length Context

前言

论文链接:https://www.aclweb.org/anthology/P19-1285/
github:https://github.com/kimiyoung/transformer-xl

目前在NLP领域中,处理语言建模问题有两种最先进的架构:RNN和Transformer。RNN按照序列顺序逐个学习输入的单词或字符之间的关系,而Transformer则接收一整段序列,然后使用self-attention机制来学习它们之间的依赖关系。这两种架构目前来看都取得了令人瞩目的成就,但它们都局限在捕捉长期依赖性上。

Transformer-XL是对Transformer的改进或变种,主要是解决长序列的问题,其中XL表示extra long,在最近流行的XLNet中就是使用Transformer-XL作为基础模块。

为了解决这一问题,CMU联合Google Brain在2019年1月推出的一篇新论文《Transformer-XL:Attentive Language Models beyond a Fixed-Length Context》同时结合了RNN序列建模和Transformer自注意力机制的优点,在输入数据的每个段上使用Transformer的注意力模块,并使用循环机制来学习连续段之间的依赖关系。Transformer-XL在多种语言建模数据集(如单词级别的enwik8和字符级别的text8)上实现了目前的SoTA效果,且该模型在推理阶段速度更快,比之前最先进的利用Transformer进行语言建模的方法快300~1800倍。

参考:
https://zhuanlan.zhihu.com/p/84159401
https://blog.csdn.net/magical_bubble/article/details/89060213
https://www.lyrn.ai/2019/01/16/transformer-xl-sota-language-model

1. Vanilla Transformer

transformer作为一种特征提取器,在NLP中有广泛的应用。但是transformer需要对输入序列设置一个固定的长度,比如在BERT中,默认长度是512。如果文本序列长度短于固定长度,可以通过填充的方式来解决。如果序列长度超过固定长度,处理起来就比较麻烦。一种处理方式,就是将文本划分为多个segments。训练的时候,对每个segment单独处理,segments之间没有联系,如下图(a)所示。这存在两个问题:

  • 1)因为segments之间独立训练,所以不同的token之间,最长的依赖关系,就取决于segment的长度;
  • 2)出于效率的考虑,在划分segments的时候,不考虑句子的自然边界,而是根据固定的长度来划分序列,导致分割出来的segments在语义上是不完整的。

在这里插入图片描述
在预测的时候,会对固定长度的segment做计算,一般取最后一个位置的隐向量作为输出。为了充分利用上下文关系,在每做完一次预测之后,就对整个序列向右移动一个位置,再做一次计算,如上图(b)所示,这导致计算效率非常低。

2. Transformer-XL

Transformer-XL架构在vanilla Transformer的基础上引入了两点创新:循环机制(Recurrence Mechanism)相对位置编码(Relative Positional Encoding),以克服vanilla Transformer的缺点。与vanilla Transformer相比,Transformer-XL的另一个优势是它可以被用于单词级和字符级的语言建模。

2.1 循环机制 Segment-Level Recurrence

与vanilla Transformer的基本思路一样,Transformer-XL仍然是使用分段的方式进行建模,但其与vanilla Transformer的本质不同是在于引入了段与段之间的循环机制,使得当前段在建模的时候能够利用之前段的信息来实现长期依赖性。如下图所示:
在这里插入图片描述
在对当前segment进行处理的时候,缓存并利用上一个segment中所有layer的隐向量序列,而且上一个segment的所有隐向量序列只参与前向计算,不再进行反向传播,这就是所谓的segment-level Recurrence。

在训练阶段,处理后面的段时,每个隐藏层都会接收两个输入:

  1. 该段的前面隐藏层的输出,与vanilla Transformer相同(上图的灰色线)。
  2. 前面段的隐藏层的输出(上图的绿色线),可以使模型创建长期依赖关系。

这两个输入会被拼接,然后用于计算当前段的Key和Value矩阵。对于某个段的某一层的具体计算公式如下:
h ~ T + 1 n − 1 = [ S G ( h T n − 1 ) ∘ h T + 1 n − 1 ] (extended context) \widetilde{h}_{\mathcal{T}+1}^{n-1}=[SG(h_{\mathcal{T}}^{n-1})\circ h_{\mathcal{T}+1}^{n-1}]\tag{extended context} h T+1n1=[SG(hTn1)hT+1n1](extended context)
q T + 1 n , k T + 1 n , v T + 1 n = h T + 1 n − 1 W q T , h ~ T + 1 n − 1 W k T , h ~ T + 1 n − 1 W v T (query key,calue,vectors) q_{\mathcal{T+1}}^n,k_{\mathcal{T+1}}^n,v_{\mathcal{T+1}}^n=h_{\mathcal{T}+1}^{n-1}W_q^T,\widetilde{h}_{\mathcal{T}+1}^{n-1}W_k^T,\widetilde{h}_{\mathcal{T}+1}^{n-1}W_v^T \tag{query key,calue,vectors} qT+1n,kT+1n,vT+1n=hT+1n1WqT,h T+1n1WkT,h T+1n1WvT(query key,calue,vectors)
h T + 1 n = T r a n s f o r m e r − L a y e r ( q T + 1 n , k T + 1 n , v T + 1 n ) (self-attention + feed-forward) h_{\mathcal{T}+1}^n=Transformer-Layer(q_{\mathcal{T}+1}^n,k_{\mathcal{T}+1}^n,v_{\mathcal{T}+1}^n) \tag{self-attention + feed-forward} hT+1n=TransformerLayer(qT+1n,kT+1n,vT+1n)(self-attention + feed-forward)

其中, T \mathcal{T} T表示第几段, n n n表示第几层, h h h表示隐层的输出。 S G ( ∘ ) SG(\circ) SG()表示停止计算梯度, [ h u ∘ h v ] [hu \circ hv] [huhv]表示在长度维度上的两个隐层的拼接, W W W是模型参数。乍一看与Transformer中的计算公式很像,唯一关键的不同就在于Key和Value矩阵的计算上 k T + 1 n k_{\mathcal{T}+1}^n kT+1n v T + 1 n v_{\mathcal{T}+1}^n vT+1n,即它们基于的是扩展后的上下文隐层状态 h ~ T + 1 n − 1 \widetilde{h}_{\mathcal{T}+1}^{n-1} h T+1n1进行计算, h T n − 1 h_{\mathcal{T}}^{n-1} hTn1之前段的缓存。

原则上只要GPU内存允许,该方法可以利用前面更多段的信息,测试阶段也可以获得更长的依赖。

在测试阶段,与vanilla Transformer相比,其速度也会更快。在vanilla Transformer中,一次只能前进一个step,并且需要重新构建段,并全部从头开始计算;而在Transformer-XL中,每次可以前进一整个段,并利用之前段的数据来预测当前段的输出。

我们详细看一下如何操作。Transform本身是可以设置multi-heads,但是在后文中为了简化描述采用单个head。将两个连续的segments表示为 s T = [ x T , 1 , x T , 2 , . . . , x T , L ] s_{\mathcal{T}}=[x_{\mathcal{T},1},x_{\mathcal{T},2},...,x_{\mathcal{T},L}] sT=[xT,1,xT,2,...,xT,L] s T + 1 = [ x T + 1 , 1 , x T + 1 , 2 , . . . , x T + 1 , L ] s_{\mathcal{T}+1}=[x_{\mathcal{T}+1,1},x_{\mathcal{T}+1,2},...,x_{\mathcal{T}+1,L}] sT+1=[xT+1,1,xT+1,2,...,xT+1,L]

L L L是序列长度。假设整个模型中,包含 N N N层Transformer,那么每个segment中就有 N N N组长度为 L L L的隐向量序列,
将第 T \mathcal{T} T个segment的第 n n n层隐向量序列表示为 h T n ∈ R L × d h_{\mathcal{T}}^n \in R^{L\times d} hTnRL×d d d d是隐向量的维度.那么第 T + 1 \mathcal{T}+1 T+1 个segment的第n层隐向量序列可以由上述公式计算得出。 h ~ T + 1 n − 1 \widetilde{h}_{\mathcal{T}+1}^{n-1} h T+1n1是对两个隐向量序列沿长度方向的拼接, [ ] [ ] []内两个隐向量的维度都是 L × d L \times d L×d,拼接之后的向量维度是 2 L × d 2L \times d 2L×d。3个 W W W分别对应query,key和value的转化矩阵。注意 q q q的计算方式不变,只使用当前segment中的隐向量,计算得到的 q q q序列长度仍然是 L L L k k k v v v采用拼接之后的 h ~ \widetilde{h} h 来计算,计算出来的序列长度是 2 L 2L 2L。之后的计算就是标准的Transformer计算。计算出来的第n层隐向量序列长度仍然是 L L L,而不是 2 L 2L 2L。Transformer的输出隐向量序列长度取决于query的序列长度,而不是key和value。

训练和预测过程如下图所示。这张图上有一个点需要注意,在当前segment中,第 n n n层的每个隐向量的计算,都是利用下一层中包括当前位置在内的,连续前 L L L个长度的隐向量,这是在上面的公式组中没有体现出来的,也是文中没有明说的。每一个位置的隐向量,除了自己的位置,都跟下一层中前 ( L − 1 ) (L-1) (L1)个位置的token存在依赖关系,而且每往下走一层,依赖关系长度会增加 ( L − 1 ) (L-1) (L1),如下图中Evaluation phase所示,所以最长的依赖关系长度是 N ( L − 1 ) N(L-1) N(L1) N N N是模型中layer的数量。 N N N通常要比 L L L小很多,比如在BERT中, N = 12 N=12 N=12或者 N = 24 N=24 N=24 L = 512 L=512 L=512,依赖关系长度可以近似为 O ( N × L ) O(N \times L) O(N×L) 。在对长文本进行计算的时候,可以缓存上一个segment的隐向量的结果,不必重复计算,大幅提高计算效率。

上文中,我们只保存了上一个segment,实际操作的时候,可以保存尽可能多的segments,只要内存或者显存放得下。论文中的试验在训练的时候,只缓存一个segment,在预测的时候,会缓存多个segments。

2.2 相对位置编码 Relative Position Encodings

在Transformer中,一个重要的地方在于其考虑了序列的位置信息。在分段的情况下,如果仅仅对于每个段仍直接使用Transformer中的位置编码,即每个不同段在同一个位置上的表示使用相同的位置编码,就会出现问题。比如,第 i − 2 i−2 i2段和第 i − 1 i−1 i1段的第一个位置将具有相同的位置编码,但它们对于第ii段的建模重要性显然并不相同(例如第 i − 2 i−2 i2段中的第一个位置重要性可能要低一些)。因此,需要对这种位置进行区分。

在vanilla Transformer中,为了表示序列中token的顺序关系,在模型的输入端,对每个token的输入embedding,加一个位置embedding。位置编码embedding或者采用正弦\余弦函数来生成,或者通过学习得到。在Transformer-XL中,这种方法行不通,每个segment都添加相同的位置编码,多个segments之间无法区分位置关系。Transformer-XL放弃使用绝对位置编码,而是采用相对位置编码,在计算当前位置隐向量的时候,考虑与之依赖token的相对位置关系。具体操作是,在算attention score的时候,只考虑query向量与key向量的相对位置关系,并且将这种相对位置关系,加入到每一层Trm的attention的计算中。

我们对两种方法做个对比。下面一组公式是vanilla Transformer计算attention的方式, E x E_x Ex 表示token的输入embedding, U U U是绝对位置编码embedding,两个 W W W分别是query矩阵和key矩阵。下面的公式是对 ( E x i + U i ) W q W k ( E x j + U j ) (E_{x_i}+U_i)W_qW_k(E_{x_j}+U_j) (Exi+Ui)WqWk(Exj+Uj) 做了分解。
A i , j a b s = E x i T W q T W k E x j ⏟ ( a ) + E x i T W q T W k U j ⏟ ( b ) + U i T W q T W k E x j ⏟ ( c ) + U i T W q T W k U j ⏟ ( d ) A_{i,j}^{abs}=\underbrace{E_{x_i}^TW_q^TW_kE_{x_j}}_{(a)}+\underbrace{E_{x_i}^TW_q^TW_kU_{j}}_{(b)}+\underbrace{U_{i}^TW_q^TW_kE_{x_j}}_{(c)}+\underbrace{U_{i}^TW_q^TW_kU_{j}}_{(d)} Ai,jabs=(a) ExiTWqTWkExj+(b) ExiTWqTWkUj+(c) UiTWqTWkExj+(d) UiTWqTWkUj
其中, E x i E_{x_i} Exi是词 i i i 的embedding, E x j E_{x_j} Exj 是词 j j j 的embedding, U i U_i Ui U j U_j Uj 是位置向量,这个式子实际上是 ( W q ( E x i + U i ) ) T ⋅ ( W k ( E x j + U j ) ) (W_q(E_{x_i}+U_i))^T \cdot(W_k(E_{x_j}+U_j)) (Wq(Exi+Ui))T(Wk(Exj+Uj))的展开,就是Transformer中的标准格式。

在Transformer-XL中,对上述的attention计算方式进行了变换,转为相对位置的计算,而且不仅仅在第一层这么计算,在每一层都是这样计算。
A i , j r e l = E x i T W q T W k , E E x j ⏟ ( a ) + E x i T W q T W k , R R i − j ⏟ ( b ) + u T W k , E E x j ⏟ ( c ) + v T W k , R R i − j ⏟ ( d ) A_{i,j}^{rel}=\underbrace{E_{x_i}^TW_q^TW_{k,E}E_{x_j}}_{(a)}+\underbrace{E_{x_i}^TW_q^TW_{k,R}\color{blue}{R_{i-j}}}_{(b)}+\underbrace{{\color{red}{u^T}}W_{k,E}E_{x_j}}_{(c)}+\underbrace{{\color{red}{v^T}}W_{k,R}\color{blue}{R_{i-j}}}_{(d)} Ai,jrel=(a) ExiTWqTWk,EExj+(b) ExiTWqTWk,RRij+(c) uTWk,EExj+(d) vTWk,RRij
对比来看,主要有三点变化:

  1. 在(b)和(d)这两项中,将所有绝对位置向量 U j U_j Uj都转为相对位置向量 R i − j R_{i−j} Rij,插一句,因为i只利用之前的序列,所以 i − j ≥ 0 i-j\geq 0 ij0。与Transformer一样,这是一个固定的编码向量,不需要学习。相对位置关系用一个位置编码矩阵 R ∈ R L m a x × d R\in R^{L_{max}\times d} RRLmax×d,第 i i i行表示相对位置间隔为 i i i的位置向量。论文中强调 R R R采用正弦函数生成,而不是通过学习得到的,好处是预测时,可以使用比训练距离更长的位置向量。
  2. 在©这一项中,将查询的 U i T , W q T U_i^T,W_q^T UiT,WqT向量转为一个需要学习的参数向量 u ∈ R d u \in R^d uRd,因为在考虑相对位置的时候,不需要查询的绝对位置 i i i,因此对于任意的 i i i,都可以采用同样的向量。同理,在(d)这一项中,也将查询的 U i T , W q T U_i^T,W_q^T UiT,WqT向量转为另一个需要学习的参数向量 v ∈ R d v \in R^d vRd
  3. 将键的权重变换矩阵 W k W_k Wk转为 W k , E W_{k,E} Wk,E W k , R W_{k,R} Wk,R,分别作为content-based key vectors和location-based key vectors。

从另一个角度来解读这个公式的话,可以将attention的计算分为如下四个部分:

  • a. 基于内容的“寻址”,即没有添加原始位置编码的原始分数。
  • b. 基于内容的位置偏置,即相对于当前内容的位置偏差。
  • c. 全局的内容偏置,用于衡量key的重要性。
  • d. 全局的位置偏置,根据query和key之间的距离调整重要性。

2.3 计算公式及矩阵形式

结合上面两个创新点,将Transformer-XL模型的整体计算公式整理如下,这里考虑一个N层的只有一个注意力头的模型:
在这里插入图片描述
其中, T \mathcal{T} T代表第几段, n n n 代表第几层, h T 0 : = E s T h_{\mathcal{T}}^0:=E_{s_{\mathcal{T}}} hT0:=EsT定义为第 T \mathcal{T} T段的词向量序列。值得一提的是,计算 A A A矩阵的时候,需要对所有的 i − j i−j ij计算 W k , R n W^n_{k,R} Wk,Rn, R i − j R_{i−j} Rij,如果直接按照公式计算的话,计算时间是 O ( l e n g t h ) 2 O(length)^2 O(length)2,而实际上 i − j i−j ij的范围只从 0   l e n g t h 0 ~ length 0 length,因此可以先计算好这 l e n g t h length length个向量,然后在实际计算 A A A矩阵时直接取用即可。

具体的,设 M M M L L L分别为memory和当前段序列的长度,则 i − j i−j ij的范围也就为 0   M + L − 1 0 ~ M+L−1 0 M+L1。下面的 Q Q Q矩阵中的每一行都代表着 W k , R W_{k,R} Wk,R, R i − j R_{i−j} Rij中一个 i − j i−j ij的可能性,即 Q k = W k , R R M + L − 1 − k Q_k=W_{k,R}R_{M+L-1-k} Qk=Wk,RRM+L1k
在这里插入图片描述
则对于上面公式中的(b)项,即 q i T W k , R R i − j q_i^T W_{k,R}R_{i-j} qiTWk,RRij,其构成的所有可能向量的矩阵为 B B B矩阵,其形状为 L ∗ ( M + L ) L\ast (M+L) L(M+L),这是我们最终需要的(b)项的attention结果。
在这里插入图片描述
我们进一步定义 B ~ \widetilde{B} B 矩阵为如下:
在这里插入图片描述
可见,需要的BB矩阵的每一行只是 B ~ \widetilde{B} B 的向左shift而已。因此,可以直接利用矩阵乘法计算 B ~ \widetilde{B} B 即可。设 R i − j R_{i-j} Rij的维度为 d R d_R dR q i q_i qi的维度为 d q d_q dq W k , R W_{k,R} Wk,R矩阵的维度为 d q ∗ d R d_q\ast d_R dqdR则直接计算矩阵B的时间复杂度为 2 ∗ d q ∗ d R ∗ L ∗ ( M + L ) 2∗d_q∗d_R∗L∗(M+L) 2dqdRL(M+L),而计算 B ~ \widetilde{B} B 的时间复杂度为 L ∗ d q ∗ ( M + L ) + d q ∗ d R ∗ ( M + L ) L∗d_q∗(M+L)+d_q∗d_R∗(M+L) Ldq(M+L)+dqdR(M+L)计算量明显不是一个量级(后者要快很多)。
同理,对于(d)项来说,可以对所有的 i − j i−j ij定义需要的矩阵 D D D L ∗ ( M + L ) L ∗ ( M + L ) L∗(M+L)L∗(M+L) L(M+L)L(M+L)
在这里插入图片描述
可以用如下的 d ~ \widetilde{d} d 来进行shift得到:
在这里插入图片描述
其中 Q Q Q矩阵已经计算过了,也可以在这一步减少计算量。

3. 实验

3.1 语言建模指标

在这里插入图片描述
在这里插入图片描述

在最关心的语言模型建模指标上,论文比较了模型在单词级别和字符级别上不同数据集的表现,并且与RNN和(vanilla) Transformer都做了比较。实验证明,Transformer-XL在各个不同的数据集上均实现了目前的SoTA:在大型单词级别数据集WikiText-103上,Transformer-XL将困惑度从20.5降到18.3;在enwiki8数据集上,12层Transformer-XL的bpc达到了1.06,相同bpc的AI-Rfou的模型参数量却是6倍,24层Transformer-XL的bpc更是达到了0.99;在One Billion Word数据集上(仅具有短句的)和Penn Treebank数据集上(小型,仅有1M)也取得了SoTA的效果,前者的困惑度从23.7到21.8,后者的困惑度从55.3到54.5。表明了Transformer-XL在各个数据集下的不俗竞争力。

3.2 两个创新点的优势

下图比较了不同上下文长度(即memory的长度)中包不包含循环机制、以及使不使用新位置编码方式的困惑度得分。可见,使用循环机制和相对位置编码的Transformer-XL明显优于其他的模型,并且能够有效利用长期依赖性,而且它能捕获超出RNN 80%的依赖性,和超出Transformer 450%的依赖性。
在这里插入图片描述

3.3 测试阶段的速度

Transformer-XL的推理速度也明显快于vanilla Transformer,尤其是对于较长的上下文。比如,在上下文长度为800时,Transformer-XL提速363倍;而当上下文长度增加到3800时,Transformer-XL提速1874倍!

4. 总结

4.1 模型特点

  • 引入循环机制(Recurrence Mechanism)
  • 相对位置编码(Relative Positional Encoding)

4.2 优点

  1. 在几种不同的数据集(大/小,字符级别/单词级别等)均实现了最先进的语言建模结果。
  2. 结合了深度学习的两个重要概念——循环机制和注意力机制,允许模型学习长期依赖性,且可能可以扩展到需要该能力的其他深度学习领域,例如音频分析(如每秒16k样本的语音数据)等。
  3. 在inference阶段非常快,比之前最先进的利用Transformer模型进行语言建模的方法快300~1800倍。
  4. 有详尽的源码!含TensorFlow和PyTorch版本的,并且有TensorFlow预训练好的模型及各个数据集上详尽的超参数设置。

4.3 不足

  1. 尚未在具体的NLP任务如情感分析、QA等上应用。
  2. 没有给出与其他的基于Transformer的模型,如BERT等,对比有何优势。
  3. 在Github源码中提到,目前的sota结果是在TPU大集群上训练得出,对于我等渣机器党就只能玩玩base模式了。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值