本文提出了一种语言表征模型BERT(Bidirectional Encoder Representations from Transformers)。它使用了一个深度、双向模型,用无标签的文本数据作为输入,来预训练一个文本的表征。BERT模型在模型的每一层中都使用了文本的上下文信息(双向)。在预训练的BERT模型后面可以接一个全连接层进行特定任务的微调训练。实验结果显示,在11个NLP任务上,BERT都可以达到现有的最高水平(18年)。

文章目录

  1. 引言
  2. 背景
  3. 正文
    1. 模型结构
    2. 输入输出表征
    3. 预训练
      1. MLM
      2. NSP
      3. 训练数据
    4. 微调 (fine-tune)
  4. 实验结果
    1. GLUE基准测试结果
    2. 不使用NSP、仅使用单向语言模型对比
    3. 不同参数性能差异
  5. 结束语
  6. 引用

引言

本文提出了一种语言表征模型BERT(Bidirectional Encoder Representations from Transformers)。它使用了一个深度、双向模型,用无标签的文本数据作为输入,来预训练一个文本的表征。BERT模型在模型的每一层中都使用了文本的上下文信息(双向)。在预训练的BERT模型后面可以接一个全连接层进行特定任务的微调训练。实验结果显示,在11个NLP任务上,BERT都可以达到现有的最高水平(18年)。

背景

预训练语言模型被证明可以有效改善许多NLP任务的性能。目前在下游任务上,它主要有两种应用策略:基于特征和基于微调。类似于ELMo的这种基于特征的方法,将预训练语言模型的输出特征作为额外的输入,输入到特定任务的模型中去。而基于微调的方法(比如GPT),可以让训练下游任务时,仅引入少量的任务特定的新的参数,在训练过程中只需要对整个模型的进行微调就可以。这两种方法目前都使用了单向(仅使用上文或下文信息)语言模型来学习通用语言表征。

文中认为,这些方法限制语言模型的能力,尤其限制了基于微调的方法。由于标准的语言模型是单向的,这就限制了模型架构的选择。比如在OpenAI的GPT中,作者使用了left-to-right的架构,也就是每一个token只能“看”到这个token之前的内容,而看不到token之后的内容。这种限制对于句子级别的任务来说不是最优的,在一些需要双向上下文的任务中(比如问答任务)这种方法更不行。

本文提出了一种基于微调方法的预训练语言模型BRET来解决前文提到的单向问题。

正文

BERT框架分为两个步骤:预训练和微调。预训练时,模型使用无标签的文本数据(覆盖很多任务)进行训练;在微调中,BERT模型首先加载预训练好的模型,然后所有的参数都使用带标签的数据进行微调训练。每一类任务的微调模型都使用同样的预训练模型进行初始化,但是它们使用单独不同的模型结构。

模型结构

BERT的模型是一个多层、双向的Transformer编码器结构,Transformer的实现结构和原论文[2]中的结构几乎一样(但是它只使用了编码部分的模型,没有解码部分)。没有了解过Transformer的同学先去看下Transformer注解 [3] [4]。文中给出了两种不同大小的BERT模型参数:

Base版为了与GPT进行比较,模型大小设计为何其一样。

输入输出表征

为了让BERT可以处理各类下游任务,数据输入既可以表示单个句子,也可以表示一个句子对。这里的句子指的是任意长度的连续文本,而不是传统语义上的句子。

BERT使用了WordPiece方法对数据进行处理,该方法可以将单词进行拆分,比如playing会拆分为play和$\#\#ing$ 。BERT中包含了30000个token。

每一个输入的句子总是以一个特定的token开头,也就是$[CLS]$。这个token的最终隐状态会作为整个句子的表征来进行分类任务的微调。句子总是以一个特定的token结尾,也就是$[SEP]$。如果输入由一对句子组成,那么句子之间会插入$[SEP]$。

和原始Transformer输入不同的是,BERT的输入由三部分嵌入$(embedding)$组成:

  • Token 的嵌入:将一个token映射到相对应的一个高维表示。
  • Segment嵌入:这个嵌入只有两个元素 (0, 1),0表示第一个句子的嵌入,1表示第二个句子的嵌入。也就是这个用于区分两个句子。该嵌入也是通过训练得到。
  • 位置嵌入:每一个位置会有一个编码,比如最长序列为512词,那么会对应一个512行的数据,每一行对应一个位置的嵌入编码。

