什么是XLNet中的双流自注意力

2020-03-03 11:14:34 浏览数 (1)


作者:Xu LIANG 编译:ronghuaiyang

导读

理解XLNet中的双流自注意力机制。

在我之前的文章什么是XLNet,它为什么比BERT效果好?中,我主要讨论了XLNet (AR语言模型)和BERT (AE语言模型)之间的区别以及重排列语言建模

我相信对XLNet有一个直观的理解远比实现细节重要,所以我只解释了重排列语言建模,而没有提到另一个重要的部分,双流自注意力架构。但正如陈家明在评论中提到的,双流自注意力是XLNet论文的另一个亮点,所以我写这篇文章是为了尽可能清楚地解释双流自注意力。

内容结构如下。

  • 重排列语言建模的快速回顾
  • 重排列带来了什么问题?
  • BERT有这样的问题吗?
  • XLNet如何解决这个问题?
  • 注意力mask:XLNet如何实现重排列?

重排列建模的快速回顾

特殊的术语:

  • AR语言模型:自回归语言建模
  • AE语言模型:自动编码器语言建模

为了使这篇文章更加独立,我在这里做一个简短的总结:什么是XLNet,为什么它的性能优于BERT。

XLNet提出使用重排列语言建模,使AR语言模型学习双向上下文。这样可以避免AE语言模型中MASK方法带来的弊端。

重排列方法是获取一个序列的重排列,并使用之前的t-1个tokens作为上下文来预测第t个位置的token。例如,我们有一个句子[x1, x2, x3, x4],而x3是我们要预测的第t个位置的token。首先,我们得到句子的排列。

代码语言:javascript复制
[('x1', 'x2', 'x3', 'x4'),
 ('x1', 'x2', 'x4', 'x3'),
 ('x1', 'x3', 'x2', 'x4'),
 ('x1', 'x3', 'x4', 'x2'),
 ('x1', 'x4', 'x2', 'x3'),
 ('x1', 'x4', 'x3', 'x2'),
 ('x2', 'x1', 'x3', 'x4'),
 ('x2', 'x1', 'x4', 'x3'),
 ('x2', 'x3', 'x1', 'x4'),
 ('x2', 'x3', 'x4', 'x1'),
 ('x2', 'x4', 'x1', 'x3'),
 ('x2', 'x4', 'x3', 'x1'),
 ('x3', 'x1', 'x2', 'x4'),
 ('x3', 'x1', 'x4', 'x2'),
 ('x3', 'x2', 'x1', 'x4'),
 ('x3', 'x2', 'x4', 'x1'),
 ('x3', 'x4', 'x1', 'x2'),
 ('x3', 'x4', 'x2', 'x1'),
 ('x4', 'x1', 'x2', 'x3'),
 ('x4', 'x1', 'x3', 'x2'),
 ('x4', 'x2', 'x1', 'x3'),
 ('x4', 'x2', 'x3', 'x1'),
 ('x4', 'x3', 'x1', 'x2'),
 ('x4', 'x3', 'x2', 'x1')]

然后选取一些样本作为训练数据。(本文从排列中随机抽取样本)

代码语言:javascript复制
('x1', 'x2', 'x4', 'x3'),
('x1', 'x4', 'x3', 'x2'),
('x2', 'x3', 'x4', 'x1'),
('x4', 'x2', 'x3', 'x1'),
('x3', 'x2', 'x4', 'x1'),

我们可以看到每个token都有机会出现在x3之前。因此,AR模型可以从这些上下文tokens中学习双向信息。如果你仍然不清楚重排列,你可以阅读前面的文章。

重排列带来了什么问题?

这种重排列可以使AR模型从两个方向看到上下文,但也带来了原transformer 无法解决的问题.

重排列语言建模目标:

  • Z:一种分解顺序
  • p_θ:似然函数
  • x_zt:分解顺序中的第t个token
  • x_z<t:第t个token之前的所有tokens

这是重排列语言建模的目标函数,即以t-1个tokens为上下文,预测第t个token。

有两个标准Transformer不能满足的要求:

  1. 为了预测token x_t,模型应该只看到x_t的位置,而不是x_t的content(我将在下一节解释什么是content)
  2. 为了预测token x_t,模型应该将x_t之前的所有token编码为content

特别是第一个要求,transformer将位置编码合并到token嵌入中。因此,它不能将位置信息与token嵌入分离开来。

BERT有这样的问题吗?

BERT是一个AE语言模型,它不像AR语言模型那样需要单独的位置信息。与XLNet需要位置信息来预测第t个token不同,BERT使用[MASK]来表示要预测哪个token(我们可以认为[MASK]只是一个占位符)。例如,如果BERT使用x2, x1, x4来预测x3,那么x2, x1, x4的嵌入包含了位置信息和其他与[MASK]相关的信息。因此,该模型很有可能预测[MASK]是x3。

在这里我将对信息做更详细的说明。BERT embedded (BERT所学的信息)包含两种信息:位置信息和内容信息(为简单起见,我将其分为两部分)。

