BERT |(2)BERT的原理详解

在写这一篇的时候,偶然发现有一篇博客,相比于我之前的一篇写得更详尽,这一篇也参考这篇博客来继续写写自己的笔记总结。

原博客地址:一文读懂BERT(原理篇)

一、什么是Bert?

BERT |(2)BERT的原理详解_第1张图片

二,bert的原理

从创新的角度来看,bert其实并没有过多的结构方面的创新点,其和GPT一样均是采用的transformer的结构,相对于GPT来说,其是双向结构的,而GPT是单向的,如下图所示

elmo:将上下文当作特征,但是无监督的语料和我们真实的语料还是有区别的,不一定的符合我们特定的任务,是一种双向的特征提取。

openai gpt就做了一个改进,也是通过transformer学习出来一个语言模型,不是固定的,通过任务 fine-tuning,用transfomer代替elmo的lstm
openai gpt其实就是缺少了encoder的transformer。当然也没了encoder与decoder之间的attention。

openAI gpt虽然可以进行fine-tuning,但是有些特殊任务与pretraining输入有出入,单个句子与两个句子不一致的情况,很难解决,还有就是decoder只能看到前面的信息。
其次bert在多方面的nlp任务变现来看效果都较好,具备较强的泛化能力,对于特定的任务只需要添加一个输出层来进行fine-tuning即可。

结构


先看下bert的内部结构,官网最开始提供了两个版本,L表示的是transformer的层数,H表示输出的维度,A表示mutil-head attention的个数

在这里插入图片描述

如今已经增加了多个模型,中文是其中唯一一个非英语的模型。

在这里插入图片描述

从模型的层数来说其实已经很大了,但是由于transformer的残差(residual)模块,层数并不会引起梯度消失等问题,但是并不代表层数越多效果越好,有论点认为低层偏向于语法特征学习,高层偏向于语义特征学习

预训练模型


首先我们要了解一下什么是预训练模型,举个例子,假设我们有大量的维基百科数据,那么我们可以用这部分巨大的数据来训练一个泛化能力很强的模型,当我们需要在特定场景使用时,例如做文本相似度计算,那么,只需要简单的修改一些输出层,再用我们自己的数据进行一个增量训练,对权重进行一个轻微的调整。

预训练的好处在于在特定场景使用时不需要用大量的语料来进行训练,节约时间效率高效,bert就是这样的一个泛化能力较强的预训练模型。

BERT的预训练过程

接下来我们看看BERT的预训练过程,BERT的预训练阶段包括两个任务,一个是Masked Language Model,还有一个是Next Sentence Prediction。

Masked Language Model


MLM可以理解为完形填空,作者会随机mask每一个句子中15%的词,用其上下文来做预测,例如:my dog is hairy → my dog is [MASK]

此处将hairy进行了mask处理,然后采用非监督学习的方法预测mask位置的词是什么,但是该方法有一个问题,因为是mask15%的词,其数量已经很高了,这样就会导致某些词在fine-tuning阶段从未见过,为了解决这个问题,作者做了如下的处理:

  • 80%的时间是采用[mask],my dog is hairy → my dog is [MASK]
  • 10%的时间是随机取一个词来代替mask的词,my dog is hairy -> my dog is apple
  • 10%的时间保持不变,my dog is hairy -> my dog is hairy

那么为啥要以一定的概率使用随机词呢?这是因为transformer要保持对每个输入token分布式的表征,否则Transformer很可能会记住这个[MASK]就是"hairy"。至于使用随机词带来的负面影响,文章中解释说,所有其他的token(即非"hairy"的token)共享15%*10% = 1.5%的概率,其影响是可以忽略不计的。Transformer全局的可视,又增加了信息的获取,但是不让模型获取全量信息。
注意:

  • 有参数dupe_factor决定数据duplicate的次数。
  • 其中,create_instance_from_document函数,是构造了一个sentence-pair的样本。对每一句,先生成[CLS]+A+[SEP]+B+[SEP],有长(0.9)有短(0.1),再加上mask,然后做成样本类object。
  • create_masked_lm_predictions函数返回的tokens是已经被遮挡词替换之后的tokens
  • masked_lm_labels则是遮挡词对应位置真实的label。

