11. BERT 论文笔记

​ BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding ,一种从Transformers模型得来的双向编码表征模型。

Abstract

​ BERT: 是Bidirectional Encoder Representations from Transformers 的缩写。

特点:

  • 不像其它模型,BERT是基于所有层的左右上下文来预训练来自未标定文本的深层双向表示向量。
  • 基于BERT得到的向量,加上一个输出层,微调下就能得到很多任务的最优模型,如:问答和语言推理,无需对特定任务架构做大量的修改。

成绩:刷了11个语言任务的榜单, 包括一下:

  • pushing the GLUE score to 80.5% (7.7% point absolute improvement),
  • MultiNLI accuracy to 86.7% (4.6% absolute improvement),
  • SQuAD v1.1 question answering Test F1 to 93.2 (1.5 point absolute improvement)
  • and SQuAD v2.0 Test F1 to 83.1 (5.1 point absolute improvement).

1. Introduction

​ 预训练语言模型已被证明对许多自然语言处理任务能有效提升。其包括语言推理和释义paraphrasing,

  • token-level task: token级别的任务. 如完形填空(Cloze), 预测句子中某个位置的单词; 或者实体识别; 或是词性标注; SQuAD等.

  • sequence-level task: 序列级别的任务, 也可以理解为句子级别的任务. 如情感分类等各种句子分类问题; 推断两个句子的是否是同义等.

    ​ ——NLP任务

预训练语言表征应用于下游任务有两种现有策略:基于特征和微调。

基于特征的方法:如ELMo, 使用特定架构包括预训练表示作为附加特征。

微调方法:如GPT , 引入最小的特定任务参数,并通过简单微调所有预训练参数在下游任务上进行训练。

在预训练中,两种方法共享相同的目标函数,它们使用单向语言模型来学习通用语言表示特征

作者认为现在技术严重制约了预训练表示的威力,特别是微调方法。主要限制在于标准语言模型是单向的,这限制了在预训练期间可以使用的架构。例如, 在OpenAI GPT中,作者使用了从左到右的架构,其中每个token仅仅只能注意到Transformer中self-attention层的之前token。这种局限对于句子级别任务是次要的,但是对于token-level级别的任务是毁灭性的,当微调方法应用于token-level任务,如QA,结合两个方向的上下文至关重要。

在本文中,作者提出基于微调方法的BERTBidirectional Encoder Representions from Transformers.

通过使用“掩码语言模型” MLM(masked language model) 预训练目标,BERT 缓解了之前方法单向限制。MLM随机掩码一些来自输入的tokens,目标是只看其上下文来预测掩码词在原来词汇表中的id。不像从左到右的预训练语言模型,MLM目标能够表示融合左右上下文,这允许作者预训练一个深层双向Transformer.除了MLM, 作者还使用“预测下一句”任务来联合预训练文本表示向量。

本文贡献如下:

  • 证明了双向预训练对语言表示的重要性。
  • 展示了预训练表示能减少了对于许多繁重工程任务特定架构的需要。BERT首次在大型句子级和词汇级任务上,微调基于表示模型就取得了SOTA表现,并且优于许多特定任务的架构
  • BERT打破了11项NLP任务的最佳纪录

2. 相关工作

2.1 基于特征的非监督方法

​ 学习广泛合适的词表示已经成为近十年来活跃领域,包括非神经网络和神经网络方法。预训练词嵌入是现代NLP系统的必不可少的部分,比从零开始嵌入训练提供显著的改进。为了预训练词嵌入向量,从左到右语言模型目标已经被使用,从左到右上下文中判别词的正确与否。

这些方法已经被推广到更广的粒度,像句子嵌入或段落嵌入。为了训练句子表示,先前工作把对候选下一个句子排序作为目标,从左到右给定前面句子的表示生成下一个句子词汇,或去噪自编码派生目标。

ELMo和其前身沿着不同维度生成传统词嵌入。它们从左到右和从右到左语言模型提取“文本敏感”的特征。每个字符上下文表示是从左到右和从右到左表示合并。当合并上下文词嵌入和已有的特定任务架构时,ELMo推动了几个主要NLP基准的最新进展,包括QA,情感分析,命名实体识别。

