预训练模型--BERT演绎

1,147 阅读18分钟

1. ELMO (2018.2.15)

Elmo是基于双向LSTM,使用经典语言模型的思路训练的。需要先在大量语料上pre-train,可以得到所谓deep contextualized的词向量,然后通过特定的方法结合在不同的NLP任务中。

1.预言模型

对于一个N个词的序列(t1,t2,...,tN)(t_1, t_2, ..., t_N),是通过已知序列(t1,t2,...,tt1)(t_1, t_2, ..., t_{t-1})来计算tkt_k的, 所以一个前向的预言模型得到每个token的概率公式如下: image_1e3pat1rvm519ujbbq1sb0ihg9.png-5kB 依据上述预言模型,将一句话(每个token用传统独立的word-embedding表示)使用LL层的LSTM,便可以得到context-independent 的representation。 在这个LL层的LSTM中,tkt_k对应的token representation有 hk,jLM,j=1,,,Lh^{LM}_{k,j}, j=1,,,L。LSTM的顶层输出 h^{LM}_{k,L}使用一个Softmax层来预测下一个词$$t_{k+1}。 上述是前向的LSTM,反向的LSTM是相同的思路: image_1e3pbm5439anl4v1o4na4n1u5bm.png-5.8kB 训练的时候同时最大化前向和后向的似然概率。 image_1e3pboj5f1dsf9rd1salgeck0c13.png-12.2kB 其中词向量与Softmax层参数是共享的,前向LSTM和后向LSTM训练各自的参数。

2.Elmo

对于一个LL层的双向LSTM,每个token tkt_k可有有2L+12L+1各向量表示: image_1e4uq2dbg1tm31ce8luj17si1mqi9.png-8.5kB 对每一层,hk,jLMh^{LM}_{k,j} 等于j层前向和后向向量concat在一起得到。

ELMO将多层的biLSTM的输出整合为一个向量ELMok=E(Rk;θe)ELMo_k=E(R_k;\theta_e),最简单的情形是,ELMo只使用顶层的向量 E(Rk)=hk,LLME(R_k)=h^{LM}_{k,L}

但是,据称最好的ELMo模型是将所有biLSTM的输出加上normalized的softmax学出来权重,这个有点想attention的原理。 image_1e4ure6h31i1t7881o46qvu679m.png-9.8kB

其中stask=softmax(w)s^{task}=softmax(w), γ\gamma是缩放因子,相当于把做使用stasks^{task}之前对每一层biLSTM用了layer normalization: image_1e4urn6kt7t21vuf1l0j164910d313.png-97.7kB

3.接入下游任务方法

(1)直接将ELMo词向量ELMokELMo_k与普通的词向量xkx_k拼接(concat)[xk;ELMok][x_k;ELMo_k]。 (2) 直接将ELMo词向量ELMokELMo_k与隐层输出向量 hkh_k 拼接 [hk;ELMok][h_k;ELMo_k],在SNLI,SQuAD上都有提升。

2. GPT, GPT2.0, GPT3.0

GPT是比Bert更早的预训练预言模型,也是pre-train+fine-tuning模式的开创作品。但是GPT的各个版本都是用的单向预言模型。并且使用transfomer解码器。

  • GPT1.0

image_1e9sktf1417qehss166s1qhq1sb6m.png-218.5kB

如上图所示,GPT模型结构就是由12个Transformer解码器堆叠而成。 在fine-tuning阶段的模型输入,使用Start,Delim, Extract拼接。

  • GPT 2.0 模型结构和预训练方式预GPT1.0本质上相同。不同处:
  1. 使用更大的语料和质量更好的语料。
  2. zero shot的实验设置,不在强调使用fine-tuning.
  3. 更大的模型。
  • GPT 3.0 几个关键点:
  1. 更大的模型
  2. 不在需要fine-tuning
  3. 使用Few-shot的实验设定效果最好。
  4. 任然是用Transformer实现的单向预言模型。

2. BERT (2018.10.11)

Bert是使用Transformer作为组件,同时在两个supervised的任务上联合训练、收敛。这两个任务是预测Mask词和预测两句话关系,第一个任务可以看作模型学习token-level的信息,并且是双向的。第二个任务是学习sentence-level甚至doc-level的信息。下面分层来讲解:

  1. Input/Output Representations

