XLNet模型总结

目录

1 导语

1.1 自回归语言模型(Autoregressive LM)

1.2 自编码语言模型(Autoencoder LM)

2 排列语言建模(Permutation Language Modeling)

2.1 Masked Two-Stream Attention

3 Transformer-XL

3.1 vanilla Transformer

3.2 Transformer-XL

3.2.1 引入循环机制

3.2.2 相对位置编码

4 XLNet与Bert的比较


1 导语

18年底谷歌爸爸推出了bert,该模型一经问世就占据了nlp界的统治地位,如今CMU和google brain联手推出了bert的改进版xlnet。在这之前也有很多公司对bert进行了优化,包括百度、清华的知识图谱融合,微软在预训练阶段的多任务学习等等,但是这些优化并没有把bert致命缺点进行改进。xlnet作为bert的升级模型,主要在以下三个方面进行了优化

  • 采用AR模型替代AE模型,解决mask带来的负面影响
  • 双流注意力机制
  • 引入transformer-xl

首先介绍自回归语言模型以及自编码语言模型

1.1 自回归语言模型(Autoregressive LM)

在ELMO/BERT出来之前,大家通常讲的语言模型其实是根据上文内容预测下一个可能跟随的单词,就是常说的自左向右的语言模型任务,或者反过来也行,就是根据下文预测前面的单词,这种类型的LM被称为自回归语言模型。GPT 就是典型的自回归语言模型。ELMO尽管看上去利用了上文,也利用了下文,但是本质上仍然是自回归LM,这个跟模型具体怎么实现有关系。ELMO是做了两个方向(从左到右以及从右到左两个方向的语言模型),但是是分别有两个方向的自回归LM,然后把LSTM的两个方向的隐节点状态拼接到一起,来体现双向语言模型这个事情的。所以其实是两个自回归语言模型的拼接,本质上仍然是自回归语言模型。

自回归语言模型有优点有缺点,缺点是只能利用上文或者下文的信息,不能同时利用上文和下文的信息,当然,貌似ELMO这种双向都做,然后拼接看上去能够解决这个问题,因为融合模式过于简单,所以效果其实并不是太好。它的优点,其实跟下游NLP任务有关,比如生成类NLP任务,比如文本摘要,机器翻译等,在实际生成内容的时候,就是从左向右的,自回归语言模型天然匹配这个过程。而Bert这种DAE模式,在生成类NLP任务中,就面临训练过程和应用过程不一致的问题,导致生成类的NLP任务到目前为止都做不太好。


1.2 自编码语言模型(Autoencoder LM)

AE模型采用的就是以上下文的方式,最典型的成功案例就是bert。我们简单回顾下bert的预训练阶段,预训练包括了两个任务,Masked Language Model与Next Sentence Prediction,Next Sentence Prediction即判断两个序列的推断关系,Masked Language Model采用了一个标志位[MASK]来随机替换一些词,再用[MASK]的上下文来预测[MASK]的真实值,bert的最大问题也是处在这个MASK的点,因为在微调阶段,没有MASK这就导致预训练和微调数据的不统一,从而引入了一些人为误差,我觉得这应该就是为什么GPT坚持采用AR模型的原因。

在xlnet中,最终还是采用了AR模型,但是怎么解决这个上下文的问题呢,这就是本文的一个重点。

1.3 AR和AE方法各自的目标函数

对于如下输入语句

针对AR方法的语言模型而言,在从前到后的方向上,实际上就是如下的目标函数,

针对以BERT为代表的AE语言模型,因为其中一定比例(比如15%)的词被替换为[MASK],因此只会针对这些被挖掉的词计入目标函数,下式中的m只有在mask词的位置才会为1

从这里可以仔细看到上式使用了约等号,并且假定各个被mask的词生成之间是相互独立的,也就是生成每一个被mask掉的词都与其他任何mask词无关。

2 排列语言建模(Permutation Language Modeling)