2.2 非监督微调方法

​ 与基于特征方法一样,这个方向第一个工作是只从未标记文本预训练词嵌入参数。

最近,句子和文档编码生成上下文字符表示的编码器已经被从未标记文本中预训练得到, 并且微调给监督学习的下游任务使用。这些方法的优势是很少需要从零开始学习参数。至少部分归于这个优点,OpenAI GPT 之前在许多来自GLUE基准测试的句子级别任务获得了最佳成绩。从左到右语言模型和自动编码器目标已经被用于预训练这些模型。

2.3 来自监督数据的迁移学习

​ 许多工作表明从大型数据集的监督任务上做迁移学习是十分有效的,像语言推理和机器翻译。机器视觉研究也证明从预训练模型上使用迁移学习的重要性,一个有效的技巧是微调预训练在ImageNet上的模型。

3. BERT

​ 本节介绍BERT和其详细实现。使用BERT框架有有两个步骤:pre-training 和fine-tuning. 在预训练阶段,模型在不同任务的未标记数据上预训练。对于微调,BERT模型首次用预训练好的参数初始化,并且所有参数是使用基于下游任务标记的数据来微调。每个下游任务有独立的微调模型,尽管它们用同样的预训练参数初始化。图1中,QA例子作为本节运行的一个示例。

202203261843624

注:

  • [CLS] 是添加在每个输入示例之前的特殊符号,
  • [SEP]是分隔字符,比如分隔问题/答案

一个BERT的区分特征是它的跨任务统一架构。其在预训练和最终下游任务的区分特别小。

模型架构

BERT模型架构是多层双向基于原本实现的Transformer编码器,及其发布的tensor2tensor库(现在已遗弃)。因为使用Transformers已经变得普遍和作者的实现和原本的Transformer几乎一样,就不详述了,可以看原文和 The Annotated Transformer。(本博客也有Transformer笔记)。

这里注释下标记的意思:

  • L:是层数,即Transformer 块的数目
  • H:隐藏单元的维数
  • A: 自注意头数

比如:$ \text{BERT}_{\text{BASE}} $代表 L=12, H=768, A=12总共参数为110M

​ $ \text{BERT}_{\text{LARGE}} $代表 L=24 H=1024, A=16总共参数为340M

$ \text{BERT}_{\text{BASE}} $设定和OpenAI GPT模型大小相同, 以便做比较。Transformer使用双向self-attention,而GPT使用限制的自注意,每个token仅注意它左边上下文。

输入/输出表示

为了是BERT处理多种下游任务,作者输入表示在一个字符序列上能任意表示单一句子和一对句子。通过这个工作,一个句子可以是任意长度的连续文本,而不是实际语义上句子。一个句子指输入到BERT的token序列,其可能是单一的句子或者是两个句子打包在一起。

作者使用30,000词汇表的WordPiece embeddings。每个序列第一个token都是一个特殊的token ([CLS]). 与此标记对应的最终隐藏状态用作分类任务聚合序列的表示。句子对被打包成一个序列,作者用两种方法区分句子。

  1. 用特殊字符([SEP])分开这个句子对
  2. 增加一个可学习的嵌入到每个词中,用来区分该词属于句子A还是句子B

如上图1所示,$ \boldsymbol{E} $表示输入嵌入,$ \boldsymbol{C} \in \mathbb{R}^H $表示[CLS]token的最终隐藏向量,第$i $

个输入词的最终隐藏向量是$\boldsymbol{T}_i \in \mathbb{R}^H $.

对于给定token,其输入表示由对应token,片段, 和位置嵌入构成,可视化其构成如下图2. 具体来说,就是[CLS]表示下一句是否为上一句真正的下一句(可以随机从语料中抽一个句子作为下一句),这就是BERT第一个任务预测下一句。[SEP]表示分割token。整个BERT输入由3部分叠加:

  • Token Embedding: 将序列打断称为词或更小单位的token
  • Segment Embedding: 分隔两个句子,用来Next sentence predict,如下图中句子A和B之间用[SEP]分隔
  • Position Embedding:不再用原始的sin/cos​函数,而是学习得到。