representations 使用一个sentence-pair {A ,B} 来构造输入,用[SEP]来连接,并以[CLS]开头,[CLS]其对应的最后一层的hidden state可以用来做句子分类任务。构造一个input representation使用三层的编码的和:

  • WordPiece embeddings来构造token embedding
  • 用来表示某个token属于句子A还是句子B,称作Segment Embedding。
  • position embeddings,学习出来的embedding向量。
  1. Pre-training BERT
  • 2.1 Pre-training Task 1#: Masked LM(masked language model)

因为传统的 conditional language models只能 left-to-right 或者right-to-left的学习,所以,为了训练得到一个双向的表征,BERT简单的随机掩盖(mask)一些token,然后只预测被掩盖的词, 这个就被称为Masked LM。

因为下游的任务不会有[MASK]这个标识。所以这会在pre-training和fine-tuning之间存在mismatch,所以作者采用的mask策略是: 不是总用[MASK]替换掩盖的token,在训练数据中,随机选取15%的token进行预测,然后分别用80%[MASK],10%随机token,10%自己来替换第i个token。其他解释参考:appendix-A

然后使用交叉熵(cross entropy loss)使用最后一层的隐变量TiT_i,来预测原始的token。这个任务的loss记作masked_lm_loss。

注意:masked_lm_loss只预测被mask的token,而不预测其他token。

  • 2.2 Pre-training Task 2#: Next Sentence Prediction

因为很多下游的任务,比如QA,NLI都是需要学习sentence-level之间的关系。所以,BERT的另一而任务是进行一个二分类的下一个句子预测任务(Next Sentence Prediction,NSP)。 在构造训练数据时,50%的句子对{A,B}是IsNext关系,另外50%是NotNext关系。 这个任务的loss记作next_sentence_loss。

然后联合训练,最终的loss是两个任务loss的和: total_loss = masked_lm_loss + next_sentence_loss

  1. Fine-tuning

在预训练之后,模型的输出,token representation再经过一层网络进行token-level的任务,比如:实体标注,mrc等。头部的 [CLS] representation,用来进行分类任务,比如:情感分析,句子继承关系预测等。 当然,不同的任务需要自定义不同的loss函数,比如:

  • GLUE 使用开头的token[CLS],它的representaton记作CC, 分类那层的网络权重记作WW。然后使用一个标准的分类任务loss:log(softmax(CWT))log(softmax(CWT))

  • SQuAD v1.1 构造输入A是question,B是passage。然后引入两个向量,开始位置向量SRHS\in\mathbb{R}^H和结束位置向量ERE\in\mathbb{R}. 第i个word的representation记作TiT_i,则它作为答案start下标的概率分布是: Pi=eS.TijeS.TjP_i= \frac{e^{S.T_i}}{ {\sum_{j}{e^{S.T_j}}}} 答案的end下标概率分布使用相同的公式。 则候选答案span(从位置i到位置j)概率为:STi+ETjS·T_i + E·T_j。最大得分的score并且同时满足j>=ij>=i,最为最终的预测结果。 训练目标是正确start和end的log-likelihoods和。

paper, code

BERT适合的场景

  • 解决句子或者段落的匹配类任务
  • 在语言本身中就包含答案,而不特别依赖文本外的其它特征
  • Bert比较适合解决输入长度不太长的NLP任务
  • Bert的适用场景,与NLP任务对深层语义特征的需求程度有关。越是需要深层语义特征的任务,越适合利用Bert来解决

3. RoBERTa(2019.7.26)