XLNet仍然遵循两阶段的过程,第一个阶段是语言模型预训练阶段;第二阶段是任务数据Fine-tuning阶段。它主要希望改动第一个阶段,就是说不像Bert那种带Mask符号的Denoising-autoencoder的模式,而是采用自回归LM的模式。就是说,看上去输入句子X仍然是自左向右的输入,看到TiTi单词的上文Context_before,来预测TiTi这个单词。但是又希望在Context_before里,不仅仅看到上文单词,也能看到TiTi单词后面的下文Context_after里的下文单词,这样的话,Bert里面预训练阶段引入的Mask符号就不需要了,于是在预训练阶段,看上去是个标准的从左向右过程,Fine-tuning当然也是这个过程,于是两个环节就统一起来。当然,这是目标。剩下是怎么做到这一点的问题。

那么,怎么能够在单词Ti的上文中Contenxt_before中揉入下文Context_after的内容呢?你可以想想。XLNet是这么做的,在预训练阶段,引入Permutation Language Model的训练目标。什么意思呢?就是说,比如包含单词Ti的当前输入的句子X,由顺序的几个单词构成,比如x1,x2,x3,x4四个单词顺序构成。我们假设,其中,要预测的单词Ti是x3,位置在Position 3,要想让它能够在上文Context_before中,也就是Position 1或者Position 2的位置看到Position 4的单词x4。可以这么做:假设我们固定住x3所在位置,就是它仍然在Position 3,之后随机排列组合句子中的4个单词,在随机排列组合后的各种可能里,再选择一部分作为模型预训练的输入X。比如随机排列组合后,抽取出x4,x2,x3,x1这一个排列组合作为模型的输入X。于是,x3就能同时看到上文x2,以及下文x4的内容了。这就是XLNet的基本思想,所以说,看了这个就可以理解上面讲的它的初衷了吧:看上去仍然是个自回归的从左到右的语言模型,但是其实通过对句子中单词排列组合,把一部分Ti下文的单词排到Ti的上文位置中,于是,就看到了上文和下文,但是形式上看上去仍然是从左到右在预测后一个单词。

当然,上面讲的仍然是基本思想。难点其实在于具体怎么做才能实现上述思想。首先,需要强调一点,尽管上面讲的是把句子X的单词排列组合后,再随机抽取例子作为输入,但是,实际上你是不能这么做的,因为Fine-tuning阶段你不可能也去排列组合原始输入。所以,就必须让预训练阶段的输入部分,看上去仍然是x1,x2,x3,x4这个输入顺序,但是可以在Transformer部分做些工作,来达成我们希望的目标。具体而言,XLNet采取了Attention掩码的机制,你可以理解为,当前的输入句子是X,要预测的单词Ti是第i个单词,前面1到i-1个单词,在输入部分观察,并没发生变化,该是谁还是谁。但是在Transformer内部,通过Attention掩码,从X的输入单词里面,也就是Ti的上文和下文单词中,随机选择i-1个,放到Ti的上文位置中,把其它单词的输入通过Attention掩码隐藏掉,于是就能够达成我们期望的目标(当然这个所谓放到Ti的上文位置,只是一种形象的说法,其实在内部,就是通过Attention Mask,把其它没有被选到的单词Mask掉,不让它们在预测单词Ti的时候发生作用,如此而已。看着就类似于把这些被选中的单词放到了上文Context_before的位置了)。具体实现的时候,XLNet是用“双流自注意力模型”实现的,细节可以参考论文,但是基本思想就如上所述,双流自注意力机制只是实现这个思想的具体方式,理论上,你可以想出其它具体实现方式来实现这个基本思想,也能达成让Ti看到下文单词的目标。

2.1 Masked Two-Stream Attention