例如 Pytorch BERT 实现中,BERT Embedding就是三者相加。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class BERTEmbedding(nn.Module):
"""
BERT Embedding which is consisted with under features
1. TokenEmbedding : normal embedding matrix
2. PositionalEmbedding : adding positional information using sin, cos
2. SegmentEmbedding : adding sentence segment info, (sent_A:1, sent_B:2)
sum of all these features are output of BERTEmbedding
"""

def __init__(self, vocab_size, embed_size, dropout=0.1):
"""
:param vocab_size: total vocab size
:param embed_size: embedding size of token embedding
:param dropout: dropout rate
"""
super().__init__()
self.token = TokenEmbedding(vocab_size=vocab_size, embed_size=embed_size)
self.position = PositionalEmbedding(d_model=self.token.embedding_dim)
self.segment = SegmentEmbedding(embed_size=self.token.embedding_dim)
self.dropout = nn.Dropout(p=dropout)
self.embed_size = embed_size

def forward(self, sequence, segment_label):
#embedding层 就是 Token+Segment+Position
x = self.token(sequence) + self.position(sequence) + self.segment(segment_label)
return self.dropout(x)

image-20210427172624924

如上所示,输入有 A 句「my dog is cute」和 B 句「he likes playing」这两个自然句,作者首先需要将每个单词及特殊符号都转化为词嵌入向量,因为神经网络只能进行数值计算。其中特殊符 [SEP] 是用于分割两个句子的符号,前面半句会加上分割编码 A,后半句会加上分割编码 B。

​ ——引用[7]

3.1 预训练BERT

​ 不像Peter等,作者不使用传统从左到右或者从右到左语言模型来预训练BERT。相反,作者预训练BERT使用两个无监督学习任务,这节会描述。这部分如图1的左半部分。

任务 # 1: Masked LM 直觉上,有理由详细双向模型完全比从左到右模型或者浅层连合从左到右和从右到左的模型更有效果。不幸的是,标准条件语言模型仅能从左到右或者从右到左训练,因此双向状态会让每个词直接看到自己(本身是将其作为标签的无监督训练,这样一来就出现了标签泄漏),并且模型可以在多层上下文中毫无顾虑地预测目标词。

standard conditional language models can only be trained left-to-right or right-to-left, since bidirectional conditioning would allow each word to indirectly
“see itself”, and the model could trivially predict the target word in a multi-layered context.

为了训练深层双向表示,作者简单地随机掩码一些百分比的输入,然后预测这些掩码字符。作者定义这个步骤为MLM,尽管其在文献里经常被定义为完形任务。在本例,遍历整个词汇表,对应掩码字符的最终隐藏状态向量被喂进一个输出softmax,像标准LM一样。在实验中,随机的在每个序列上,掩码15%的所有WordPiece 字符。对比降噪自编码器,作者仅预测掩码词而不是重构整个输入。

尽管这允许作者获得双向预训练模型,其带来的负面影响是在预训练和微调之间造成不匹配,因为[MASK]字符不经常出现在微调中。为了缓解这个问题,作者不总是替换“掩码”词为[MASK]字符,而是训练数据生成器随机选择15%的token位置来预测。假如第i个字符被选中,作者有80%情况下是用[MASK]替换,10%的情况下用一个随机字符替换,还有10%情况下不变。然后(第i个词的最终隐藏向量)将用来采用交叉熵损失来预测原本字符。如附录C.2。

例如,在my dog is hairy 这句话中,它选择 hairy。然后执行以下步骤:

  • 数据生成不会总是用 [MASK] 替换被选择的单词,而是执行以下操作:

  • 80% 的情况下:用 [MASK] 替换被选择的单词,例如,my dog is hairy → my dog is [MASK]

  • 10% 的情况下:用一个随机单词替换被选择的单词,例如,my dog is hairy → my dog is apple

  • 10% 的情况下:保持被选择的单词不变,例如,my dog is hairy → my dog is hairy。这样做的目的是使表示偏向于实际观察到的词。

    ​ ——BERT翻译

任务 # 2:下一个句子预测任务(Next Sentence Prediction NSP)