输入的一个示意图如下:

句子输入

从上图我们可以看出输入的嵌入$E_{input} = E_{token} + E_{segment} + E_{position} (E 表示 embedding)$。

我们用$C \in \mathbb{R}^H$表示$[CLS]$对应的输出向量($H$为隐层维度),使用$T_i\in \mathbb{R}^H$表示第$i$个token的输出隐层向量。

预训练

BERT使用两个任务的来对模型进行预训练:

  • 遮蔽语言模型 (Masked Language Model, MLM)
  • 下句预测 (Next Sentence Prediction, NSP)

MLM

语言模型是给定一个单词序列来预测下一个单词的任务。而在MLM任务中,并不是预测下一个token,而是将token序列中的一部分遮蔽掉,然后仅去预测这些被遮蔽的token。

为了训练一个双向的表征,文中将输入句子中$ 15\% $的token随机进行掩盖(使用[MASK]进行替换),替换策略为:

  1. $80$%确实使用$[MASK]$进行替换
  2. $10$%使用随机的token进行替换
  3. $10$%保持不变

NSP

下句预测任务是一个二分类的任务,给定一对句子,如果这两个句子是出自同同一段话的上下连续的两个句子那么标签为,否则为。文中BERT训练数据中有$50\% $的数据为连续句子,$50$%为非连续的。文中使用$C$也就是$[CLS]$对应的隐层输出作为NSP任务的输入来进行分类任务的微调训练。

在预训练中引入NSP,对于问答任务(QA)和自然语言推理(NLI)任务很有帮助。

训练数据

文中使用了两个数据集:

  • BooksCorpus (大概8亿词汇)
  • 英语维基百科(25亿词汇)

微调 (fine-tune)

如何使用BERT进行微调非常直观。$BERT$可以使用单个句子或者两个句子作为输入。对于不同的任务,两个句子代表不同含义,比如:

  1. 一段文本中的一个句子对
  2. 蕴含关系推断任务中的假设文本和前提文本
  3. 问答任务中的问题与段落
  4. 文本分类任务或序列标记任务中的(文本-$\emptyset$),即单个句子输入

对于token级别的任务来说,可以使用所有的$token$的隐层输出作为微调层的输入来进行微调训练;对于分类任务来说,可以用$[CLS]$对应的隐层输出作为微调层的输入来进行微调训练。

实验结果

本节我们给出一些实验结果,具体结果可以参考论文。

GLUE基准测试结果

GLUE基准测试

我们可以看到$BERT_{LARGE}$模型在各个任务上的表现都是最好的。

不使用NSP、仅使用单向语言模型对比

结果比较

No NSP表示不使用NSP任务进行预训练。LTR表示仅使用单向语言模型进行训练,比如GPT。+BiLSTMLRT & NoNSP模型的基础上,微调的时候,在后面连接了一个随机初始化的双向LSTM层。

从结果我们可以看到NSP的引入对于$MNLI/QNLI/SQuAD$任务影响比较大;添加双向LSTM层虽然对原来的模型性能有所改善,但是还是比不上$BERT_{BASE}$。

不同参数性能差异

不同超参数差异

其中$L$为层数,$H$为隐层维度,$A$为自注意力机制头数量。显然参数越多性能越好。

结束语

BERT 是NLP领域的一个突破,它让很多NLP任务都可以利用预训练的模型进行微调来达到较好的效果。对于实现细节感兴趣的同学可以去看源码[5]。

引用

[1] Devlin, Jacob, et al. "Bert: Pre-training of deep bidirectional transformers for language understanding." arXiv preprint arXiv:1810.04805 (2018).

[2] Vaswani, Ashish, et al. "Attention is all you need." arXiv preprint arXiv:1706.03762 (2017).

[3] The Illustrated Transformer, http://jalammar.github.io/illustrated-transformer/

[4] The Annotated Transformer, http://nlp.seas.harvard.edu/2018/04/03/attention.html

[5] https://github.com/google-research/bert


[本]通信工程@河海大学 & [硕]CS@清华大学
这个人很懒,他什么也没有写!

1
507
0

更多推荐


2022年11月30日