文章目录
论文:BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding
论文链接:https://arxiv.org/abs/1810.04805
一、简介
BERT的内部结构其实就是多个transformer 的encoder,如果您对transformer并不了解,请参阅我之前的博文。
从创新的角度来看,bert其实并没有过多的结构方面的创新点,其和GPT一样均是采用的transformer的结构,相对于GPT来说,其是双向结构的,而GPT是单向的,如下图所示
elmo:将上下文当作特征,但是无监督的语料和我们真实的语料还是有区别的,不一定的符合我们特定的任务,是一种双向的特征提取。
openai gpt:就做了一个改进,也是通过transformer学习出来一个语言模型,不是固定的,通过任务 finetuning,用transfomer代替elmo的lstm。
openai gpt其实就是缺少了encoder的transformer。当然也没了encoder与decoder之间的attention。
openAI gpt虽然可以进行fine-tuning,但是有些特殊任务与pretraining输入有出入,单个句子与两个句子不一致的情况,很难解决,还有就是decoder只能看到前面的信息。
其次bert在多方面的nlp任务变现来看效果都较好,具备较强的泛化能力,对于特定的任务只需要添加一个输出层来进行fine-tuning即可。
二、模型结构
从模型的层数来说其实已经很大了,但是由于transformer的残差(residual)模块,层数并不会引起梯度消失等问题,但是并不代表层数越多效果越好,有论点认为低层偏向于语法特征学习,高层偏向于语义特征学习。
其实概括一下,Bert主要有三部分构成:Embedding + Transformer Encoder + Loss优化
2.1 Embedding
word embedding(无预训练) + position embedding + type embedding
BERT输入的数据是两句话,通过【sep】分隔符标记,分割符前称为前段,分隔符后面的称为后段,一次输入两句,是为了后面计算一个叫classification 的 loss;
type embedding在这个例子中,在输入前段的词都是 E A E_A EA,后段的词都是 E B E_B EB;
此外,引入position embedding 是为了解决attention机制中忽略词的顺序。
2.2 Transformer Encoder
Multi_Head Attention (多头注意力机制) + Feed Forward (前向传播)
Multi_Head Attention : 具体详见“Attention is All Your Need”论文,这里详细的讲一下,在BERT中是如何使用multi_head attention进行编码的。
第一步,将输入的embedding 进行维度扩展,同attention那篇论文中讲的那样,一个维度作为Key,一个维度作为query,一个维度作为Value。
第二步,进行multi_head划分,将扩展后的每一个维度,都进行划分,图中例子我们进行的是两个头的划分。
第三步,对于划分出的每一个头,与输入中的其他词做self-attention,内部自注意力机制,得到新的向量表示。
第四步,将每一个头 自注意力后的向量表示进行concat,简单拼接,最为最后每一个词的向量表示。
第五步,增加一个dropout层,由于是深度transformer,深度越深有可能产生梯度消失、梯度爆炸的问题,因此,这里采用了残差连接,将原始的word embedding与tansformer后的向量表示相加。最后再来一个layer norm 层归一化。
Feed Forward:很简单,如下图所示。
2.3 Loss优化
对于这个模型中的Loss优化,总的来说是Mask Language Model 和 Next sentence prediction的Loss。如图示:
Mask Language Model:将输入句子mask(挖)掉一个词,然后通过上下文的词来预测这个词。通过预测的loss,计算Mask LM Loss
Next sentence prediction:在word embedding的时候说到,模型的输入是由【sep】标记分割的两句话,因此这两句话有两种可能,一、两句话出自同一篇文章,上下两句是连续的,classfication 为True;二、两句话不相关,不是上下文关系,classfication 为False。
因此整个模型通过优化这两个任务的损失,来训练整个模型。
三、BERT的预训练过程
BERT的预训练阶段包括两个任务,一个是Masked Language Model,还有一个是Next Sentence Prediction。
3.1 Masked Language Model
MLM可以理解为完形填空,作者会随机mask每一个句子中15%的词,用其上下文来做预测,例如:my dog is hairy → my dog is [MASK]
此处将hairy进行了mask处理,然后采用非监督学习的方法预测mask位置的词是什么,但是该方法有一个问题,因为是mask 15%的词,其数量已经很高了,这样就会导致某些词在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全局的可视,又增加了信息的获取,但是不让模型获取全量信息。
3.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来完成语义的大部分的学习。
四、总结
4.1 BERT的优点
-
Transformer Encoder因为有Self-attention机制,因此BERT自带双向功能
-
因为双向功能以及多层Self-attention机制的影响,使得BERT必须使用Cloze版的语言模型Masked-LM来完成token级别的预训练
-
为了获取比词更高级别的句子级别的语义表征,BERT加入了Next Sentence Prediction来和Masked-LM一起做联合训练
-
为了适配多任务下的迁移学习,BERT设计了更通用的输入层和输出层
-
微调成本小
4.2 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,历时四天。
4.3 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任务。