许多重要的下游任务如QA和NLI都基于理解两个句子的理解,但是这不是直接被模型捕获到的。为了训练模型理解句子关系,作者预训练了一个二元的下一个句子预测任务,能从任何单语语料中简单生成。具体来说,对于每个预训练例子选择句子A和B时,50%的时候句子B是句子A的真正下一句(标记为IsNext), 而另外50%的句子B是从语料中随机抽取的句子(标记为NotNext).如图1所示, C被用来预测下一句(向量C没有微调的话不是一个有意义的句子表示)。尽管其是简单的,在5.1中作者证明,增加这个任务预训练对QA和NLI都有比较好的效果。尽管先前的工作,只有句子嵌入被迁移到下游任务,BERT迁移所有参数来初始化最终任务模型参数。

预训练数据

预训练过程很大程度上遵循已有语言模型预训练文献。预训练语料使用了BooksCorpus(800M 词汇)和英文维基百科(2500M 词汇)。对于维基,作者只提取文本信息,忽略列表和表格以及标题。为了提取长连续序列,关键是使用文档级别语料库,而不是无序句子级别语料。

3.2 微调BERT

​ 微调是简单的因为Transformer的自注意里机制允许BERT通过交换合适的输入和输出来为许多下游任务建模——无论是单个文本还是文本对。对于涉及文本对的应用,常见模式是在应用双向交叉注意力之前,独立地编码文本对。BERT取代其使用自注意里机制来统一这两个阶段,当用自注意力有效地编码串联的文本对,这就包含了两个句子的双向交叉注意力。

对于每个任务,作者简单地连接特定任务的输入和输出喂进BERT,端到端微调所有参数。

  • 在输入中,句子A和句子B从预训练类似于(1)在段落中的句子对,(2)蕴含中的前提-假设对,(3)问题回答任务中的问题-文章对,(4)文本分类中的text-∅对。
  • 在输出中,对于字符级别任务,字符表示被喂进到输出层,例如序列标注或QA,而为了分类[CLS]表示被喂进输出层,如需求或情感分析。

对比预训练,微调相对代价小些。论文所有结果,从相同的预训练模型开始,在TPU大概1小时能被复现,或者在GPU上几小时复现。作者在小节4中描述具体任务细节,在附录A.5可以找到更多细节。

4. 实验

​ 本节展示了BERT在11项具体微调任务微调结果。

4.1 GLUE

​ 通用语言理解估计(General Language Understanding Evaluation : GLUE)基准是多种语言理解任务。GLUE数据集详细描述在附录B.1.

GLUE上的微调,作者表示输入句子(句子或句子对)如第3部分描述的,用最后的隐藏向量$ C \in \mathbb{R}^H $ 对应第一个输入字符([CLS]) 作为总的表示。在微调时,只有分类层的权重$ W \in \mathbb{R}^{K\times H} $ 新参数引入,这里K是标签的数目。作者用C和W来计算标准分类损失如()。

  • 作者使用batch_size大小为32,遍历所有数据,为所有GLUE任务微调3轮。对于每个任务,作者在验证集上选择最佳微调学习率[ 在5e-5, 4e-5, 3e-5, 和2e-5之间 ]。
  • 另外,对于 ,作者发现在小数据集上微调有时不稳定,所以随机重新开始跑几次,选择在验证集上最好的模型。对于随机重启,作者使用一样的预训练节点,但执行不同的微调打乱数据并且分类层初始化。

image-20210428004212040

结果如上表1所示,在所有任务上,通过巨大的界限所有的BERT都优于现有系统,与之前最佳水平相比,获得对应的平均准确性4.5%和7.0%的提升。

注意和OpenAI GPT的模型结构几乎相同,区分在于使用了掩码注意力。对于大型和最广泛使用的GLUE任务 MNLI, BERT比当前模型取得了4.6%的绝对准确性提升。在GLUE官方排行榜,取得了80.5分数,对比OpenAI GPT相比,截止本文写作时只取得了72.8.

作者发现 在所有任务上显著优于,尤其是小训练集。更多模型大小影响探索在5.2节。

4.2 SQuAD v1.1

​ Stanford Question Answering Dataset (SQuAD v1.1) 是一个由100k个一堆问题/答案对构成的数据集。给定一个问题和一段包含答案的维基段落,任务是预测这段答案的区间。