这里简单说下“双流自注意力机制”,一个是内容流自注意力,其实就是标准的Transformer的计算过程;主要是引入了Query流自注意力,这个是干嘛的呢?其实就是用来代替Bert的那个[Mask]标记的,因为XLNet希望抛掉[Mask]标记符号,但是比如知道上文单词x1,x2,要预测单词x3,此时在x3对应位置的Transformer最高层去预测这个单词,但是输入侧不能看到要预测的单词x3,Bert其实是直接引入[Mask]标记来覆盖掉单词x3的内容的,等于说[Mask]是个通用的占位符号。而XLNet因为要抛掉[Mask]标记,但是又不能看到x3的输入,于是Query流,就直接忽略掉x3输入了,只保留这个位置信息,用参数w来代表位置的embedding编码。其实XLNet只是扔了表面的[Mask]占位符号,内部还是引入Query流来忽略掉被Mask的这个单词。和Bert比,只是实现方式不同而已。

上面说的Attention掩码,我估计你还是没了解它的意思,我再用例子解释一下。Attention Mask的机制,核心就是说,尽管当前输入看上去仍然是x1->x2->x3->x4,但是我们已经改成随机排列组合的另外一个顺序x3->x2->x4->x1了,如果用这个例子用来从左到右训练LM,意味着当预测x2的时候,它只能看到上文x3;当预测x4的时候,只能看到上文x3和x2,以此类推……这样,比如对于x2来说,就看到了下文x3了。这种在输入侧维持表面的X句子单词顺序,但是其实在Transformer内部,看到的已经是被重新排列组合后的顺序,是通过Attention掩码来实现的。如上图所示,输入看上去仍然是x1,x2,x3,x4,可以通过不同的掩码矩阵,让当前单词Xi只能看到被排列组合后的顺序x3->x2->x4->x1中自己前面的单词。这样就在内部改成了被预测单词同时看到上下文单词,但是输入侧看上去仍然维持原先的单词顺序了。关键要看明白上图右侧那个掩码矩阵,我相信很多人刚开始没看明白,因为我刚开始也没看明白,因为没有标出掩码矩阵的单词坐标,它的坐标是1-2-3-4,就是表面那个X的单词顺序,通过掩码矩阵,就能改成你想要的排列组合,并让当前单词看到它该看到的所谓上文,其实是掺杂了上文和下文的内容。这是attention mask来实现排列组合的背后的意思。

上面讲的Permutation Language Model是XLNet的主要理论创新,所以介绍的比较多,从模型角度讲,这个创新还是挺有意思的,因为它开启了自回归语言模型如何引入下文的一个思路,相信对于后续工作会有启发。当然,XLNet不仅仅做了这些,它还引入了其它的因素,也算是一个当前有效技术的集成体。感觉XLNet就是Bert、GPT 2.0和Transformer XL的综合体变身,首先,它通过PLM预训练目标,吸收了Bert的双向语言模型;然后,GPT2.0的核心其实是更多更高质量的预训练数据,这个明显也被XLNet吸收进来了;再然后,Transformer XL的主要思想也被吸收进来,它的主要目标是解决Transformer对于长文档NLP应用不够友好的问题。

https://blog.csdn.net/weixin_37947156/article/details/93035607

3 Transformer-XL

本文发表在ACL2019上,论文想要解决的问题:如何赋予编码器捕获长距离依赖的能力。目前在自然语言处理领域,Transformer的编码能力超越了RNN,但是对长距离依赖的建模能力仍然不足。在基于LSTM的模型中,为了建模长距离依赖,提出了门控机制和梯度裁剪,目前可以编码的最长距离在200左右。在基于Transformer的模型中,允许词之间直接建立联系【self-attention】,能够更好地捕获长期依赖关系,但是还是有限制。

3.1 Motivation

Transformer编码固定长度的上下文,即将一个长的文本序列截断为几百个字符的固定长度片段(segment),然后分别编码每个片段[1],片段之间没有任何的信息交互。比如BERT,序列长度的极限一般在512。动机总结如下:

  • Transformer无法建模超过固定长度的依赖关系,对长文本编码效果差。
  • Transformer把要处理的文本分割成等长的片段,通常不考虑句子(语义)边界,导致上下文碎片化(context fragmentation)。通俗来讲,一个完整的句子在分割后,一半在前面的片段,一半在后面的片段。

