赞
踩
预训练模型(Pretrained model):一般情况下预训练模型都是大型模型,具备复杂的网络结构,众多的参数量,以及在足够大的数据集下进行训练而产生的模型.
在NLP领域,预训练模型往往是语言模型,因为语言模型的训练是无监督的,可以获得大规模语料,同时语言模型又是许多典型NLP任务的基础,如机器翻译,文本生成,阅读理解等,常见的预训练模型有BERT, GPT, roBERTa, transformer-XL等.
“干翻芝麻街”
2018 年,谷歌发布了基于双向 Transformer 的大规模预训练语言模型 BERT,刷新了 11 项 NLP 任务的最优性能记录,为 NLP 领域带来了极大的惊喜。很快,BERT 就在圈内普及开来,也陆续出现了很多与它相关的新工作。
BERT 带来的震撼还未平息,来自卡耐基梅隆大学与谷歌大脑的研究者又提出新型预训练语言模型 XLNet,在 SQuAD、GLUE、RACE 等 20 个任务上全面超越 BERT。
作者表示,BERT 这样基于去噪自编码器的预训练模型可以很好地建模双向语境信息,性能优于基于自回归语言模型的预训练方法。然而,由于需要 mask 一部分输入,BERT 忽略了被 mask 位置之间的依赖关系,因此出现预训练和微调效果的差异(pretrain-finetune discrepancy)
基于这些优缺点,该研究提出了一种泛化的自回归预训练模型 XLNet。XLNet 可以:
最终,XLNet 在 20 个任务上超过了 BERT 的表现,并在 18 个任务上取得了当前最佳效果(state-of-the-art),包括机器问答、自然语言推断、情感分析和文档排序。
以前超越 BERT 的模型很多都在它的基础上做一些修改,本质上模型架构和任务都没有太大变化。但是在这篇新论文中,作者从自回归(autoregressive)和自编码(autoencoding)两大范式分析了当前的预训练语言模型,并发现它们虽然各自都有优势,但也都有难以解决的困难。为此,研究者提出 XLNet,并希望结合大阵营的优秀属性。
随着一些奇怪的高维数据出现,比如图像、语音,传统的统计学-机器学习方法遇到了前所未有的挑战。
数据维度过高,数据单调,噪声分布广,传统方法的“数值游戏”很难奏效。数据挖掘?已然挖不出有用的东西。
为了解决高维度的问题,出现的线性学习的PCA降维方法,PCA的数学理论确实无懈可击,但是却只对线性数据效果比较好。
于是,寻求简单的、自动的、智能的特征提取方法仍然是机器学习的研究重点。比如LeCun在1998年CNN总结性论文中就概括了今后机器学习模型的基本架构。
当然CNN另辟蹊径,利用卷积、降采样两大手段从信号数据的特点上很好的提取出了特征。对于一般非信号数据,该怎么办呢??
自动编码器基于这样一个事实:原始input(设为x)经过加权(W、b)、映射(Sigmoid)之后得到y,再对y反向加权映射回来成为z。
通过反复迭代训练两组(W、b),使得误差函数最小,即尽可能保证z近似于x,即完美重构了x。
那么可以说正向第一组权(W、b)是成功的,很好的学习了input中的关键特征,不然也不会重构得如此完美。结构图如下:
从生物的大脑角度考虑,可以这么理解,学习和重构就好像编码和解码一样。
这个过程很有趣,首先,它没有使用数据标签来计算误差update参数,所以是无监督学习。
其次,利用类似神经网络的双隐层的方式,简单粗暴地提取了样本的特征。
这个双隐层是有争议的,最初的编码器确实使用了两组(W,b),但是Vincent在2010年的论文中做了研究,发现只要单组W就可以了。
即 W ′ = W T W'=W^T W′=WT, W W W 和 W ’ W’ W’ 称为Tied Weights。实验证明, W ′ W' W′ 真的只是在打酱油,完全没有必要去做训练。
逆向重构矩阵让人想起了逆矩阵,若 W − 1 = W T W^{-1}=W^T W−1=WT 的话, W W W 就是个正交矩阵了,即 W W W 是可以训成近似正交阵的。
由于 W ′ W' W′ 就是个酱油,训练完之后就没它事了。正向传播用 W W W 即可,相当于为input预先编个码,再导入到下一layer去。所以叫自动编码器,而不叫自动编码解码器。
Vincent在2008年的论文中提出了AutoEncoder的改良版——dA。论文的标题叫 “Extracting and Composing Robust Features”,译成中文就是"提取、编码出具有鲁棒性的特征"。
怎么才能使特征很鲁棒呢?就是以一定概率分布(通常使用二项分布)去擦除原始input矩阵,即每个值都随机置0, 这样看起来部分数据的部分特征是丢失了。以这丢失的数据 x ′ x' x′ 去计算 y y y,计算 z z z,并将 z z z 与原始 x x x 做误差迭代,这样,网络就学习了这个破损(原文叫Corruputed)的数据。
这个破损的数据是很有用的,原因有二:
这样训练出来的Weight的鲁棒性就提高了。图示如下:
关键是,这样胡乱擦除原始input真的很科学?真的没问题? Vincent又从大脑认知角度给了解释:
paper中这么说到:人类具有认知被阻挡的破损图像能力,此源于我们高等的联想记忆感受机能。
我们能以多种形式去记忆(比如图像、声音,甚至如上图的词根记忆法),所以即便是数据破损丢失,我们也能回想起来。
另外,就是从特征提取的流形学习(Manifold Learning)角度看:
破损的数据相当于一个简化的PCA,把特征做一个简单的降维预提取。
Denoising Auto-encoder与人的感知机理类似,比如人眼看物体时,如果物体某一小部分被遮住了,人依然能够将其识别出来。
人在接收到多模态信息时(比如声音,图像等),少了其中某些模态的信息有时也不会造成太大影响。
Autoencoder的本质是学习一个相等函数,即网络的输入和重构后的输出相等,这种相等函数的表示有个缺点就是当测试样本和训练样本不符合同一分布,即相差较大时,效果不好,而Denoising Autoencoder在这方面的处理有所进步。
在 ELMO/BERT 出来之前,大家通常讲的语言模型其实是根据上文内容预测下一个可能跟随的单词,就是常说的自左向右的语言模型任务,或者反过来也行(就是根据下文预测前面的单词)。这种类型的 LM 被称为自回归语言模型。
AR即 Auto-Regressive自回归,也就是论文题目中的自回归。
给定文本序列 x = [ x 1 , … , x T ] \mathbf{x}=[x_1,…,x_T] x=[x1,…,xT],语言模型的目标是调整参数使得训练数据上的似然函数最大:
m a x θ l o g p θ ( x ) = ∑ t = 1 T l o g p θ ( x t ∣ x < t ) = ∑ t = 1 T l o g e x p ( h θ ( x 1 : t − 1 ) T e ( x t ) ) ∑ x ′ e x p ( h θ ( x 1 : t − 1 ) T e ( x ′ ) ) 等式(1) \underset{\theta}{max}\; log p_\theta(\mathbf{x})=\sum_{t=1}^T log p_\theta(x_t \vert \mathbf{x}_{<t})=\sum_{t=1}^T log \frac{exp(h_\theta(\mathbf{x}_{1:t-1})^T e(x_t))}{\sum_{x'}exp(h_\theta(\mathbf{x}_{1:t-1})^T e(x'))} \text{ 等式(1)} θmaxlogpθ(x)=t=1∑Tlogpθ(xt∣x<t)=t=1∑Tlog∑x′exp(hθ(x1:t−1)Te(x′))exp(hθ(x1:t−1)Te(xt)) 等式(1)
自回归语言模型的缺点是无法同时利用上下文的信息,貌似 ELMO 这种双向都做,然后拼接看上去能够解决这个问题,但其实融合方法过于简单,所以效果其实并不是太好。它的优点跟下游 NLP 任务有关,比如生成类 NLP 任务,比如文本摘要,机器翻译等,在实际生成内容的时候,就是从左向右的,自回归语言模型天然匹配这个过程。
而 Bert 这种 DAE(Denoise AutoEncoder)模式,在生成类 NLP 任务中,面临训练过程和应用过程不一致的问题,导致生成类的 NLP 任务到目前为止都做不太好
AE即(Denoising )AutoEncoder降噪自编码,以BERT模型为代表的自编码模型。
BERT是去噪(denoising)自编码的方法。对于序列 x \mathbf{x} x,BERT会随机挑选15%的Token变成[MASK]得到带噪声版本的 x ^ \hat{\mathbf{x}} x^。假设被Mask的原始值为 x ˉ \bar{\mathbf{x}} xˉ,那么BERT希望尽量根据上下文恢复(猜测)出原始值了,也就是:
m a x θ l o g p θ ( x ˉ ∣ x ^ ) ≈ ∑ t = 1 T m t l o g p θ ( x t ∣ x ^ ) = ∑ t = 1 T m t l o g e x p ( H θ ( x ) t T e ( x t ) ) ∑ x ′ e x p ( H θ ( x ) t T e ( x ′ ) ) 等式(2) \underset{\theta}{max}\;log p_\theta(\bar{\mathbf{x}} | \hat{\mathbf{x}}) \approx \sum_{t=1}^Tm_t log p_\theta(x_t | \hat{\mathbf{x}})=\sum_{t=1}^T m_t log \frac{exp(H_\theta(\mathbf{x})_{t}^T e(x_t))}{\sum_{x'}exp(H_\theta(\mathbf{x})_{t}^T e(x'))} \text{ 等式(2)} θmaxlogpθ(xˉ∣x^)≈t=1∑Tmtlogpθ(xt∣x^)=t=1∑Tmtlog∑x′exp(Hθ(x)tTe(x′))exp(Hθ(x)tTe(xt)) 等式(2)
注意:前面的AR语言模型的RNN在 t t t 时刻只能看到之前的时刻,因此记号是 h θ ( x 1 : t − 1 ) h_\theta(\mathbf{x}_{1:t-1}) hθ(x1:t−1);而BERT的Transformer(不同与用于语言模型的Transformer)可以同时看到整个句子的所有Token,因此记号是 H θ ( x ) H_\theta(\mathbf{x}) Hθ(x)。
如上式中的 ≈ ≈ ≈ 符号所强调,BERT(AE)对联合条件概率进行分解是基于一个独立假设,即假定所有掩码token均被独立重建,待预测的掩码token之间在给定未掩盖的token的上下文中没有依赖关系,这样的假设太过简单,因为高阶、长程依赖在自然语言中普遍存在。
这种 AE【(Denoising )AutoEncoder】降噪自编码 的优缺点正好和 AR(Auto-Regressive自回归)【语言模型】 反过来,它能比较自然地融入双向语言模型,同时看到被预测单词的上文和下文,这是好处。缺点是啥呢?主要在输入侧引入 [Mask] 标记,导致预训练阶段和 Fine-tuning 阶段不一致的问题,因为 Fine-tuning 阶段是看不到 [Mask] 标记的
独立假设
输入噪声
双向上下文
鉴于这些优点和缺点,XLNet作者就想结合AR和AE语言模型各自的优点同时摒弃缺点,因此就有了屠榜的XLNet。
XLNet 的出发点就是:能否融合自回归 LM 和 DAE LM 两者的优点。具体来说就是,站在 AR 的角度,如何引入和双向语言模型等价的效果
根据上面的讨论,语言模型和BERT各有优缺点,有什么办法能构建一个模型使得同时有它们的优点并且没有它们缺点呢?
借鉴NADE(不了解的读者可以忽略,这是一种生成模型)的思路,只要在 AR 以及 AE 方式中再加入一个步骤,就能够完美地将两者统一起来,那就是 Permutation,XLNet使用了排列语言模型,它同时有AR、AE两个模型的优点。
具体实现方式是,通过随机取一句话排列的一种,然后将末尾一定量的词给 “遮掩”(和 BERT 里的直接替换 “[MASK]” 有些不同)掉,最后用 AR 的方式来按照这种排列方式依此预测被 “遮掩” 掉的词
这里我稍微解释下,为什么是 “遮掩” 末尾的一些词,以及随机打乱句子的顺序有什么用?
这里再谈一个有意思的点,到底该挑选最后几个做遮掩呢?作者这里设了一个超参数 K,K 等于总长度除以需要预测的个数。拿上面的例子,总长为 7 而需要预测为 2,于是 K = 7/2。而论文中实验得出的最佳 K 值介于 6 和 7 (更好)之间,其实如果我们取 K 的倒数(即 1 6 , 1 7 \frac{1}{6},\frac{1}{7} 61,71),然后转为百分比,就会发现最佳的比值介于 14.3% 到 16.7% 之间,还记得 BERT 论文的同学肯定就会开始觉得眼熟了。因为 BERT 里将 Token 遮掩成 “[MASK]” 的百分比就是 15%,正好介于它们之间,我想这并不只是偶然,肯定有更深层的联系。
给定长度为T的序列 x \mathbf{x} x,总共有 T ! T! T! 种排列方法,也就对应 T ! T! T! 种链式分解方法。
举个例子,假设 x = x 1 x 2 x 3 \mathbf{x}=x_1x_2x_3 x=x1x2x3,则 T = 3 T=3 T=3,那么总共用 3 ! = 6 3!=6 3!=6种分解方法:
p ( x ) = p ( x 1 ) p ( x 2 ∣ x 1 ) p ( x 3 ∣ x 1 x 2 ) ⇒ 1 → 2 → 3 p ( x ) = p ( x 1 ) p ( x 2 ∣ x 1 x 3 ) p ( x 3 ∣ x 1 ) ⇒ 1 → 3 → 2 p ( x ) = p ( x 1 ∣ x 2 ) p ( x 2 ) p ( x 3 ∣ x 1 x 2 ) ⇒ 2 → 1 → 3 p ( x ) = p ( x 1 ∣ x 2 x 3 ) p ( x 2 ) p ( x 3 ∣ x 2 ) ⇒ 2 → 3 → 1 p ( x ) = ) p ( x 1 ∣ x 2 x 3 ) p ( x 2 ∣ x 3 p ( x 3 ) ⇒ 3 → 2 → 1 p ( x ) = p ( x 1 ∣ x 3 ) p ( x 2 ∣ x 1 x 3 ) p ( x 3 ) ⇒ 3 → 1 → 2 p(\mathbf{x})=p(x_1)p(x_2|x_1)p(x_3|x_1x_2) \Rightarrow 1 \rightarrow 2 \rightarrow 3 \\ p(\mathbf{x})=p(x_1)p(x_2|x_1x_3)p(x_3|x_1) \Rightarrow 1 \rightarrow 3 \rightarrow 2 \\ p(\mathbf{x})=p(x_1|x_2)p(x_2)p(x_3|x_1x_2) \Rightarrow 2 \rightarrow 1 \rightarrow 3 \\ p(\mathbf{x})=p(x_1|x_2x_3)p(x_2)p(x_3|x_2) \Rightarrow 2 \rightarrow 3 \rightarrow 1 \\ p(\mathbf{x})=)p(x_1|x_2x_3)p(x_2|x_3p(x_3) \Rightarrow 3 \rightarrow 2 \rightarrow 1 \\ p(\mathbf{x})=p(x_1|x_3)p(x_2|x_1x_3)p(x_3) \Rightarrow 3 \rightarrow 1 \rightarrow 2 p(x)=p(x1)p(x2∣x1)p(x3∣x1x2)⇒1→2→3p(x)=p(x1)p(x2∣x1x3)p(x3∣x1)⇒1→3→2p(x)=p(x1∣x2)p(x2)p(x3∣x1x2)⇒2→1→3p(x)=p(x1∣x2x3)p(x2)p(x3∣x2)⇒2→3→1p(x)=)p(x1∣x2x3)p(x2∣x3p(x3)⇒3→2→1p(x)=p(x1∣x3)p(x2∣x1x3)p(x3)⇒3→1→2
注意: p ( x 2 ∣ x 1 x 3 ) p(x_2 \vert x_1x_3) p(x2∣x1x3) 指的是第一个词是 x 1 x_1 x1 并且第三个词是 x 3 x_3 x3 的条件下第二个词是 x 2 x_2 x2 的概率,也就是说原来词的顺序是保持的。如果理解为第一个词是 x 1 x_1 x1 并且第二个词是 x 3 x_3 x3 的条件下第三个词是 x 2 x_2 x2,那么就理解错了。
如果我们的语言模型遍历 T ! T! T! 种分解方法,并且这个模型的参数是共享的,那么这个模型应该就能(必须)学习到各种上下文。
对于一个长度为 T T T的句子,我们可以遍历 T ! T! T! 种路径,然后学习语言模型的参数,但是这个计算量非常大(10!=3628800,10个词的句子就有这么多种组合)。因此实际我们只能随机的采样 T ! T! T! 里的部分排列。
为了用数学语言描述,我们引入几个记号:
举个例子,假设 T = 3 T=3 T=3,那么 Z T \mathcal{Z}_T ZT 共有 3 ! = 6 3!=6 3!=6 个元素,我们假设其中之一 z = [ 1 , 3 , 2 ] z=[1,3,2] z=[1,3,2],则 z 3 = 2 z_3=2 z3=2,而 z < 3 = [ 1 , 3 ] z_{<3}=[1,3] z<3=[1,3]。
有了上面的记号,则排列语言模型的目标是调整模型参数使得下面的似然概率最大:
m a x θ E z ∼ Z T [ ∑ t = 1 T l o g p θ ( x z t ∣ x z < t ) ] \underset{\theta}{max} \mathbb{E}_{z \sim \mathcal{Z}_T}[\sum_{t=1}^Tlog p_\theta(x_{z_t}|\mathbf{x}_{z_{<t}})] θmaxEz∼ZT[t=1∑Tlogpθ(xzt∣xz<t)]
上面的公式看起来有点复杂,细读起来其实很简单:从所有的排列中采样一种,然后根据这个排列来分解联合概率成条件概率的乘积,然后加起来。
注意:上面的模型只会遍历概率的分解顺序,并不会改变原始词的顺序。
论文中 Permutation 具体的实现方式不是打乱输入句子的顺序,而是通过对 Transformer 的 Attention Mask 进行操作,实现不同的分解方法。
比如说序号依次为 1234 的句子,先随机取一种排列 3241。根据这个排列我们就做出类似上图的 Attention Mask,先看第 1 行,因为在新的排列方式中 1 在最后一个,根据从左到右 AR 方式,1 就能看到 234 全部,于是第一行的 234 位置是红色的(没有遮盖掉,会用到),以此类推,第 2 行,因为 2 在新排列是第二个,只能看到 3 于是 3 位置是红色,第 3 行,因为 3 在第一个,看不到其他位置,所以全部遮盖掉…
比如 p ( x 1 ∣ x 3 ) p ( x 2 ∣ x 1 x 3 ) p ( x 3 ) p(x_1 \vert x_3)p(x_2 \vert x_1x_3)p(x_3) p(x1∣x3)p(x2∣x1x3)p(x3),我们可以在用Transformer编码 x 1 x_1 x1时候让它可以Attend to x 3 x_3 x3,而把 x 2 x_2 x2Mask掉;编码 x 3 x_3 x3 的时候把 x 1 , x 2 x_1,x_2 x1,x2 都Mask掉。
下图为排列语言模型在预测
x
3
x_3
x3 时不同排列的情况:
比如图的左上,对应的分解方式是
3
→
2
→
4
→
1
3 \rightarrow 2 \rightarrow 4 \rightarrow 1
3→2→4→1,因此预测
x
3
x_3
x3 是不能attend to任何其它词,只能根据之前的隐状态
m
e
m
mem
mem 来预测。而对于左下,
x
3
x_3
x3可以attend to其它3个词。
上面排列(Permutation)语言模型的思想很简单,但是如果我们使用标准的Transformer来实现时会有问题。我们来看一个例子。
假设输入的句子是 “I like New York”,并且一种排列为 z = [ 1 , 3 , 4 , 2 ] z=[1, 3, 4, 2] z=[1,3,4,2],假设我们需要预测 z 3 = 4 z_3=4 z3=4 ,那么根据公式:
p θ ( X z 3 = x ∣ x z 1 z 2 ) = p θ ( X 4 = x ∣ x 1 x 3 ) = e x p ( e ( x ) T h θ ( x 1 x 3 ) ) ∑ x ′ e x p ( e ( x ′ ) T h θ ( x 1 x 3 ) ) p_\theta(X_{z_3}=x|x_{z_1z_2})=p_\theta(X_4=x|x_1x_3)=\frac{exp(e(x)^Th_\theta(x_1x_3))}{\sum_{x'}exp(e(x')^Th_\theta(x_1x_3))} pθ(Xz3=x∣xz1z2)=pθ(X4=x∣x1x3)=∑x′exp(e(x′)Thθ(x1x3))exp(e(x)Thθ(x1x3))
另外我们再假设一种排列为 z ’ = [ 1 , 3 , 2 , 4 ] z’=[1,3,2,4] z’=[1,3,2,4],我们需要预测 z 3 = 2 z_3=2 z3=2,那么:
p θ ( X z 3 = x ∣ x z 1 z 2 ) = p θ ( X 2 = x ∣ x 1 x 3 ) = e x p ( e ( x ) T h θ ( x 1 x 3 ) ) ∑ x ′ e x p ( e ( x ′ ) T h θ ( x 1 x 3 ) ) p_\theta(X_{z_3}=x|x_{z_1z_2})=p_\theta(X_2=x|x_1x_3)=\frac{exp(e(x)^Th_\theta(x_1x_3))}{\sum_{x'}exp(e(x')^Th_\theta(x_1x_3))} pθ(Xz3=x∣xz1z2)=pθ(X2=x∣x1x3)=∑x′exp(e(x′)Thθ(x1x3))exp(e(x)Thθ(x1x3))
我们仔细对比一下公式会发现这两个概率是相等的。
但是根据经验,显然这两个概率是不同的,而且上面的那个概率大一些,因为York跟在New之后是一个城市,而”York New”是什么呢?
上面的问题的关键是模型并不知道要预测的那个词在原始序列中的位置。
了解Transformer的读者可能会问:输入的位置编码在哪里呢?位置编码的信息不能起作用吗?
注意:位置编码是和输入的Embedding加到一起作为输入的,因此 p θ ( X 4 = x ∣ x 1 x 3 ) p_\theta(X_4=x \vert x_1x_3) pθ(X4=x∣x1x3) 里的 x 1 x_1 x1 和 x 3 x_3 x3 是带了位置信息的,模型(可能)知道(根据输入的向量猜测)I是第一个词,而New是第三个词,但是第四个词的向量显然这个是还不知道(知道了还要就不用预测了),因此就不可能知道它要预测的词到底是哪个位置的词,因此我们必须”显式”的告诉模型我要预测哪个位置的词。
为了后面的描述,我们再把上面的两个公式写出更加一般的形式。给定排列 z z z,我们需要计算 p θ ( X z t ∣ x z < t = x ) p_\theta(X_{z_t} \vert \mathbf{x}_{z_{<t}}=x) pθ(Xzt∣xz<t=x),如果我们使用普通的Transformer,那么计算公式为:
p θ ( X z t = x ∣ x z < t ) = e x p ( e ( x ) T h θ ( x z < t ) ) ∑ x ′ e x p ( e ( x ′ ) T h θ ( x z < t ) ) p_\theta(X_{z_t}=x \vert \mathbf{x}_{z_{<t}})=\frac{exp(e(x)^Th_\theta(\mathbf{x}_{z_{<t}}))}{\sum_{x'}exp(e(x')^Th_\theta(\mathbf{x}_{z_{<t}}))} pθ(Xzt=x∣xz<t)=∑x′exp(e(x′)Thθ(xz<t))exp(e(x)Thθ(xz<t))
根据前面的讨论,我们知道问题的关键是模型并不知道要预测的到底是哪个位置的词,为了解决这个问题,我们把预测的位置 z t z_t zt放到模型里:
p θ ( X z t = x ∣ x z < t ) = e x p ( e ( x ) T g θ ( x z < t , z t ) ) ∑ x ′ e x p ( e ( x ′ ) T g θ ( x z < t , z t ) ) p_\theta(X_{z_t}=x \vert \mathbf{x}_{z_{<t}})=\frac{exp(e(x)^Tg_\theta(\mathbf{x}_{z_{<t}}, z_t))}{\sum_{x'}exp(e(x')^Tg_\theta(\mathbf{x}_{z_{<t}}, z_t))} pθ(Xzt=x∣xz<t)=∑x′exp(e(x′)Tgθ(xz<t,zt))exp(e(x)Tgθ(xz<t,zt))
上式中 g θ ( x z < t , z t ) g_\theta(\mathbf{x}_{z_{<t}}, z_t) gθ(xz<t,zt) 表示这是一个新的模型 g g g,并且它的参数除了之前的词 x z < t \mathbf{x}_{z_{<t}} xz<t,还有要预测的词的位置 z t z_t zt。
接下来的问题是用什么模型来表示 g θ ( x z < t , z t ) g_\theta(\mathbf{x}_{z_{<t}}, z_t) gθ(xz<t,zt)。当然有很多种可选的函数(模型),我们这里通过位置 z t z_t zt 来从context x z < t \mathbf{x}_{z_{<t}} xz<t 里通过 Attention 机制提取需要的信息来预测这个位置的词。那么它需要满足如下两点要求:
但是上面两点要求对于普通的Transformer来说是矛盾的无法满足的。因为上面是理解为什么要搞出两个Stream的关键,所以我这里再啰嗦一点举一个例子。
假设输入的句子还是”I like New York”,并且一种排列为 z = [ 1 , 3 , 4 , 2 ] z=[1, 3, 4, 2] z=[1,3,4,2],假设 t = 2 t=2 t=2,我们现在是在计算 g θ ( x z < t , z t ) g_\theta(\mathbf{x}_{z_{<t}}, z_t) gθ(xz<t,zt),也就是给定第一个位置的词为 I 预测第三个位置为New的概率,显然我们不能使用New本身的而只能根据第一个位置的I来预测。假设我们非常幸运的找到了一很好的函数g,它可以能够比较好的预测这个概率 g θ ( x 1 , z 2 ) g_\theta(x_1, z_2) gθ(x1,z2)。现在我们又需要计算t=3,也就是根据 g θ ( x 1 , z 2 ) g_\theta(x_1, z_2) gθ(x1,z2)和 z t z_t zt来预测York,显然知道第三个位置是New对于预测第四个位置是York会非常有帮助,但是 g θ ( x 1 , z 2 ) g_\theta(x_1, z_2) gθ(x1,z2)并没有New这个词的信息。读者可能会问:你不是说g可以比较好的根据第一个词I预测第三个词New的概率吗?这里有两点:I后面出现New的概率并不高;在预测York时我们是知道第三个位置是New的,只不过模型的限制我们没有重复利用这信息。
为了解决这个问题,论文引入了两个Stream,也就是两个隐状态:
下面我们介绍一下计算过程。我们首先把查询隐状态 g i ( 0 ) g_i^{(0)} gi(0)初始化为一个变量w,把内容隐状态 h i ( 0 ) h_i^{(0)} hi(0)初始化为词的Embedding e ( x i ) e(x_i) e(xi)。这里的上标0表示第0层(不存在的层,用于计算第一层)。因为内容隐状态可以编码当前词,因此初始化为词的Embedding是比较合适的。
接着从m=1一直到第M层,我们逐层计算:
g
z
t
(
m
)
←
A
t
t
e
n
t
i
o
n
(
Q
=
g
z
t
(
m
−
1
)
,
K
V
=
h
z
<
t
(
m
−
1
)
;
θ
)
Query流,可以使用
z
t
但不能用其内容
x
z
t
h
z
t
(
m
)
←
A
t
t
e
n
t
i
o
n
(
Q
=
h
z
t
(
m
−
1
)
,
K
V
=
h
z
≤
t
(
m
−
1
)
;
θ
)
Content流,同时使用
z
t
和
x
z
t
上面两个流分别使用自己的Query向量 g z t g_{z_t} gzt和 h z t h_{z_t} hzt;但是Key和Value向量都是用的 h h h,因为 h h h 是内容。但是注意Query流不能访问 z t z_t zt的内容,因此KV是 h z < t ( m − 1 ) h_{z_{<t}}^{(m-1)} hz<t(m−1),这里用的是小于号 < 表示不包括 t t t 时刻的content。而Content流的KV是 h z ≤ t ( m − 1 ) h_{z_{\le t}}^{(m-1)} hz≤t(m−1),它包含 x z t x_{z_t} xzt。
上面的梯度更新和标准的self-attention是一样的。在fine-tuning的时候,我们可以丢弃掉Query流而只用Content流。最后在计算公式的时候我们可以用最上面一层的Query向量 g z t ( M ) g_{z_t}^{(M)} gzt(M)。
下面我们通过下图来直观的了解Two Stream排列模型的计算过程:
图的左上是Content流Attention的计算,假设排列为
3
→
2
→
4
→
1
3 \rightarrow 2 \rightarrow 4 \rightarrow 1
3→2→4→1,并且我们现在预测第1个位置的词的概率。根据排列,我们可以参考所有4个词的信息,因此
K
V
=
[
h
1
(
0
)
,
h
2
(
0
)
,
h
3
(
0
)
,
h
4
(
0
)
]
KV=[h_1^{(0)},h_2^{(0)},h_3^{(0)},h_4^{(0)}]
KV=[h1(0),h2(0),h3(0),h4(0)],而
Q
=
h
1
(
0
)
Q=h_1^{(0)}
Q=h1(0)。
左下是Query流的计算,因为不能参考自己的内容,因此 K V = [ h 2 ( 0 ) , h 3 ( 0 ) , h 4 ( 0 ) ] KV=[h_2^{(0)},h_3^{(0)},h_4^{(0)}] KV=[h2(0),h3(0),h4(0)],而 Q = g 1 ( 0 ) Q=g_1^{(0)} Q=g1(0)。
而图的右边是完整的计算过程,我们从下往上看,首先 h h h 和 g g g 分别被初始化为 e ( x i ) e(x_i) e(xi) 和 W W W,然后Content Mask和Query Mask计算第一层的输出 h ( 1 ) h^{(1)} h(1)和 g ( 1 ) g^{(1)} g(1),然后计算第二层……。注意最右边的Content Mask和Query Mask,我们先看Content Mask。它的第一行全是红点,表示第一个词可以attend to所有的词(根据 3 → 2 → 4 → 1 3 \rightarrow 2 \rightarrow 4 \rightarrow 1 3→2→4→1),第二个词可以attend to它自己和第三个词,……。而Query Mask和Content Mask的区别就是不能attend to自己,因此对角线都是白点。
虽然排列语言模型有很多有点,但是它的计算量很大(排列很多),很难优化。因此我们只预测一个句子后面的一些词,为什么不预测前面的词呢?因为前面的词的上下文比较少,上下文信息相对较少。比如句子”I like New York”。预测I的时候没有任何上下文,因此可能的选择很多。而到最后一个词York的时候,如果New已经知道了,那么York的概率就非常大了。
因此我们把一个排列 z z z分成两个子序列 z ≤ c z_{\le c} z≤c 和 z > c z_{>c} z>c,分别叫做non-target序列和target序列,其中c是切分点。我们会使用一个超参数K,表示 1 / K 1/K 1/K 的Token会被预测,因此根据公式:
∣ z ∣ − c ∣ z ∣ = 1 K \frac{|z|-c}{|z|}=\frac{1}{K} ∣z∣∣z∣−c=K1
可以计算出 K ≈ ∣ z ∣ − c ∣ z ∣ K \approx \frac{\vert z \vert -c}{\vert z \vert} K≈∣z∣∣z∣−c,约等于的原因是因为K是整数。前面c个不用预测的Token,我们不需要计算其Query流,从而可以节省计算时间。
到此为止,XLNet的核心思想已经比较清楚了。主要使用LM,但是为了解决上下文的问题,引入了Permutation LM。Permutation LM在预测时需要target的位置信息,因此通过引入Two-Stream,Content流编码到当前时刻的内容,而Query流只参考之前的历史以及当前要预测位置。最后为了解决计算量过大的问题,对于一个句子,我们只预测后 1 K \frac{1}{K} K1个词。
接下来XLNet借鉴了Transformer-XL的优点,它对于很长的上下文的处理是要优于传统的Transformer的。我们这里只是简单的介绍Transformer-XL,有兴趣的读者可以参考Transformer-XL论文。
尽管 Transformer 最初是为翻译任务而构建的,但最近的趋势表明,它在语言建模上的应用也可以带来显著的效果。但是,为了获得最佳应用,需要对其架构进行一些修改。
为什么?Transformer 有什么问题?
与 RNN 相比,Transformer 的一项重大改进是其捕获长期依赖关系的能力。但是,Transformer 需要存储的中间步骤(梯度)信息比 RNN 要多的多,并且随着序列长度的增加而指数级增加【 O ( n 2 ⋅ d O(n^2·d O(n2⋅d)】。换句话说,如果你试图一次输入整个文档,内存可能会爆炸(BOOM!)
为了防止出现此问题,早期有些做法是将文档分成固定大小的文本段(Segment),一次训练一段。这虽然解决了内存问题,但是破坏了模型捕获长期依赖关系的能力。例如句子 “The daughter had a nice umbrella | that her mother gave her”,如果 “daughter” 和 “her” 属于不同段。那么在编码 “her 时将无法知晓"daughter” 的信息。
我们知道GPT就是使用Transformer来进行语言模型的建模。因为Transformer要求输入是定长的词序列(不像RNN可以处理长度不确定的输入序列),太长的截断,不足的padding,这样我们把一个语料库的字符串序列切分成固定长度的segments。它有下面一些问题:
上图做是普通的Transformer语言模型的训练过程。假设Segment的长度为4,如图中我标示的:根据红色的路径,虽然
x
8
x_8
x8的最上层是受
x
1
x_1
x1影响的,但是由于固定的segment,x_8无法利用
x
1
x_1
x1 的信息。而预测的时候的上下文也是固定的4,比如预测
x
6
x_6
x6时我们需要根据
[
x
2
,
x
3
,
x
4
,
x
5
]
[x_2,x_3,x_4,x_5]
[x2,x3,x4,x5]来计算,接着把预测的结果作为下一个时刻的输入。接着预测
x
7
x_7
x7的时候需要根据
[
x
3
,
x
4
,
x
5
,
x
6
]
[x_3,x_4,x_5,x_6]
[x3,x4,x5,x6]完全进行重新的计算。之前的计算结果一点也用不上。
如何解决这个问题呢?下面就轮到 Transformer-XL 出场了。
首先Transformer-XL是一个语言模型,也就是改进Transformer来根据历史的词预测下一个词。它不同于BERT的Mask语言模型问题,也不同于XLNet使用的排列语言模型。
而Transformer-XL如下图所示:
我们会把之前一个固定长度的词序列每一层的输出都放到一个cache里,比如把
x
1
,
…
,
x
4
x_1,…,x_4
x1,…,x4的计算结果都存起来,那么在训练第二个Segment
[
x
5
,
…
,
x
8
]
[x_5,…,x_8]
[x5,…,x8]的时候就可以让Self-Attention机制参考
[
x
1
,
…
,
x
4
]
[x_1,…,x_4]
[x1,…,x4]的信息了。当然在反向计算梯度的时候,cache里的内容是不会参与梯度的计算的。而在预测的时候,比如右图我们在计算
x
12
x_{12}
x12作为输入的时候,之前那些
[
x
11
,
x
10
,
…
]
[x_{11},x_{10},…]
[x11,x10,…]都不需要重新计算。而普通的的Transformer是需要的,为什么呢?我们仔细看一下上图,在t=12的时候,
x
11
x_{11}
x11可以attend to
[
x
11
,
…
,
x
9
]
[x_{11},…,x_{9}]
[x11,…,x9](而
x
8
x_8
x8被截掉了),而在t=11的时候可以attend to
[
x
11
,
…
,
x
8
]
[x_{11},…,x_{8}]
[x11,…,x8],因此这两个计算结果是不同的,需要重新计算。
根据之前的思路,我们用cache缓存部分历史的状态。虽然计算梯度的时候只使用本segment的信息,但是在forward的时候其实是用到了之前的segment(甚至很久以前的segment,只有cache的空间足够大)的信息,因此它又有点类似于RNN。下面我们形式化的用数学语言来描述状态重用的过程。假设两个相邻的segment为 s τ = [ x τ , 1 , x τ , 2 , … , x τ , L ] s_\tau=[x_{\tau,1}, x_{\tau,2}, …, x_{\tau,L}] sτ=[xτ,1,xτ,2,…,xτ,L]和 s τ + 1 = [ x τ + 1 , 1 , x τ + 1 , 2 , … , x τ + 1 , L ] s_{\tau+1}=[x_{\tau+1,1}, x_{\tau+1,2}, …, x_{\tau+1,L}] sτ+1=[xτ+1,1,xτ+1,2,…,xτ+1,L]。假设segment s τ s_\tau sτ的第n层的隐状态序列为 h τ n ∈ R L × d h_\tau^n \in R^{L \times d} hτn∈RL×d,那么计算segment s τ + 1 s_{\tau+1} sτ+1的隐状态的过程如下:
h
~
τ
+
1
n
−
1
=
[
S
G
(
h
τ
n
−
1
)
∘
h
τ
+
1
n
−
1
]
q
τ
+
1
n
,
k
τ
+
1
n
,
v
τ
+
1
n
=
h
τ
+
1
n
−
1
W
q
T
,
h
~
τ
+
1
n
−
1
W
k
T
,
h
~
τ
+
1
n
−
1
W
v
T
h
t
a
u
+
1
n
=
Transformer-Layer
(
q
τ
+
1
n
,
k
τ
+
1
n
,
v
τ
+
1
n
)
我们看到,
原则上只要 GPU 内存允许,该方法可以利用前面更多段的信息,测试阶段也可以获得更长的依赖(类似于 DenseNet)。
在Transformer中,一个重要的地方在于其考虑了序列的位置信息。在分段的情况下,如果仅仅对于每个段仍直接使用Transformer中的位置编码,即每个不同段在同一个位置上的表示使用相同的位置编码,就会出现问题。比如,第 i − 2 i-2 i−2段和第 i − 1 i−1 i−1段的第一个位置将具有相同的位置编码,但它们对于第 i i i段的建模重要性显然并不相同(例如第 i − 2 i-2 i−2段中的第一个位置重要性可能要低一些)。
Transformer-XL不能像BERT那样使用绝对位置编码,下面我们来分析一些为什么不行。
和前面一样,假设两个相邻的segment为 s τ = [ x τ , 1 , x τ , 2 , … , x τ , L ] s_\tau=[x_{\tau,1}, x_{\tau,2}, …, x_{\tau,L}] sτ=[xτ,1,xτ,2,…,xτ,L]和 s τ + 1 = [ x τ + 1 , 1 , x τ + 1 , 2 , … , x τ + 1 , L ] s_{\tau+1}=[x_{\tau+1,1}, x_{\tau+1,2}, …, x_{\tau+1,L}] sτ+1=[xτ+1,1,xτ+1,2,…,xτ+1,L]。假设segment s τ s_\tau sτ的第n层的隐状态序列为 h τ n ∈ R L × d h_\tau^n \in R^{L \times d} hτn∈RL×d,那么计算公式如下:
h
τ
+
1
=
f
(
h
τ
,
E
s
τ
+
1
+
U
1
:
L
)
h
τ
=
f
(
h
τ
−
1
,
E
s
τ
+
U
1
:
L
)
上式中 E s τ E_{s_{\tau}} Esτ是segment的每一个词的Embedding的序列。我们发现 E s τ E_{s_{\tau}} Esτ和 E s τ + 1 E_{s_{\tau+1}} Esτ+1都是加了 U 1 : L U_{1:L} U1:L,因此模型无法通过向量判断它到底是当前segment的第i个位置还是前一个Segment的第i个位置。注:不熟悉位置编码的读者需要参考Transformer图解。它的基本思想就是给每一个绝对位置一个Embedding,因此模型可以通过这个Embedding猜测它在编码哪个位置的信息,也可以学到某个位置用什么向量来表示更好。
因此Transformer-XL必须使用相对位置编码,它使用了和原始的Transformer使用正弦函数不同的方法。原始的Transformer是把位置信息embedding进去直接加到输入里,而Transformer-XL是在Attention计算的时候利用当前Query和Key的相对位置。
相对位置编码不再关心句中词的绝对位置信息,而是相对的,比如说两个词之间隔了多少个词这样的相对信息。
在标准的Transformer里,同一个Segment的 q i q_i qi和 k j k_j kj的attention score这样分解
A
i
,
j
a
b
s
=
(
W
q
(
E
x
i
+
U
i
)
)
T
⋅
(
W
k
(
E
x
j
+
U
j
)
)
=
(
E
x
i
+
U
i
)
T
W
q
T
W
k
(
E
x
j
+
U
j
)
=
E
x
i
T
W
q
T
W
k
(
E
x
j
+
U
j
)
+
U
i
T
W
q
T
W
k
(
E
x
j
+
U
j
)
=
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
)
其中, E x i E_{x_i} Exi是词 i i i的词向量, U i U_i Ui是词 i i i的位置向量。
(a)(b)(c)(d)四项各有各的意义:(a)表示纯基于内容之间的寻址;(b)和(c)则分别是 i i i位置的内容和位置信息分别相对于 j j j位置的位置和内容信息进行的寻址;(d)则是纯基于位置之间的寻址。于是要改进的话,就需要对后三个和位置信息相关的项进行改进
Transformer-XL给出的改进方案是这样:
Transformer-XL 给出的改进方案是这样:
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)表示内容的计算,也就是 x i x_i xi的Embedding乘以变换矩阵 W q W_q Wq和 x j x_j xj的Embedding乘以 W k , E W_{k,E} Wk,E的内积;(b)表示基于内容的位置偏置,也就是 i i i的向量乘以相对位置编码;(c)表示全局的内容偏置;(d)表示全局的位置偏置。
首先XLNet借鉴了Transoformer-XL的相对位置编码的思想,这个和它基本一样,因此这里不再介绍。另外一点就是cache前一个segment的隐状态。我们假设有两个从原始序列 s \mathbf{s} s里抽取的两个连续Segment, x ~ = s 1 : T \tilde{x}=s_{1:T} x~=s1:T和 x = s T + 1 : 2 T x=s_{T+1:2T} x=sT+1:2T。同时假设 z ~ \tilde{z} z~和 z z z分别是[1,…,T]和[T+1,…,2T]的一个排列。然后根据排列 z ~ \tilde{z} z~的概率分解我们首先计算第一个segment,并且把Content流的隐状态 h ~ ( m ) \tilde{h}^{(m)} h~(m) cache下来,这里 h ~ ( m ) \tilde{h}^{(m)} h~(m)是第m层的Content流的隐状态。那么计算第二个Segment的Content流的方法如下:
h z t ( m ) ← Attention ( Q = h z t ( m − 1 ) , K V = [ h ~ ( m − 1 ) , h z ≤ t ( m − 1 ) ] ; θ ) h_{z_t}^{(m)} \leftarrow \text{Attention} (Q=h_{z_t}^{(m-1)},KV=[\tilde{h}^{(m-1)},h_{z \le t}^{(m-1)}];\theta) hzt(m)←Attention(Q=hzt(m−1),KV=[h~(m−1),hz≤t(m−1)];θ)
上式用自然语言描述就是:为了计算 z t z_t zt 第m层的隐状态,我们使用Attention机制,其中Query是上一次的隐状态 h z t ( m − 1 ) h_{z_t}^{(m-1)} hzt(m−1),而Key和Value除了 z 1 , … , z t z_1,…,z_t z1,…,zt 第m-1层的隐状态,也需要attend to cached上一个segment的所有第 m − 1 m-1 m−1 层的隐状态。
在计算第二个segment时,我们只需要知道隐状态 h ~ ( m ) \tilde{h}^{(m)} h~(m)就可以了,而并不需要知道它是通过哪个排列 z ~ \tilde{z} z~ 计算出来的。这样我们在cache前一个segment时不用考虑它的排列。
许多下游的任务会有多余一个输入序列,比如问答的输入是问题和包含答案的段落。下面我们讨论怎么在自回归框架下怎么预训练两个segment。和BERT一样,我们选择两个句子,它们有50%的概率是连续的句子(前后语义相关),有50%的概率是不连续(无关)的句子。我们把这两个句子拼接后当成一个句子来学习排列语言模型。输入和BERT是类似的:[A, SEP, B, SEP, CLS],这里SEP和CLS是特殊的两个Token,而A和B代表两个Segment。而BERT稍微不同,这里把CLS放到了最后。原因是因为对于BERT来说,Self-Attention唯一能够感知位置是因为我们把位置信息编码到输入向量了,Self-Attention的计算本身不考虑位置信息。而前面我们讨论过,为了减少计算量,这里的排列语言模型通常只预测最后1/K个Token。我们希望CLS编码所有两个Segment的语义,因此希望它是被预测的对象,因此放到最后肯定是会被预测的。
但是和BERT不同,我们并没有增加一个预测下一个句子的Task,原因是通过实验分析这个Task加进去后并不是总有帮助。【注:其实很多做法都是某些作者的经验,后面很多作者一看某个模型好,那么所有的Follow,其实也不见得就一定好。有的时候可能只是对某个数据集有效果,或者效果好是其它因素带来的,一篇文章修改了5个因素,其实可能只是某一两个因素是真正带来提高的地方,其它3个因素可能并不有用甚至还是有少量副作用。】
由于很多下游NLP任务中都包含了多个句子的情况,比如问答任务。下面我们讨论怎么在自回归框架下怎么预训练两个segment。和BERT一样,我们选择两个句子,它们有50%的概率是连续的句子(前后语义相关),有50%的概率是不连续(无关)的句子。我们把这两个句子拼接后当成一个句子来学习Permutation LM。输入和BERT是类似的:[A, SEP, B, SEP, CLS],这里SEP和CLS是特殊的两个Token,而A和B代表两个Segment。与BERT稍微不同,这里把CLS放到了最后。原因是因为对于BERT来说,Self-Attention能够感知位置是因为我们把位置信息编码到输入向量了,Self-Attention的计算本身不考虑位置信息。而前面我们讨论过,为了减少计算量,这里的排列语言模型通常只预测最后1/K个Token。我们希望CLS编码所有两个Segment的语义,因此希望它是被预测的对象,而放到最后肯定是会被预测的
但是和BERT不同,XLNet并没有增加一个预测下一个句子的Task,原因是通过实验分析这个Task加进去后并不是总有帮助。【注:其实很多做法都是某些作者的经验,后面很多作者一看某个模型好,那么所有的Follow,其实也不见得就一定好。有的时候可能只是对某个数据集有效果,或者效果好是其它因素带来的,一篇文章修改了5个因素,其实可能只是某一两个因素是真正带来提高的地方,其它3个因素可能并不有用甚至还是有少量副作用】
BERT使用的是绝对的Segment编码,也就是第一个句子对于的Segment id是0,而第二个句子是1。这样如果把两个句子换一下顺序,那么输出是不一样的。XLNet使用的是相对的Segment编码,它是在计算Attention的时候判断两个词是否属于同一个Segment,如果位置 i i i和 j j j的词属于同一个segment,那么使用一个可以学习的Embedding s i j = s + s_{ij}=s_+ sij=s+,否则 s i j = s − s_{ij}=s_- sij=s−,也就是说,我们只关心它们是属于同一个Segment还是属于不同的Segment。当我们从位置 i i i attend to j j j的时候,我们会这样计算一个新的attention score:
a i j = ( q i + b ) T s i j a_{ij}=(q_i+b)^Ts_{ij} aij=(qi+b)Tsij
其中 q i q_i qi是第 i i i个位置的Query向量,b是一个可学习的bias。最后我们会把这个attention score加到原来计算的Attention score里,这样它就能学到当 i i i和 j j j都属于某个segment的特征,以及 i i i和 j j j属于不同segment的特征。
XLNet和BERT都是预测一个句子的部分词,但是背后的原因是不同的。BERT使用的是Mask语言模型,因此只能预测部分词(总不能把所有词都Mask了然后预测?)。而XLNet预测部分词是出于性能考虑,而BERT是随机的选择一些词来预测。
除此之外,它们最大的区别其实就是BERT是约等号,也就是条件独立的假设——那些被MASK的词在给定非MASK的词的条件下是独立的。但是我们前面分析过,这个假设并不(总是)成立。下面我们通过一个例子来说明(其实前面已经说过了,理解的读者跳过本节即可)。
假设输入是[New, York, is, a, city],并且假设恰巧XLNet和BERT都选择使用[is, a, city]来预测New和York。同时我们假设XLNet的排列顺序为[is, a, city, New, York]。那么它们优化的目标函数分别为:
J
BERT
=
l
o
g
p
(
New
∣
is a city
)
+
l
o
g
p
(
York
∣
is a city
)
J
XLNet
=
l
o
g
p
(
New
∣
is a city
)
+
l
o
g
p
(
York
∣
New
,
is a city
)
从上面可以发现,XLNet可以在预测York的使用利用New的信息,因此它能学到”New York”经常出现在一起而且它们出现在一起的语义和单独出现是完全不同的。
关于训练值得一说的是,和 BERT 一样也是同时构建正例(正确的连续句子)和负例(随机下一句的例子),之后分别对每段进行 Permutation 处理,然后预测,对于正例,后一段会用前一段的信息,而对于负例就不用。
关于训练 loss,XLNet 只用了 PLM 的 loss,却没有像 BERT 一样用 Next Sentence Prediction (下句预测)loss,但是它在句子级别任务表现却不差,对于这个现象感觉非常神奇,按理说应该是会有帮助的。
和语言模型相比,XLNet最大的优势就是通过输入序列的各种排列,同时学习到上下文的信息。
XLNet 整体看起来非常恶心,不如 Transformer 那么简单直白,并且给我一种拆东墙补西墙的感觉(引入了 Permutation,所以没有位置信息了,由此又引入了双流注意力)。XLNet 在 Transformer XL 的基础上引入了随机排列和双流注意力机制,因此使得整个模型变得非常复杂
XLNet 训练总共使用了 126GB 纯文本数据,而 BERT 训练只使用了 13GB 的数据。所以虽说最终成绩 XLNet 超过了 BERT,但究竟是因为数据的帮助,还是模型真的很好呢?
XLNet预训练数据:
和BERT一样,XLNet使用了BooksCorpus和英文的维基百科作为训练数据,这两者总共13GB的文本。此外,XLNet还增加了Giga5(16GB)、ClueWeb 2012-B和Common Crawl的数据来进行Pretraining。对于ClueWeb 2012-B和Common Crawl的内容使用了启发式的规则进行了预处理,最终各自保留了19GB和78GB的文本。使用SentencePiece工具后分别得到2.78B, 1.09B, 4.75B, 4.30B和19.97B Token(subword unit),总计32.89B。
最大的模型XLNet-Large采样了和BERT-large一样的超参数,从而得到类似大小的模型。序列长度和cache分别设置为512和384。训练XLNet-Large是在512核心(不是512个)的TPU v3芯片上进行,使用Adam优化器迭代了500K次。使用了线性的Learning rate decay,batch大小是2048,最终训练了2.5天。我们发现模型仍然是欠拟合(underfitting)的,如果继续训练的话在训练数据上的loss还能下降。但是对于下游的任务并没有太大帮助。因此我们判断是因为数据太大了,默认没有能力完全拟合数据。为了与BERT对比,我们也训练了XLNet-Base模型,它只使用了BooksCorpus和维基百科的数据。
因为引入了递归(recurrence)的机制,我们使用双向的输入pipeline,也就是把一个batch的一半样本正常顺序输入而另一半反向输入。对于XLNet-Large,我们设置K为6,也就是预测1/6的Token。Fine-tuning过程基本是follow BERT。此外我们采样了span-based预测,也就是我们首先采样一个长度L, L ∈ [ 1 , … , 5 ] L \in [1, …, 5] L∈[1,…,5],也就是最少一个Token(1-gram),最多连续5个Token(5-gram)。然后使用长度为KL的上下文来预测这个n-gram。后面的代码分析我们会看到这一点。
RACE数据集,它包含大概100K个问题。它是中国12岁到18岁的学生在初中和高中的英语阅读理解问题。下图是其中一个样例,我们在中学经常做的阅读理解题。
下图是实验结果,我们可以看到XLNet比最好的BERT模型要提升很多。
SQuAD是一个大规模的阅读理解任务的数据集。和前面的选择题不同,SQuAD可以看成问答题,也就是需要从阅读的文章找答案。如下图所示:
SQuAD1.1假设答案是原文的一个连续的一个或者多个词,并且答案是一定存在的。而SQuAD2.0可能会问没有答案的问题。因此为了fine-tuning SQuAD2.0,我们使用了Multi-Task Learning:其中一个损失函数是一个二分类的logistic regression损失函数,它判断有没有答案;而另一个就是标标准的span抽取的损失函数(感兴趣的读者可以参考BERT的论文)。因为v1.1的问题是包含在v2.0里的,因此在打榜的时候我们直接使用v2.0的模型去做v1.1的题目,只是把判断有没有答案的部分去掉(因为v1.1肯定有答案)。另外因为很多参赛者会使用额外的数据,我们也增加了NewsQA的数据作为训练数据。如下表所示,我们的单一的模型(很多好成绩都是好的模型的Ensembling)取得了SOTA的成绩。
我们在IMDB,Yelp-2,Yelp-5,DBpedia,AG,Amazon-2和Amazon-5等文本分类数据集上做了对比实验,结果如下:
GLUE数据集上的实验如下:
ClueWeb09-B是一个文档排序的数据集。它主要用于搜索引擎:给定一个Query,然后给相关的网页排序。下面是实验结果:
因为XLNet引入了很多改进点,包括实验排列语言模型,使用Transformer-XL里的改进,而且还使用了不同的Pretraining数据,为了发现哪些改进是有效的,下面做了Ablation实验,对比的主要是BERT-base和XLNet-base,因为它们的训练数据都是BooksCorpus和Wiki。
从上面的对比实验发现:加上预测下一个句子这个Multi-Task任务在XLNet里并无作用。而去掉memory、span-based的预测和双向的数据时效果都是有所下降的,因此它们都是有用的。
参考资料:
XLNet原理
XLNet代码分析
XLNet代码分析(二)
XLNet代码分析(三)
XLNet代码分析(四)
XLNet 详解
降噪自动编码器(Denoising Autoencoder)
降噪自动编码机(Denoising Autoencoder)
比 BERT 效果更好的 XLNet 详解
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。