如图1所示,QA任务,作者表示输入问题和段落打包成一个序列,对于问题用A的嵌入,段落用B的嵌入(图1中)。作者在微调时只引入一个开始向量$S \in \mathbb{R}^H$和结束向量$ E \in \mathbb{R}^H$ 。作为答案开始区间单词$ i $的概率是由$T_i$和S之间的点积并除以段落中所有词结果再过softmax:

同样的式子用来计算单词作为答案区间结束的概率。作为候选区间位置i到位置j定义为:$S \cdot T_i + E \cdot T_j$,并将满足$j \ge i $最大分数作为预测结果。训练目标是正确答案开始和结束位置的对数似然的和。微调3轮,学习率为5e-5, batch size为32.

image-20210428200949428

表2展示了问答任务中的排名前几位的模型,因此,作者使用适度的数据增强,首先对TriviaQA进行微调,然后再对SQuAD进行微调。 BERT在集成模型上比排名第一的系统高出+1.5 F1,在单个系统上比排名第一的系统高出+1.3 F1

4.3 SQuAD v2.0

​ SQuAD 2.0任务拓展了 v1.1的问题定义,允许在提供的段落中没有短答案存在的可能性,使得问题更合理。

使用简单方法来拓展v1.1 BERT 模型来完成这个任务。将没有答案的问题看作其答案开始和结束都在[CLS]字符。 在预测是,作者比较无答案区间分数: $ S \cdot C + E \cdot C $ 和 最好的无答案区间

时,作者预测没有答案,这里$ \tau $阈值在验证集上选择使得F1最大化。作者这个模型不使用TriviaQA数据。微调两轮,学习率为5e-5, batch size为48.

结果和之前排行榜比较如表3,包括将BERT作为其中组件的系统。作者发现+5.1 F1改进比之前最佳系统。

image-20210428213327589

4.4 SWAG

​ 对抗生成情形The Situations With Adversarial Generations (SWAG),数据集包含113k 句子对完整实例,用于评估常识推理。给定一个句子,任务是在四个选择中选最合理的延续。

当在SWAG上微调时,构建四个输入句子,每个包含给定句子串(句子A)和可能的延续(句子B)。引入特定任务唯一的参数是一个向量,它与[CLS]字符做点积得到表征C表示每个选择的分数,该分数再过softmax层归一化。

微调模型3轮,学习率为2e-5,batch size=16,结果在表4。 优于作者baseline ESIM+ELMo系统有+27.1%, OpenAI GPT 8.3% 。

image-20210428235933430

5. 消融研究

​ 在本节, 在BERT的许多方面执行消融实验,来理解BERT各个部分的相对重要性。消融研究在附录C可以被找到。

5.1 预训练任务的影响

​ 通过评估两个预训练目标来证明BERT的深层双向重要性,它们使用同样的预训练数据,微调方案和跟 超参数。

NO NSP: 双向模型,使用“掩码 语言模型”(MLM)训练,但是没有预测下一句任务。

LTR&No NSP :一个只注意左边上下文的模型,使用标准的从左到右语言模型训练,而不是MLM。只注意左边的约束也应用到微调,因为没有它,引入到预训练/微调不匹配会退化下游任务表现。 另外,这个模型是没有NSP任务的预训练。这能直接跟OpenAI GPT对比,但使用作者的大型训练数据,输入表示和微调方案。

首先分析NSP任务带来的影响。在表5中,展示了移除nSP对QNLI, MNLI和SquAD的表现造成显著的不良影响。接下来,比较“No NSP”和“LTR&No NSP”来评估训练双向表示方面的影响。在所有任务上,LTR模型表现比MLM差,在MRPC和SQuAD退化很大。

image-20210429005634711

对于SQuAD,直觉上LTR模型将在字符预测上表现差劲,因为token-level隐状态没有右边的上下文。为了对增强LTR系统做出最大的尝试,在BiLSTM的顶部进行随机初始化。在SQuAD上有显著的提升,但结果仍然比预训练的双向模型要差。BiLSTM在GLUE任务上是有害的。