RoBERTa(a Robustly Optimized BERT Pretraining Approach)是改进的BERT。这篇文章主要做的几点工作:

  1. 静态Masking vs 动态Masking

    原来Bert对每一个序列随机选择15%的Tokens替换成[MASK],为了消除与下游任务的不匹配,还对这15%的Tokens进行(1)80%的时间替换成[MASK];(2)10%的时间不变;(3)10%的时间替换成其他词。但整个训练过程,这15%的Tokens一旦被选择就不再改变,也就是说从一开始随机选择了这15%的Tokens,之后的N个epoch里都不再改变了。这就叫做静态Masking。 而RoBERTa一开始把预训练的数据复制10份,每一份都随机选择15%的Tokens进行Masking,也就是说,同样的一句话有10种不同的mask方式。然后每份数据都训练N/10个epoch。这就相当于在这N个epoch的训练中,每个序列的被mask的tokens是会变化的。这就叫做动态Masking。 那么这样改变是否真的有效果?作者在只将静态Masking改成动态Masking,其他参数不变的情况下做了实验,动态Masking确实能提高性能。 image_1e9smpgfq1ti3u431ng9hbi11jv9.png-17.3kB

  2. with NSP vs without NSP

  3. 更大的mini-batch

  4. 更多的数据,更长时间的训练

4. AlBert (2019.12.26)

AlBert的主要探索在于如何减少参数、缩减模型,模型缩减了训练以及predict的时间都会减少,当然表现不能降低。 在一般的Bert网络中,令词典的embedding大小为EE,encoder layer为LL, 隐层大小为 HH, 然后设置feed-forward/filter size 为4H4H, attention的head数量为H/64H/64。 AlBert与Bert的模型主结构不变,主要进行了三点改进:

1.Factorized embedding parameterizatio

在Bert以及之后的一下改进工作,比如XLNet和RoBERTa中,WordPiece的词向量大小EE是与隐层大小HH有关联的,比如EE常等于HH。这种设置,也许不是必须的。作者认为,WordPiece的词向量是学习*语境独立(context-independent)的表征,而隐层向量是学习语境相关(context-dependent)*的表征。而Bert类模型的优势在于从语境中获取信号来学习与语境无关的表征,因此,将 WordPiece 词嵌入大小EE 从隐藏层大小HH分离出来,这样可以更高效地利用总体的模型参数, 其中HH远远大于EE

如果字典大小是 VV,那Bert类的模型的embedding矩阵大小是VEV*E,这回轻松达到十亿级别的参数量。

所以,Albert想要打破 EEHH之间的绑定关系,从而减小模型的参数量,同时提升模型表现。

在AlBert中,对embedding的参数进行因式分解(factorization),将其分解为两个更小的矩阵。不是将one-hot的向量直接映射到EE大小的隐向量,在AlBert中,先将其映射到EE大小的embedding,然后再放进隐层。就是将embedding matrix分解为两个分别为VEV*EEHE*H矩阵。这样就可以embedding向量从O(VH)O(V*H) 变成 O(VE+EH)O(V*E + E*H),当HH远大于EE时,参数的减少是非常显著的。

Bert 上面图表示BERT的One-hot向量输入,第一次投影是词与词之间是没有交互的(context independent)。只有到了做Attention时,词与词之间才有交互(context dependent)。因此第一次投影不需要很高维度的向量。 AlBert 而上图的AlBert中,可以把第一次的映射放到很低的维度,然后在context中做attention时,再放大到大维度。而NLP训练模型的vocab通常是很大的,所以第一次one-hot vector映射到embedding参数会很多。这样做有两个好处:

  1. 参数大大减小
  2. 词的Context independent表示与Context dependent表示之间解锁,可以自由的对Context dependent表示进行加高,也就是网络变宽

2.Cross-layer parameter sharing

有几种参数共享的方法可以选择,比如只共享层间前向网络的参数(feed-forward network,FFN),只共享attention的参数。而AlBert采用的策略是共享层间所有参数。

3.Inter-sentence coherence loss

Bert中使用两种loss,一个是masked_lm_loss,另一个是next_sentence_loss。有一篇文章讨论去掉next_sentence_loss,发现模型表现并没有太多影响。 所以作者猜想next_sentence_loss作用甚微的原因是,这个任务太过简单,模型只需要学习到两个句子主题不同就可以,且与MLM重复,导致Bert学习到的几乎都是来自MLM。所以,AlBert采用sentence-order prediction (SOP)loss,训练数据的构造与Bert相似,从同一篇文档中取出连续的两句话,作为正例子,相同的两句话调换顺序,作为负例。挺玄学的。

分析:

  1. 效果:AlBert比Bert只是在large以上的版本会比Bert好,比如 xlarge、xxlarge 。
  2. 速度:在predict阶段(前向传播),AlBert和Bert在同一版本几乎没有区别,严格来说,Albert还要更慢些,因为,AlBert的Embedding还要做一个矩阵分解的运算。所以,AlBert不能带来预测速度的提升

