一.简介
Bert是什么?
BERT,全称是 Bidirectional Encoder Representation from Transformers,基于语义理解的深度双向预训练Transformer。BERT能够同时利用前后两个方向的信息,而ELMo和GPT只能使用单个方向的。
要理解 Bert,5 个关键词帮你理解其思想,分别是Pre-training、Deep、Bidirectional、Transformer、Language Understanding。
Deep
Bert 与 Transformer 不同,Bert 的神经网络层更深,意味着它能更准确表达语义的理解,提取更多特征。
Bidirectional
BERT 被设计成一个深度双向模型,使得神经网络更有效地从第一层本身一直到最后一层捕获来自目标词的左右上下文的信息。
传统上,我们要么训练语言模型预测句子中的下一个单词( GPT 中使用的从右到左的上下文),要么训练语言模型预测从左到右的上下文。这使得我们的模型容易由于信息丢失而产生错误。
Transformer
Bert 是基于 Tranformer 的深度双向语言表征模型,也就是利用Transformer结构构造了一个多层双向的Encoder 网络。它的特点之一就是所有层都联合上下文语境进行预训练。
Bert 的目标是生成预训练语言模型,所以只需要Encoder机制。Transformer的Encoder是一次性读取整个文本序列,而不是从左到右或者从右到左按顺序读取。
Pre-training
pre-training 的意思是,作者认为,确实存在通用的语言模型,先用大量数据预训练一个通用模型,然后再微调模型,使其适用于下游任务。为了区别于针对语言生成的 Language Model,作者给通用的语言模型,取了一个名字,叫语言表征模型Language Representation Model。
深度学习就是表征学习,大多只在预训练表征微调的基础上加一个线性分类器作为输出就可以完成下游任务。
Language Understanding
Bert 是一个语言表征模型,能实现语言表征目标训练,通过深度双向 Transformer 模型达到语义理解的目的。
整合以上特点,我们就可以很直观的理解 Bert,Bert 是一个用 Transformer 作为特征抽取器的深度双向预训练语言理解模型。Bert 就是一个预训练模型,利用双向 Transformer,通过大量数据训练一个语言表征模型,这是一个通用模型,通过对其微调来适用下游任务,包括分类,回归,机器翻译,问答系统等等任务。
2.工作原理
Bert 的模型结构如图左边第一个,Bert采用了Transformer Encoder,也就是每时每刻的Attention计算都能够得到全部时刻的输入。
OpenAI GPT 采用Transformer的Decoder,每个时刻的Attention计算只能依赖于该时刻前的所有时刻的输入,因为OpenAI GPT 是单向语言模型。
ELMO 则采用的是 LSTM,这个模型虽然可以学习到前后语义,但是输出依赖于前面的输入,决定了 EMLO 的网络层数不会太多,会造成大量耗时,这就决定了 ELMO 提取的特征有限。
输入
BERT模型要求有一个固定的Sequence的长度,比如128。如果不够就在后面padding,否则就截取掉多余的Token,从而保证输入是一个固定长度的Token序列。第一个Token总是特殊的[CLS],它本身没有任何语义,因此它会(必须)编码整个句子(其它词)的语义。
Bert 的输入相较其它模型,采用了三个Embedding相加的方式,通过加入Token Embeddings,Segment Embeddings,Position Embeddings三个向量,以此达到预训练和预测下一句的目的。
如上图,Bert 的输入Input是两个句子:"my dog is cute","he likes playing"。首先会在第一句开头加上特殊Token [CLS] 用于标记句子开始,用[SEP] 标记句子结束。
然后对每个Token进行3个Embedding,词的Embedding (Token Embeddings),位置 Embedding (Position Embeddings),句子 Embedding (Segment Embeddings)。最终将三个 Embedding 求和的方式输入到下一层。
下面详细介绍下三个 Embedding。
Token Embeddings
通过建立字向量表将每个字转换成一个一维向量,作为模型输入。特别的,英文词汇会做更细粒度的切分,比如playing或切割成 play 和 ##ing,中文目前尚未对输入文本进行分词,直接对单子构成为本的输入单位。将词切割成更细粒度的Word Piece是为了解决未登录词的常见方法。
假如输入文本 ”I like dog“。下图则为Token Embeddings层实现过程。输入文本在送入 Token Embeddings 层之前要先进性tokenization处理,且两个特殊的Token会插入在文本开头 [CLS] 和结尾 [SEP]。
Bert 在处理英文文本时只需要 30522 个词,Token Embeddings层会将每个词转换成768维向量,例子中5个Token会被转换成一个 (5, 768) 的矩阵或 (1, 5, 768) 的张量。
Segment Embedding
Bert 能够处理句子对的分类任务,这类任务就是判断两个文本是否是语义相似的。句子对中的两个句子被简单的拼接在一起后送入模型中,Bert 如何区分一个句子对是两个句子呢?答案就是 Segment Embeddings。
Segement Embeddings 层有两种向量表示,前一个向量是把0赋值给第一个句子的各个Token,后一个向量是把1赋值给各个 Token,问答系统等任务要预测下一句,因此输入是有关联的句子。而文本分类只有一个句子,那么 Segement embeddings 就全部是 0。
Position Embedding
由于出现在文本不同位置的字/词所携带的语义信息存在差异(如 ”你爱我“ 和 ”我爱你“),你和我虽然都和爱字很接近,但是位置不同,表示的含义不同。
在 RNN 中,第二个 ”I“ 和 第一个 ”I“ 表达的意义不一样,因为它们的隐状态不一样。对第二个 ”I“ 来说,隐状态经过 ”I think therefore“ 三个词,包含了前面三个词的信息,而第一个 ”I“ 只是一个初始值。因此,RNN 的隐状态保证在不同位置上相同的词有不同的输出向量表示。
RNN能够让模型隐式的编码序列的顺序信息,相比之下,Transformer 的自注意力层 (Self-Attention) 对不同位置出现相同词给出的是同样的输出向量表示。尽管 Transformer 中两个 ”I“ 在不同的位置上,但是表示的向量是相同的。
Transformer中通过植入关于Token的相对位置或者绝对位置信息来表示序列的顺序信息。作者测试用学习的方法来得到 Position Embeddings,最终发现固定位置和相对位置效果差不多,所以最后用的是固定位置的,而正弦可以处理更长的 Sequence,且可以用前面位置的值线性表示后面的位置。
偶数位置,使用正弦编码,奇数位置,使用余弦编码。
Masked Language Model
Maked LM 是为了解决单向信息问题,现有的语言模型的问题在于,没有同时利用双向信息,如 ELMO 号称是双向LM,但实际上是两个单向RNN构成的语言模型的拼接,由于时间序列的关系,RNN模型预测当前词只依赖前面出现过的词,对于后面的信息无从得知。
那么如何同时利用好前面的词和后面的词的语义呢?Bert提出Masked Language Model,也就是随机遮住句子中部分 Token,模型再去通过上下文语义去预测 Masked 的词,通过调整模型的参数使得模型预测正确率尽可能大。
怎么理解这一逻辑,Bert 预训练过程就是模仿我们学习语言的过程,要准确的理解一个句子或一段文本的语义,就要学习上下文关系,从上下文语义来推测空缺单词的含义。而 Bert 的做法模拟了英语中的完形填空,随机将一些单词遮住,让 Bert 模型去预测这个单词,以此达到学习整个文本语义的目的。
那么 Bert 如何做到”完形填空“的呢?
随机 mask 预料中 15% 的 Token,然后预测 [MASK] Token,与 masked token 对应的最终隐藏向量被输入到词汇表上的 softmax 层中。这虽然确实能训练一个双向预训练模型,但这种方法有个缺点,因为在预训练过程中随机 [MASK] Token 由于每次都是全部 mask,预训练期间会记住这些 MASK 信息,但是在fine-tune期间从未看到过 [MASK] Token,导致预训练和 fine-tune 信息不匹配。
而为了解决预训练和 fine-tune 信息不匹配,Bert 并不总是用实际的 [MASK] Token 替换 masked 词汇。
为什么15%的 Token 不完全 MASK?如果只有 MASK,这个预训练模型是有偏置的,也就是只能学到一种方式,用上下文去预测一个词,这导致 fine-tune 丢失一部分信息。
加上 10% 的随机词和 10% 的真实值是让模型知道,每个词都有意义,除了要学习上下文信息,还需要提防每个词,因为每个词都不一定是对的,对于 Bert 来说,每个词都需要很好的理解和预测。
有些人会疑惑,加了随机 Token,会让模型产生疑惑,从而不能学到真实的语义吗?对于人来说,完形填空都不一定能做对,而将文本中某些词随机替换,更是难以理解,从概率角度来说,随机 Token 占比只有 15% * 10% = 1.5%,预料足够的情况下,这并不会影响模型的性能。
因为 [MASK] Token 占比变小,且预测难度加大的原因,所以 MASK 会花更多时间。
Next Sentence Prediction
在许多下游任务中,如问答系统 QA 和自然语言推理NLI,都是建立在理解两个文本句子之间的关系基础上,这不是语言模型能直接捕捉到的。
为了训练一个理解句子关系的模型,作者提出 Next Sentence Prediction,也即是预训练一个下一句预测的二分类任务,这个任务就是每次训练前都会从语料库中随机选择句子 A 和句子 B,50% 是正确的相邻的句子,50% 是随机选取的一个句子,这个任务在预训练中能达到 97%-98% 的准确率,并且能很显著的提高 QA 和 NLI 的效果。
Fine-Tuning
fine-tune 就是指在已经训练好的语言模型基础上,使用有标签的数据对参数进行调整,使其更好的适用于下游任务。如对于分类问题在语言模型基础上加一层 softmax 网络,然后再新的预料上重新训练进行fine-tune。
ERT的Fine-Tuning如下图所示,共分为4类任务。
对于普通的分类任务,输入是一个序列,如图中右上所示,所有的Token都是属于同一个Segment(Id=0),我们用第一个特殊Token [CLS]的最后一层输出接上softmax进行分类,用分类的数据来进行Fine-Tuning。
对于相似度计算等输入为两个序列的任务,过程如图左上所示。两个序列的Token对应不同的Segment(Id=0/1)。我们也是用第一个特殊Token [CLS]的最后一层输出接上softmax进行分类,然后用分类数据进行Fine-Tuning。
第三类任务是序列标注,比如命名实体识别,输入是一个句子(Token序列),除了[CLS]和[SEP]的每个时刻都会有输出的Tag,比如B-PER表示人名的开始,本章的序列标注部分已经介绍过怎么把NER变成序列标注的问题了,这里不再赘述。然后用输出的Tag来进行Fine-Tuning,过程如图右下所示。
第四类是问答类问题,比如SQuAD v1.1数据集,输入是一个问题和一段很长的包含答案的文字(Paragraph),输出在这段文字里找到问题的答案。
我们怎么用BERT处理这样的问题呢?我们首先把问题和Paragraph表示成一个长的序列,中间用[SEP]分开,问题对应一个Segment(id=0),包含答案的文字对于另一个Segment(id=1)。这里有一个假设,那就是答案是Paragraph里的一段连续的文字(Span)。BERT把寻找答案的问题转化成寻找这个Span的开始下标和结束下标的问题。
如上图的左下所示。对于Paragraph的第i个Token,BERT的最后一层把它编码成,然后我们用一个向量S(这是模型的参数,需要根据训练数据调整)和它相乘(内积)计算它是开始位置的得分,因为Paragraph的每一个Token(当然WordPiece的中间,比如##ing是不可能是开始的)都有可能是开始可能,我们用softmax把它变成概率,然后选择概率最大的作为答案的开始:
类似的有一个向量T,用于计算答案结束的位置。
三.总结
BERT是一个语言表征模型(language representation model),通过超大数据、巨大模型、和极大的计算开销训练而成,在11个自然语言处理的任务中取得了最优(state-of-the-art, SOTA)结果。或许你已经猜到了此模型出自何方,没错,它产自谷歌。估计不少人会调侃这种规模的实验已经基本让一般的实验室和研究员望尘莫及了,但它确实给我们提供了很多宝贵的经验:
1、深度学习就是表征学习 (Deep learning is representation learning)
"We show that pre-trained representations eliminate the needs of many heavily engineered task-specific architectures". 在11项BERT刷出新境界的任务中,大多只在预训练表征(pre-trained representation)微调(fine-tuning)的基础上加一个线性层作为输出(linear output layer)。在序列标注的任务里(e.g. NER),甚至连序列输出的依赖关系都先不管(i.e. non-autoregressive and no CRF),照样秒杀之前的SOTA,可见其表征学习能力之强大。
2、规模很重要(Scale matters)
"One of our core claims is that the deep bidirectionality of BERT, which is enabled by masked LM pre-training, is the single most important improvement of BERT compared to previous work". 这种遮挡(mask)在语言模型上的应用对很多人来说已经不新鲜了,但确是BERT的作者在如此超大规模的数据+模型+算力的基础上验证了其强大的表征学习能力。这样的模型,甚至可以延伸到很多其他的模型,可能之前都被不同的实验室提出和试验过,只是由于规模的局限没能充分挖掘这些模型的潜力,而遗憾地让它们被淹没在了滚滚的paper洪流之中。
3、预训练价值很大(Pre-training is important)
"We believe that this is the first work to demonstrate that scaling to extreme model sizes also leads to large improvements on very small-scale tasks, provided that the model has been sufficiently pre-trained". 预训练已经被广泛应用在各个领域了(e.g. ImageNet for CV, Word2Vec in NLP),多是通过大模型大数据,这样的大模型给小规模任务能带来的提升有几何,作者也给出了自己的答案。BERT模型的预训练是用Transformer做的,但我想换做LSTM或者GRU的话应该不会有太大性能上的差别,当然训练计算时的并行能力就另当别论了。