文章围绕如何建模长距离依赖,提出Transformer-XL【XL是extra long的意思】:

  • 提出片段级递归机制(segment-level recurrence mechanism),引入一个记忆(memory)模块(类似于cache或cell),循环用来建模片段之间的联系。
    • 使得长距离依赖的建模成为可能;
    • 使得片段之间产生交互,解决上下文碎片化问题。
  • 提出相对位置编码机制(relative position embedding scheme),代替绝对位置编码。
    • 在memory的循环计算过程中,避免时序混淆【见model部分】,位置编码可重用。

小结一下,片段级递归机制为了解决编码长距离依赖和上下文碎片化,相对位置编码机制为了实现片段级递归机制而提出,解决可能出现的时序混淆问题。

3.2 Model

3.2.1 Vanilla Transformer

transformer-XL在文章中所对比的Vanilla Transformer model,也是google在AAAI 2019[18]上的一篇工作,其将transformer用于character-level的语言模型中:添加了多个loss来提高其表现并加快拟合速度;增大transformer层数来提高表现,最多到了64层。

下图是Vanilla transformer在训练时的示意图(segment长度为4)[19]:

在transformer-XL中,上一个时刻的segment的representation会被保存下来,并作为下一个segment的扩展上下文,整个过程类似于RNN。由此,可以捕获的最大依赖项长度增加了N倍(N是网络深度);同时Recurrence使得编码当前segment时,仍然可以利用之前segment的信息,从而解决了context fragmentation问题。下图是transformer-XL在训练时的示意图(segment长度为4):

segment-level recurrence mechanism

为了解决长距离依赖,文章引入一个memory状态。

在训练过程中,每个片段的表示为最后的隐层状态​,​表示片段的序号,​表示片段的长度,​表示隐层维度。

在计算​片段的表示时,用memory缓存​片段​层的隐层状态​,用来更新​,这样就给下一个片段同了上文,长距离依赖也通过memory保存了下来。并且,最大可能的依赖长度线性增长,达到 N*L 。

relative position embedding scheme

faster evaluation

在评估时, Transformer-XL比Vanilla Transformer具有更长的有效上下文,并且Transformer-XL能够在不需要重新计算的情况下处理新段中的所有元素,显著提高了速度。下图是评估阶段的对比图:

Vanilla Transformer:

Transformer-XL

推荐几篇博文:

Transformer-XL解读(论文 + PyTorch源码)

论文笔记 —— Transformer-XL

https://blog.csdn.net/weixin_37947156/article/details/93035607

4 XLNet与Bert的比较

  • Bert是直接在输入端显示地通过引入Mask标记,在输入侧隐藏掉一部分单词,让这些单词在预测的时候不发挥作用,要求利用上下文中其它单词去预测某个被Mask掉的单词。
  • XLNet则抛弃掉输入侧的Mask标记,通过Attention Mask机制,在Transformer内部随机Mask掉一部分单词(这个被Mask掉的单词比例跟当前单词在句子中的位置有关系,位置越靠前,被Mask掉的比例越高,位置越靠后,被Mask掉的比例越低),让这些被Mask掉的单词在预测某个单词的时候不发生作用。
  • Bert隐藏了15%的词,用85%去预测15%的词。缺少了15%的词中的关联性。
  • XLNet是通过整个上下文去预测某个词,这样的词的利用率更高,理论上效果更好。

References:

XLNet:运行机制及和Bert的异同比较

XLNet原理探究

XLNet预训练模型,看这篇就够了!

XLNet论文笔记(上)

transformer三部曲

[NLP] 相对位置编码(二) Relative Positional Encodings - Transformer-XL

发布了74 篇原创文章 · 获赞 17 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/sinat_25394043/article/details/103461807