paper

5. ELECTRA (2020.4.23)

Bert使用的语言模型是MLM,即它随机mask 15%的token,然后训练模型来预测masked位置的token。而后Bert之大训练之难大家都知道,这篇ELECTRA借鉴了GAN的思路来搭建模型。Bert中是只预测被masked位置的token,这个任务太过简单(上一篇AlBert是觉得Next Sentence Prediction ,看来对Bert的改进就是让任务更难,必先苦其心志,劳其筋骨,饿其体肤,,)。那么如何引入一个更难的任务呢?它首先使用MLM模型,作者称为Generator,来改写一句话,就是对MASK位置替换成一些token,然后使用另一个网络,作者称为Discriminative,来预测句子中每个token是否被替换(序列标注问题)。 作者称这个任务叫做replaced token detection

image_1e6gen6gl1l70er1q5b1evs1ri99.png-31.3kB

  1. Pre-training

模型结构如上图,Generator和Discriminator就是Bert编码器。在pre_training阶段,G和D一同训练,在fine_tuning阶段,G保持不变,只有D进行参数更新。

对于输入:x=[x1,...,xn]x = [x_1,..., x_n],编码得到向量:h(x)=[h1;...,hn]h(x) = [h_1;..., h_n]

在pre_training阶段,因为无法在Generato和Discriminator中间进行back-propagate,所以实际上左右两个网络是独立训练的:

  • Generator

左边的Generator网络,就是标准的MLM,在所有[MASK]位置计算预测token的概率,对于位置kk, Generator生成token xtx_t的概率是: image_1e6gjelir1srg183o1k9s841ac39.png-10.8kB

loss定义为: image_1e6gksc391dst1mhksq91er512ca13.png-9.4kB

  • Discriminator

使用的训练sample,论文里称为corrupted example xcorruptx^{corrupt},是使用Generator替换maskted-out的token生成的。 然后让Discriminator预测xtx_t有没有被替换: image_1e6gjmma6q2vkb711r7rl7mo1m.png-6.2kB

右边Disc的loss定义为: image_1e6gkt76lu3t1321jq16sgs751g.png-14.7kB

  • loss

最终的训练模式是将两个loss加权相加: image_1e6gkv07k1uston91ge4eus5em1t.png-8.6kB 因为判别器的任务相对来说容易些,RTD loss相对MLM loss会很小,因此加上一个系数,作者训练时使用了50。

paper code 参考: 1

6. XLNet (2019.6.19)

作者将目前市面上的两种预训练模式定义为AR(autoregressive)和AE(autoencoding)。 AR模式有ELMO和GPT,它的问题是采用的单向的预言模型来预测,虽然ELMO使用两个方向的语言模型,但是效果还是很差。 AE模式,比如BERT,通过Masked LM可以很好的实现双向语言模型,但是存在两个问题:1. [MASK]字符只在pre-train中有,但是在fine-tuning中是不存在的,所以这造成了两个阶段的偏差。 2. BERT的假设是预测的tokens之间完全独立,这个与自然语言往往具有长依赖来说就太简单了。比如预训练时输入:“自然[Mask][Mask]处理”,目标函数其实是 p(自然处理)+p(自然处理)p(语|自然处理)+p(言|自然处理),而如果使用AR则应该是 p(自然)+p(自然语)p(语|自然)+p(言|自然语)。这样下来BERT得到的概率分布也是基于这个假设的,忽略了这些token之间的联系

所以XLNet提出了方案,相比较BERT,有三点改动:

  1. 使用 Permutation Language Modeling。作者提出two-stream attention来实现。
  2. 借鉴Transformer-XL的思想,更适用于长文本,所以在SQuAD任务上表现更好。
  3. 不再使用NSP(Next Sentence Prediction)任务。XLNet采用Relative Segment Encoding,只判断两个token是否在一个segment中,而不是判断他们各自属于哪个segment
  4. 更大更好的语料。

