文章目录
1.前言
- 监督学习:给定训练数据
x
和 标签y
。使得Model
对x
的输出越接近y
越好 - 自监督学习:没有标签
y
,我们将数据分成两份,使得Model
对其中一部分的输出越接近另一部分越好
BERT 就是自监督学习,利用非 Mask 的来预测 Mask 的部分
2.Bert(Bidirectional Encoder Representations from Transformers)
源自Transformers
的双向编码表示。主要包含两个部分,预训练和 Fine-tuning
2.1主要预训练任务
2.1.1.完形填空
- 随机选择一些输入进行遮挡
- 被遮住可以是将字换成了
MASK
:一个特殊的字符,代表被盖住,不在字典里出现 - 可以是利用字典中的其他字随机替换
- 被遮住可以是将字换成了
- 被盖住的字输出的结果经过一个线性层,然后做
softmax
得到结果,这个结果和真实字的one-hot
编码越接近越好
2.1.2.预测下一个句子
[CLS]
放在一个序列的最前面,没有特别具体的语义。我们通过[CLS]
对应的输出,来判断两个句子是不是连接在一起的。
2.2预训练
2.2.1.输入表示
原文说:我们的输入表示能够在一个 token 序列中明确表示单个句子 和 一对句子。一个“句子”可以是连续文本的任意跨度,而不是一个实际的语言句子。
上图是论文中的示例。比如输入的一个序列包含两个句子,”my dog is cute”,”he likes playing”
。
- 我们在序列的最前面加上一个特殊的 Token
[CLS]
,其在最后一个隐藏层的隐藏状态被当做整个序列的聚合表示,从而应用于分类任务 - 在一个句子的末尾加上一个
[SEP]
表示一个句子的结束,以区分开不同的句子
我们在进行了分词,添加了特殊 Token 之后的序列作为模型的输入。
接着对每个Token进行3个Embedding:词的Embedding,Segment的Embedding和位置的Embedding
- 对词的 Embedding 就是将词表示成向量,使用
WordPiece embedding
- Segment Embedding 就是给词打上标签,代表其属于哪个句子。这里使用的是学习好的 Embedding
- 位置的 Embedding 就是对其位置进行编码
2.2.2.MLM(Mask Language Model)
BERT 使用的是 MASK 语言模型。Mask语言模型有点类似与完形填空——给定一个句子,把其中某些词遮挡起来,让模型猜测可能的词。
BERT 对输入序列随机进行 15% Mask,然后预测这些被遮住的 Token。通过调整模型的参数使得模型预测正确的概率尽可能大。
但是这有一个问题:在 Pretraining Mask LM 时会出现特殊的Token [MASK],但是在后面的fine-tuning时却不会出现,这会出现Mismatch的问题。为了减轻这种不匹配,在BERT中,如果某个Token在被选中的15%个Token里,则按照下面的方式随机的执行
- 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,就是不变
2.2.3.NSP
在有些任务中,比如问答,前后两个句子有一定的关联关系,我们希望BERT Pretraining的模型能够学习到这种关系。因此BERT还增加了一个新的任务——预测两个句子是否有关联关系。
这通过为 BERT 添加一个任务来实现:我们预训练了一个二分类的 是否是下一个句子
的任务。
当选择句子 A
和 B
作为预训练样本时,B
有 50% 的概率是 A
的真实的下一句,也有 50% 的概率是随机的一句。
比如下面两个句子是相关的
[CLS] the man went to [MASK] store [SEP] he bought a gallon [MASK] milk [SEP]
下面两个句子是不相关的
[CLS] the man [MASK] to the store [SEP] penguin [MASK] are flight ##less birds [SEP]
2.2.4.总体架构
BERT的架构是多层的双向 Transformer encoder。这将使得我们能够获取双向的语义信息,而不是像传统方法那样,只能从左向右或者从右向左来获取单向的语义信息。
我们定义层数(Transformer blocks)为
L
L
L,hidden size 为
H
H
H ,self-attention 的头的个数为
A
A
A。一共提供了两版 BERT
-
B E R T B A S E ( L = 12 , H = 768 , A = 12 ) BERT_{BASE}(L=12, H=768, A=12) BERTBASE(L=12,H=768,A=12) ,总参数量为 110M
- BASE 版本的模型大小和 OpenAI GPT相同,只不过使用了双向的 self-attention
-
B E R T L A R G E ( L = 24 , H = 1024 , A = 16 ) BERT_{LARGE}(L=24,H=1024,A=16) BERTLARGE(L=24,H=1024,A=16),总参数量为 340M
E
代表 对输入进行 Embedding 的结果C
是[CLS]
在最后一个隐藏层对应的隐藏状态T
是其它位置对应的隐藏状态
2.3.Fine-tuning
Fine-tuning是简单的,因为Transformer中的 self-attention 机制提供了 BERT 对许多下游任务进行建模的能力,无论他们包含单个文本还是文本对。我们只需要替换掉输入和输出就好了。
对于每个任务,我们只需将特定于任务的输入和输出插入到BERT中,并对所有参数进行端到端微调。
在输出端,token 表示被输入到输出层用于 token 级任务,如序列标记或问题回答,而[CLS]
表示被输入到输出层用于分类,如逻辑蕴涵和情感分析
-
对于相似度计算等任务,输入是两个序列,如任务
(a)
那样。我们用第一个特殊的 Token[CLS]
的最后一层输出,接上softmax
进行分类,用分类的数据来进行Fine-tuning
-
对于普通的分类任务,输入是一个序列。像任务
(b)
那样。我们用第一个特殊的 Token[CLS]
的最后一层输出,接上softmax
进行分类,用分类的数据来进行Fine-tuning
-
第三类是问答类问题(如
(c)
所示),输入是一个问题和一段很长的包含答案的文字,输出在这段文字中找到的答案。我们首先将问题和Paragraph
表示成一个很长的序列,中间用[SEP]
分开,这里假设答案是Paragraph
中一段连续的文字(Span)。BERT把寻找答案的问题转化成寻找这个Span的开始下标和结束下标的问题。对于Paragraph的第i个Token,BERT的最后一层把它编码成 T i T_i Ti,然后我们用一个向量S(这是模型的参数,需要根据训练数据调整)和它相乘(内积)计算它是开始位置的得分,因为Paragraph的每一个
Token
(当然WordPiece
的中间,比如##ing
是不可能是开始的)都有可能是开始可能,我们用softmax
把它变成概率,然后选择概率最大的作为答案的开始类似的有个向量
T
,用于计算答案结束的位置 -
第四类任务是序列标注,比如命名实体识别,输入是一个句子(Token序列),除了
[CLS]
和[SEP]
的每个时刻都会有输出的Tag,比如B-PER表示人名的开始。然后用输出的Tag来进行Fine-Tuning
,如任务(d)
所示