位置信息很容易理解,因为它告诉模型当前token的位置。内容信息(语义和语法)包含当前标记的“意义”。一个直观的例子是kind — man woman = queen

XLNet怎么解决这个问题?

XLNet提出了双流自注意力来解决这个问题。

顾名思义,它包含两种自注意力。一个是content stream attention,它是Transformer中的标准自注意力。另一个是query stream attention。XLNet引入它来替换BERT中的[MASK] token。

例如,如果BERT想用上下文单词x1和x2的知识来预测x3,它可以使用[MASK]来表示x3 token。[MASK]只是一个占位符。x1和x2的嵌入包含位置信息,帮助模型“知道”[MASK]的是x3。

XLNet的情况有所不同。一个token x3将服务两种角色。当它被用作内容来预测其他标记时,我们可以使用内容表示(通过内容流注意力来学习)来表示x3。但是如果我们想要预测x3,我们应该只知道它的位置而不是它的内容。这就是为什么XLNet使用查询表示(通过查询流注意力来学习)来保留x3之前的上下文信息,只保存x3的位置信息。

为了直观地理解双流自注意力,我们可以认为XLNet用查询表示代替了BERT中的[MASK]。他们只是选择不同的方法做同一件事。

注意力mask:XLNet如何实现重排列?

当我第一次读到这篇文章的时候,我不禁对训练中重排列的实现细节产生了疑惑。如果你们感兴趣,我就简单讲一下。

在第一部分“重排排列语言建模的快速回顾”中,我给出了一个句子[x1, x2, x3, x4] 的排列示例,如下所示。

代码语言:javascript复制
[('x1', 'x2', 'x3', 'x4'),
 ('x1', 'x2', 'x4', 'x3'),
 ('x1', 'x3', 'x2', 'x4'),
 ('x1', 'x3', 'x4', 'x2'),
 ('x1', 'x4', 'x2', 'x3'),
 ('x1', 'x4', 'x3', 'x2'),
 ('x2', 'x1', 'x3', 'x4'),
 ('x2', 'x1', 'x4', 'x3'),
 ('x2', 'x3', 'x1', 'x4'),
 ('x2', 'x3', 'x4', 'x1'),
 ('x2', 'x4', 'x1', 'x3'),
 ('x2', 'x4', 'x3', 'x1'),
 ('x3', 'x1', 'x2', 'x4'),
 ('x3', 'x1', 'x4', 'x2'),
 ('x3', 'x2', 'x1', 'x4'),
 ('x3', 'x2', 'x4', 'x1'),
 ('x3', 'x4', 'x1', 'x2'),
 ('x3', 'x4', 'x2', 'x1'),
 ('x4', 'x1', 'x2', 'x3'),
 ('x4', 'x1', 'x3', 'x2'),
 ('x4', 'x2', 'x1', 'x3'),
 ('x4', 'x2', 'x3', 'x1'),
 ('x4', 'x3', 'x1', 'x2'),
 ('x4', 'x3', 'x2', 'x1')]

我们很容易误解,我们需要获得一个句子的随机顺序并将其输入到模型中。但事实并非如此。输入语句的顺序是[x1, x2, x3, x4]XLNet使用注意力掩码来重排列分解因子的顺序

这个句子的原始顺序是[x1, x2, x3, x4]。我们随机得到一个分解的顺序为[x3, x2, x4, x1]

左上角是内容表示的计算。如果我们想要预测x1的内容表示,我们应该拥有所有4个token内容信息。KV = [h1, h2, h3, h4]Q = h1

左下角是查询表示的计算。如果我们想要预测x1的查询表示,我们不能看到x1本身的内容表示。KV = [h2, h3, h4]Q = g1

右下角是整个计算过程。我把它从头到尾解释了一遍。首先,hg被初始化为e(xi)w。在内容掩码和查询掩码之后,双流注意力将输出第一层输出h^(1)g^(1),然后计算第二层。

注意右边的内容掩码和查询掩码。它们都是矩阵。在内容mask中,第一行有4个红点。这意味着第一个token (x1)可以看到(注意到)所有其他tokens,包括它自己(x3->x2->x4->x1)。第二行有两个红点。这意味着第二个token (x2)可以看到(注意到)两个token(x3->x2)。等等。

内容掩码和查询掩码之间惟一的区别是,查询掩码中的对角元素为0,这意味着token不能看到它们自己。

让我们总结一下。输入的句子只有一个顺序。但是我们可以使用不同的注意力mask来实现不同的分解顺序。

总结

在这篇文章中,我主要解释了XLNet面临的问题是什么,以及如何使用双流自注意力来解决它。我还提到了有关排列注意里mask的一些实现细节。对于结果的比较,你可以从XLNet team中找到最新的发布,它比论文的比较更加公平。

—END—

英文原文:https://towardsdatascience.com/what-is-two-stream-self-attention-in-xlnet-ebfe013a0cf3

0 人点赞