XLNet实现

  1. Permutations 对于序列 x = [This, is, a, sentence],序列长度是TT,则组合数量是T!T!个。比如,当给定前面两个,计算第三个位置token的概率时。假设有三个组合: [1, 2, 3, 4], [1, 2, 4, 3] 和 [4, 3, 2, 1] ,则它对应的概率就是:Pr(a,This,is)Pr(a,|This,is),Pr(sentence,This,is)Pr(sentence,|This,is)Pr(is,sentence,a)Pr(is,|sentence,a)。 所以,XLNet的目标函数,就是在所有组合上进行AR预言模型,最大化单方向预测的组合似然概率: image_1e9picl3cpdr1ndbov3107jf2j1a.png-19.1kB
  2. Attention Mask

模型解决token的order问题,在transformer中,是将position-embedding与word-embedding相加,同时作为输入。比如,Pr(Thisis+2)Pr(This|is+2)。但是,在XLNet中,序列的次序是已经被打乱,所以使用这种相对位置就错误了。 这里使用attention mask来实现,比如对于组合[3,2,4,1],模型计算第一个位置,即'a',的概率,因为前面没有token,所以是没有语境,则它对应的掩码是[0,0,0,0]。 同理可以得到这个组合的掩码矩阵: [0111001000000110]\begin{bmatrix} 0 & 1 & 1& 1 \\ 0 & 0 & 1& 0 \\ 0 & 0 & 0& 0 \\ 0 & 1 & 1& 0\end{bmatrix} 另一种表示是(-表示这个位置是mask了): Pr(This,is+2,a+3,sentence+4)Pr(This|-,is+2,a+3,sentence+4) Pr(is,,a+3,)Pr(is|-,-,a+3,-) Pr(a,,,)Pr(a|-, -,-,-) Pr(sentence,is+2,a+3,)Pr(sentence|-,is+2,a+3,-)

  1. Two-stream self-attention

这是还需要考虑一个问题:我们不仅需要计算语境中预测某个位置token的条件概率,还需要知道模型正在预测的是哪个位置。也就是想计算:Pr(This1,is+2)Pr(This|1,is+2), this是1st1^{st},is是2st2^{st}的概率。但是Transformer是直接把位置embedding与word embedding加到一起的,也就是:Pr(ThisThis+1,is+2)Pr(This|This+1,is+2)。但是在XLNet中,因为token顺序被打乱,所以模型不知道This是1st1^{st},甚至不知道This是不是在序列中。 解决方案是使用two-stream self-attention mechanism,在m层,每个ii位置的token,使用两个向量来表示:himh^m_igimg^m_ihh的初始化是word-embedding+position-embedding,而gg的初始化,是一般的embedding+position-embedding。hh是在content stream中更新,就是常规的self-attention,使用Q,K,V来更新。gg在query stream中更新,使用未mask部分的content vector作为K和V,上一层的它自己作为Q来更新。

下图展示了,在mm层,g4mg^m_4是如何更新的: image_1e9pt040n141j3jda421tuj101s1n.png-72.1kB

再会看论文中的例子和图: 对于一个输入序列(1,2,3,4),如果想要计算一个组合(3,2,4,1),通过掩码矩阵边可以实现,但实际上他的输入序列还是(1,2,3,4) 通过这个掩码计算的是:p(12,3,4)p(1|2,3,4), p(23)p(2|3), p(3)p(3|), p(42,3)p(4|2,3),也就是可以实现计算组合(3,2,4,1)。实际上就标准的self-attention。XLNet就是以这种方式,在构建预言模型的时候,同时“读到”后面的token。

image_1e9pep7bc1na3vq10e012qi1cqsm.png-111.5kB

图中掩码矩阵,红点表示不掩盖的部分。

参考1 Transformer 中self-attention以及mask操作的原理以及代码解析

7. SpanBERT (2019.7.24)

相比较Bert,SpanBERT的改变主要有两点:

  1. MLM,不在随机Mask,而是每次mask掉一个区间的所有token,而这个区间的长度和起始位置都是随机选择的。
  2. 不再使用NSP任务(Next Sentence Prediction ),代替使用SBO(Span Boundary Objective)任务。

image_1e6qlnkmea0a1t4f10721dmh7dh9.png-48.7kB