安排分开的LTR和RTL模型预训练,然后两个方法表示每个字符并连接起来,就像ELMo一样。然而:

  • (a) 比单向模型参数多2倍
  • (b) 对于QA这样的任务来说是不直观的,因为RTL模型没有以问题为条件作为打哪
  • (c) 这比深层双向模型要弱得多,因为其可以在每层选择使用左边右边上下文
5.2 Effect of Model Size

​ 在本节,探索模型大小在微调任务上准确性的影响。用不同层数、不同隐藏单元、不同注意力头训练BERT模型,但其有跟前面描述的同样的超参数和训练流程。

在选择的GLUE任务上结果如表6所示。表中,从5个随机重启点微调记录平均验证集准确性。可以看到大模型在四个数据集都有明显的准确性提升,即使MRPC(Microsoft Research Paraphrase Corpus)仅有3600个标记的训练样本,其显著不同于预训练任务。也许令人惊讶的是,相对于现有文献中模型,能在现有基础上取得如此显著的提升。例如,最大Transformer探究是(L=6, H=1024, A=16),100M参数的encoder。文献中找到的最大Transformer是(L=64, H=512, A=2)使用235M 参数。相比之下, 含有110M参数,和含有340M参数。

多年来人们知道增大模型大小将持续提升在大型任务上的表现,如机翻和语言建模,由表6所示的留存训练数据的LM困惑度可以证明。然而,作者相信,这是第一次证明,提供充分的预训练,将模型提升到极端规模也能在小任务上取得提升。

image-20210429152541635

Peters (2018b) 表示在下游任务混合结果,将受增加预训练双向bi-LM从两层到四层的影响,并且 Melamud (2016)提到增加隐藏层维度从200到600也是有益的,但再增加到1000不会带来提升。所有先前的工作都基于特征方法——作者假设当模型微调后直接在下游任务是要,并且其使用非常骚随机初始化附加参数,特定任务模型能从大型更昂贵的预训练表示上获益,即使下游任务数据集很小。

5.3 基于特征方法使用BERT

​ 到现在为止所有BERT结果都是使用微调方法,将一个简单分类层加到预训练模型中,并且所有参数都在下游任务上联合训练。然而,基于特征方法,从预训练模型提取固定特征,有一定的优点。

  • 首先,不是所有任务都是容易被Transformer 编码器架构表示,因此特需要加上定任务模型架构。
  • 其次,预先计算一个昂贵的训练数据表示,然后在这种表示上运行多种更便宜模型的许多实验,还是有计算优势的。

在本节,在CoNLL-2003命名实体识别任务上用BERT方法比较了两种方法。BERT输入中,使用保留大小写的WordPiec模型,并且包括通过数据提供的最大文档上下文。遵循标准实践,将其表示为标记任务,但在输出中不使用CRF层。作者使用第一个子字符的表示作为字符级别分类器遍历NER标签集的输入。

为了切除这种微调方法,使用基于特征的方法,从一层或多层中提取激活信息,而不用微调BERT任何参数。上下文嵌入被用作输入,来随机初始化在分类层前面的两层768维BiLSTM。

结果如表7所示。$ \text{BERT}_{\text{LARGE}} $ 跟最新方法表现的有竞争力。最好表现的方法连接了预训练Transformer顶部四个隐藏层字符表示,这比整个模型微调值只落后的0.3 F1。证明了对于BERT微调和基于特征的方法都是有效的。

image-20210429173034443

6 结论

​ 最近,归功于用语言模型迁移学习实验表现提升已经证明了,丰富的、无监督预训练是许多语言理解系统的不可分割的一部分。实际上,这些结果允许低资源任务从双向架构中获益。本文主要贡献是进一步推广这些发现到深层双向架构,允许同样预训练模型来处理广泛的NLP任务。

​ 至于附录部分,就不翻译整理了,引用[3]比较详细。

引用

[1] The Illustrated BERT, ELMo, and co

[2] BERT model for anwsering TOEIC reading test

[3] BERT:预训练的深度双向 Transformer 语言模型

[4] Bert 论文阅读笔记

[5] BERT:语言理解的深度双向变换器预训练

[6] BERT论文解读

[7] 谷歌终于开源BERT代码:3 亿参数量,机器之心全面解读

[8] BERT 文字解释