[论文笔记]BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding

$\qquad$最近这个模型刚出来,感觉nlp领域的格局大震动,我还是先蹲着看看大家如何讨论以及google会不会又搞什么新花样好了(毕竟这模型也不是谁想跑就能跑起来的……)。持续关注一下,估计几个月内还要更新这篇233

Introduction

$\qquad$目前在nlp领域,pre-trained language model在很多任务中都表现得十分出色。比如,需要对整句分析来判断句子关系的任务:natural language inference(根据前提premise判断假说hypothesis和它的关系:矛盾contradiction or 蕴含entailment)、paraphrasing(复述);token层面需要生成某些特定token的任务:named entity recognition、阅读理解等。

$\qquad$目前将预训练语言表征应用于实际下游任务存在两种策略:基于特征的策略(feature-based)和微调策略(fine-tuning)。基于特征的策略(如 ELMo)使用将预训练表征作为额外特征的任务专用架构。微调策略(如生成预训练 Transformer (OpenAI GPT))引入了任务特定最小参数,通过简单地微调预训练参数在下游任务中进行训练。在之前的研究中,两种策略在预训练期间使用相同的目标函数,利用单向语言模型来学习通用语言表征。

$\qquad$然而,google团队认为现有的的技术完全没有发挥出这两种策略的优势,尤其是fine-tuning。这其中主要是因为现有的language model大多是单向的,每个token只能考虑到它前面词带来的信息,后面的词却被忽略了。比如说在阅读理解这种语境中,上下文都很重要,不能只看上文不看下文。于是作者提出了一种新的预训练模型来克服这种单向局限:masked language model(MLM),它随机将input中的一些词mask掉;然后让模型根据这个被mask词的上下文来预测原词的id(完形填空)。

BERT

Model Architecture - OpenAI_GPT

$\qquad$关于模型结构,BERT完全沿用了Transformer的源码。为了通过比较来突出信息双向利用带来的便利,BERT和OpenAI GPT(generative pre-training)保持高度一致。我们来看一下OpenAI GPT的具体结构:

$\qquad$利用12个transformer block(一个block就是一个multi-head attention+一个feed forward),在不同类别任务中采取不同的输入方式(delim:delimiter,定界符: $, <\s>, <\e>)。GPT采用semi-supervised的方式训练:先用无监督方法pre-train模型(词层面上训练word embedding比较好,句子层面就sentence embedding),再用监督方法train我们需要的结果。具体过程:

Unsupervised pre-training

$\qquad$通过语言模型来训练。假设给定语料(无标签)为$U={u_1,…,u_n}$,设$k$为窗口长度,$P$为条件概率,$\Theta$为网络模型的参数,通过神经网络进行最大似然估计(用前$k$个词预测接下来一个词)$U=(u_{-k,…,u_{-1}})$为一个词对应的context,$n$为transformer的层数,$W_e$为embedding matrix,$W_p$为position embedding matrix:

Supervised fine-tuning

$\qquad$设label集为$C$,每次输入包含多个词语$x^1,…,x^m$,对应label为$y$。记transformer最后一层的activation为$h_l^m$,那么再进一个线性层后得到的概率预测为:

$\qquad$对它加起来求最大似然,就得到了objective function $L_2(C)$。对于利用auxiliary objective的方法,就是将$L_1(C)+L_2(C)$作为目标函数。实际上,我们只需要fine-tune $W_y$ 和eliminater的embedding就可以了。

Model Architecture - BERT

$\qquad$BERT和OpenAI GPT的最大区别在于它用的是双向的数据。(这……不就是把原来的masked multi-head attention中的mask去掉了吗?!)记transformer的block数为$L$,在不同block之间流通时的hidden size为$H$,multi-head中head的数量为$A$,feed-forward中间那一层的大小为$4H$,定义两种模型大小:

  • $BERT_{BASE}:L=12,H=768,A=12,Parameters=110M$
  • $BERT_{LARGE}:L=24,H=1024,A=16,Parameters=340M$

Input Representation

$\qquad$可见输入主要由三部分相加而成,分别为1. 原词的word embedding(word piece, 最长512词,多句时所有句子加起来不超过512词);2. Segment embedding用来分开不同的句子(或者可以在不同句子之间加分隔符来区分);3. 通过神经网络学习到的position embedding。

Pre-training Tasks

Masked LM

$\qquad$这一节主要讨论的是,用什么任务去pre-training这个模型,能够得到更好的效果。在OpenAI GPT中用的是language model,通过前面的词预测下一个词。但是这种模型在这里却不适用了,因为标准的language model只能是从左往右或从右往左,预测下一个词,而无法同时双向预测。因此我们考虑盖住文本中的一个词(用[mask]这个token代替被遮盖词),让模型通过两侧的语境做完形填空。

$\qquad$然而这种方法有两个缺点:

  • 在真正训练的时候,不会出现[mask]这样的文本。为此作者把需要被mask的词按照80%概率变成[mask],10%概率变成另一个随机词,10%的概率不变来处理。对于transformer来说,它并没有被告知到底哪个词是被mask掉的,所以它必须学习每个单词的替换可能性。
  • 在每个batch中只有15%的词会被预测,这导致它收敛得会更慢一些,需要更多的训练次数。不过总体来说这种方法还是利大于弊。

Next Sentence Prediction

$\qquad$对于需要输入多句话的任务,采用“预测下一句是什么”的方法,如果是原本的下一句则label为IsNext,如果不是(从语料库中随机选句)则label为NotNext。正负label占比为1:1,最终训练准确率为97%-98%。以下为label的示例:

Input = [CLS] the man went to [MASK] store [SEP]

he bought a gallon [MASK] milk [SEP]

Label = IsNext

Input = [CLS] the man [MASK] to the store [SEP]

penguin [MASK] are flight ##less birds [SEP]

Label = NotNext

Pre-training Procedure

$\qquad$如上所述,补充了一些细节:用英文wiki训练,optimizer=Adam,用了gelu而不是relu等;

$\qquad$补充:由于relu缺乏probabilistic interpretation,有人提出了GELU(Gaussian Error Linear Unit),定义为$GELU(x)=xP(X<x),X~N(\mu, \sigma^2)$,在多个数据集中表现好于RELU和ELU。顺带一提RELU大名:Recitified Linear Unit。示意图如下:

Fine-tuning Procedure

$\qquad$同补充一些细节,同时提到:fine-tuning真的很快,而且大数据集需要tune的更少,对parameter更不敏感。