上面图介绍了SpanBERT的训练模式。“an American football game”这个区间被mask掉,SBO使用区间两边token的隐层向量(x4x_4x9x_9)来预测span中的每个token。上图就是在预测football时,MLM和SBO两个任务的loss说明,其中football是span中的第三个tokne,他的位置向量是p3p_3

1.mask span

对于一句输入,迭代构造mask输入,当mask的部分达到15%,结束这个过程。每次选择的span长度和span起始位置都是随机的,其中span长度服从几何分布,并且最大长度只能是 10。作者通过实验确定,当 p=0.2时表现最好,这时span的平均长度为3.8。

在Bert中,对于所有需要mask的token,会用[MASK]替换80%的词,10%的词随机替换成其他词,10%的词保持不变。在SpanBERT采用相同的策略,只不过它作用于每个span。

2.SBO task

当mask的span为(xs,...,xe)(x_s, . . . , x_e),其中(s,e)(s,e)表示span的起始和结束位置,SBO任务就是用span两边token的representation (Xs1X_{s-1}, Xe+1X_{e+1}),来预测span中的每个token。当要预测ii位置的token的: image_1e6qn7pgn1citn4qndbob11ff0m.png-4.5kB

其中位置向量是相对于(s,e)(s,e)的相对位置, f()f(·)就是使用一个简单的双层神经网络。

image_1e6qo4bgatvuaj9lkflott269.png-17.9kB

然后使用i位置的向量表示yiy_i来预测xix_i,loss为计算交叉熵。

3.loss

前面连个任务的loss相加。 image_1e6qokuia144f12k71nhl7n2jhum.png-11.9kB

4.实施

  1. 位置向量使用200维的向量。
  2. 输入使用更长的sentence。

5.实验和分析

image_1e6qoutsqiim1q5jiebtpv12qv9.png-99kB

  1. SpanBERT 尤其在抽取式问答上表现好。
  2. 舍弃掉 NSP 的一段长句训练普遍要比原始 BERT 两段拼接的方式要好。

6.参考

paper

8. Bert-WWM

Bert-WWM(Whole Word Masking)与Bert的区别,是在mask方式的区别。在英文语料中,句子的分隔使用WordPiece,就是将较长的单词分割,分别进行mask(在字典中使用“##token”来表示token是分隔的部分)。在中文Bert中,一般就直接在token_level进行 mask。而Bert-WWM是在将句子分词后,mask 某个token,同时mask这个token所在词语的其他token,模型输入还是在token级别。下面的例子更清楚:

说明样例
原始文本使用语言模型来预测下一个词的probability。
分词文本使用 语言 模型 来 预测 下 一个 词 的 probability 。
Bert的Mask结果使 用 语 言 [MASK] 型 来 [MASK] 测 下 一 个 词 的 pro [MASK] ##lity 。
Bert-WWM的Mask结果使 用 语 言 [MASK] [MASK] 来 [MASK] [MASK] 下 一 个 词 的 [MASK] [MASK] [MASK] 。

然后其他方面与Bert都一样。

看一样他在LCQMC上的实验结果: image_1e6jcg5461sdt1r716m36i1e429.png-38.8kB

9. ERNIE (2019.3)

首先百度的RENIE与BERT的模型结构没有区别,区别在于它mask的词不是完全随机的,而是利用了图谱的知识。按照论文的说法,这样mask,ERNIE 直接对语义知识进行建模,增强了模型语义表示能力

  1. 不一样的mask方式

    image_1e9vklebr1no0b841b8ilgtp41m.png-42.6kB image_1e9vkmt811q6m1n141tfj18r71qip1g.png-48.2kB

    如图,bert只是mask单个token,而ERNIE采用了三种mask方式,分别是token,entity,phrase。

  2. 引入DLM学习对话 image_1e9vkvuajnat18521cdp7tf1a0n1t.png-58kB ERNIE 还引入了论坛对话类数据,利用 DLM(Dialogue Language Model)建模 Query-Response 对话结构,将对话 Pair 对作为输入,让模型来学习判断当前的多轮对话是真实的还是假的。。

10. ERNIE 2.0

引入多任务学习。 引入了多大7个任务来fine-tuning模型(不是在预训练阶段),并且采用的是逐次增加任务的方式来预训练

image_1e9vl34qopif30u4e1u0d12pd2a.png-101.4kB