BERT |(2)BERT的原理详解_第2张图片

Next Sentence Prediction


选择一些句子对A与B,其中50%的数据B是A的下一条句子,剩余50%的数据B是语料库中随机选择的,学习其中的相关性,添加这样的预训练的目的是目前很多NLP的任务比如QA和NLI都需要理解两个句子之间的关系,从而能让预训练的模型更好的适应这样的任务。
个人理解:

  • Bert先是用Mask来提高视野范围的信息获取量,增加duplicate再随机Mask,这样跟RNN类方法依次训练预测没什么区别了除了mask不同位置外;
  • 全局视野极大地降低了学习的难度,然后再用A+B/C来作为样本,这样每条样本都有50%的概率看到一半左右的噪声;
  • 但直接学习Mask A+B/C是没法学习的,因为不知道哪些是噪声,所以又加上next_sentence预测任务,与MLM同时进行训练,这样用next来辅助模型对噪声/非噪声的辨识,用MLM来完成语义的大部分的学习。

BERT |(2)BERT的原理详解_第3张图片

输入


bert的输入可以是单一的一个句子或者是句子对,实际的输入值是segment embedding与position embedding相加,具体的操作流程可参考transformer讲解。

BERT的输入词向量是三个向量之和:

Token Embedding:WordPiece tokenization subword词向量。
Segment Embedding:表明这个词属于哪个句子(NSP需要两个句子)。
Position Embedding:学习出来的embedding向量。这与Transformer不同,Transformer中是预先设定好的值。

 

三、如何使用bert

 

BERT |(2)BERT的原理详解_第4张图片

BERT |(2)BERT的原理详解_第5张图片

BERT |(2)BERT的原理详解_第6张图片

四、BERT的总结和优缺点

BERT适用场景

第一,如果NLP任务偏向在语言本身中就包含答案,而不特别依赖文本外的其它特征,往往应用Bert能够极大提升应用效果。典型的任务比如QA和阅读理解,正确答案更偏向对语言的理解程度,理解能力越强,解决得越好,不太依赖语言之外的一些判断因素,所以效果提升就特别明显。反过来说,对于某些任务,除了文本类特征外,其它特征也很关键,比如搜索的用户行为/链接分析/内容质量等也非常重要,所以Bert的优势可能就不太容易发挥出来。再比如,推荐系统也是类似的道理,Bert可能只能对于文本内容编码有帮助,其它的用户行为类特征,不太容易融入Bert中。

第二,Bert特别适合解决句子或者段落的匹配类任务。就是说,Bert特别适合用来解决判断句子关系类问题,这是相对单文本分类任务和序列标注等其它典型NLP任务来说的,很多实验结果表明了这一点。而其中的原因,我觉得很可能主要有两个,一个原因是:很可能是因为Bert在预训练阶段增加了Next Sentence Prediction任务,所以能够在预训练阶段学会一些句间关系的知识,而如果下游任务正好涉及到句间关系判断,就特别吻合Bert本身的长处,于是效果就特别明显。第二个可能的原因是:因为Self Attention机制自带句子A中单词和句子B中任意单词的Attention效果,而这种细粒度的匹配对于句子匹配类的任务尤其重要,所以Transformer的本质特性也决定了它特别适合解决这类任务。

从上面这个Bert的擅长处理句间关系类任务的特性,我们可以继续推理出以下观点:

既然预训练阶段增加了Next Sentence Prediction任务,就能对下游类似性质任务有较好促进作用,那么是否可以继续在预训练阶段加入其它的新的辅助任务?而这个辅助任务如果具备一定通用性,可能会对一类的下游任务效果有直接促进作用。这也是一个很有意思的探索方向,当然,这种方向因为要动Bert的第一个预训练阶段,所以属于NLP届土豪们的工作范畴,穷人们还是散退、旁观、鼓掌、叫好为妙。

第三,Bert的适用场景,与NLP任务对深层语义特征的需求程度有关。感觉越是需要深层语义特征的任务,越适合利用Bert来解决;而对有些NLP任务来说,浅层的特征即可解决问题,典型的浅层特征性任务比如分词,POS词性标注,NER,文本分类等任务,这种类型的任务,只需要较短的上下文,以及浅层的非语义的特征,貌似就可以较好地解决问题,所以Bert能够发挥作用的余地就不太大,有点杀鸡用牛刀,有力使不出来的感觉。

这很可能是因为Transformer层深比较深,所以可以逐层捕获不同层级不同深度的特征。于是,对于需要语义特征的问题和任务,Bert这种深度捕获各种特征的能力越容易发挥出来,而浅层的任务,比如分词/文本分类这种任务,也许传统方法就能解决得比较好,因为任务特性决定了,要解决好它,不太需要深层特征。

第四,Bert比较适合解决输入长度不太长的NLP任务,而输入比较长的任务,典型的比如文档级别的任务,Bert解决起来可能就不太好。主要原因在于:Transformer的self attention机制因为要对任意两个单词做attention计算,所以时间复杂度是n平方,n是输入的长度。如果输入长度比较长,Transformer的训练和推理速度掉得比较厉害,于是,这点约束了Bert的输入长度不能太长。所以对于输入长一些的文档级别的任务,Bert就不容易解决好。结论是:Bert更适合解决句子级别或者段落级别的NLP任务。

总结下BERT的主要贡献:

  • 引入了Masked LM,使用双向LM做模型预训练。
  • 为预训练引入了新目标NSP,它可以学习句子与句子间的关系。
  • 进一步验证了更大的模型效果更好: 12 --> 24 层。
  • 为下游任务引入了很通用的求解框架,不再为任务做模型定制。
  • 刷新了多项NLP任务的记录,引爆了NLP无监督预训练技术。

BERT是谷歌团队糅合目前已有的NLP知识集大成者,刷新11条赛道彰显了无与伦比的实力,且极容易被用于多种NLP任务。宛若一束烟花点亮在所有NLP从业者心中。更为可贵的是谷歌选择了开源这些,让所有从业者看到了在各行各业落地的更多可能性。

BERT优点

  • Transformer Encoder因为有Self-attention机制,因此BERT自带双向功能
  • 因为双向功能以及多层Self-attention机制的影响,使得BERT必须使用Cloze版的语言模型Masked-LM来完成token级别的预训练
  • 为了获取比词更高级别的句子级别的语义表征,BERT加入了Next Sentence Prediction来和Masked-LM一起做联合训练
  • 为了适配多任务下的迁移学习,BERT设计了更通用的输入层和输出层
  • 微调成本小

BERT缺点

  • task1的随机遮挡策略略显粗犷,推荐阅读《Data Nosing As Smoothing In Neural Network Language Models》
  • [MASK]标记在实际预测中不会出现,训练时用过多[MASK]影响模型表现;
  • 每个batch只有15%的token被预测,所以BERT收敛得比left-to-right模型要慢(它们会预测每个token)
  • BERT对硬件资源的消耗巨大(大模型需要16个tpu,历时四天;更大的模型需要64个tpu,历时四天。
  • 关于BERT最新的各领域应用推荐张俊林的Bert时代的创新(应用篇)

思考

  • 个人并不认为文章是模型的改进,更认可为任务的设计改进。
  • 论文作者只比较了有没有task1的影响,并没有针对task2对比试验。提升是否来自好的预训练任务设计没有明说。
  • bert对nlp领域目前已有知识的有效“整合”,在硬件配置足够的情况下能提高nlp多领域性能
     

你可能感兴趣的:(#,BERT,bert)