BERT原理总结

2018年Google推出的BERT模型是NLP任务的集大成者,在11个NLP任务中夺得SOTA结果。也预示着词向量技术目前的巅峰。

和ELMO以及OpenAI GPT一样,BERT也是通过预训练的方式训练语言模型,然后在下游任务中进行微调。上面也说了,BERT是词向量模型的集大成者,为什么这么说呢?因为它融合了2018年的两个有名的词向量模型ELMOOpenAI GPT的优点

Feature-based pre-train:ELMO模型采用BILM(双向lstm语言模型),通过上下文预测词。每一个方向的lstm进行特征提取,最后用这两个方向的特征进行简单的串联后进行语言模型的预训练,预训练完成后用自己任务进行微调,微调方法为:加载预训练好的参数和模型,输入下游任务数据(去除标签)到预训练好的模型中进行微调(domain transfer),获取每个隐藏层的embedding线性组合后(也就是动态词向量)作为新的特征进行下游任务。它的弊端首先在于双向lstm只是简单的进行拼接串联融合,这种简单的拼接的特征表达能力还不够强。(现在没有实验证明这一点,只是理论猜测)。其次,lstm相对于transformer来说不能很好的解决长距离依赖的问题。因为transformer结构中的self-attention是每一个词都会和文本中的其他词计算attention,所以不管他们距离有多远,最大路径长度都为1,可以捕捉长距离依赖关系

Fine-tuning pre-train:OpenAIGPT采用单向的transformer语言模型,通过上文预测词。用transformer进行特征提取,进行语言模型的预训练,训练完成后,在下游任务上进行微调。微调方法为:先加载预训练好的模型和参数,然后输入下游任务的数据到模型中进行标签预测和语言模型辅助微调。在处理下游任务时,OpenAI GPT是采用和预训练一样的结构(即单向transormer)直接进行下游任务。这种模型的弊端就是因为采用单向的transformer结构,无法利用下文的信息。语言表征能力有待加强。

BERT(Bidirectional Encoder Representations from Transformers)模型采用双向transformer结构,通过对语言模型的预训练,使用Fine-tuning模式解决下游任务。可以很好的利用词的上下文信息。它的预训练方式与ELMO和OpenAI GPT有比较大的区别,这也是它最让人眼前一亮的地方。

BERT结构
输入:三部分embedding的和(分别为Token embedding+ segment embedding + position embedding)

  • Token embedding:使用WordPiece embeddings(什么是wordpiece,比如playing和play两个单词,实际上为同一个词,wordpiece就是把这两个词分为play和##ing。这样可以把词的本身的意思和时态分开,减少词表的数量)。[CLS]:每个序列的第一个 token 始终是特殊分类嵌入(special classification embedding),即 CLS。对应于该 token的最终隐藏状态(即,Transformer的输出)被用于分类任务的聚合序列表示。如果没有分类任务的话,这个向量是被忽略的。[SEP]:用于分隔一对句子的特殊符号。有两种方法用于分隔句子:第一种是使用特殊符号 SEP;第二种是添加学习句子 A 嵌入到第一个句子的每个 token 中,句子 B 嵌入到第二个句子的每个 token 中。如果是单个输入的话,就只使用句子 A

  • Position embedding:对应于公式
    在这里插入图片描述
    pos表示单词的位置,i表示单词的维度,dmodel表示单词的向量一共有多少维。至于为什么选用这个公式来表示position
    embedding,作者说选择这个函数是因为假设它可以让模型很容易地通过相对位置来学习,因为对于任何固定的偏置k,PEpos+k都可以表示成一个线性函数PE
    pos(根据公式sin(α+β)=sinαcosβ+cosαsinβ,cos(α+β)=cosαcosβ-sinαsinβ,这表明α+β的位置可以表示为α位置向量的线性变化)

  • Segment embedding:因为训练数据都是由两个句子构成的,那么每个句子有个句子整体的embedding项对应给每个单词,蕴含着句子是属于第一句还是第二句的信息

预训练
Masked LM(遮蔽语言模型)

  • 以15%的概率随机选中一些需要被处理的词。选中这些词后,再以80%的概率用[mask]标志去替换这些词(即遮蔽),以10%的概率随机的用语料库的一个词替换它,以10%的概率不对这些词做任何处理。在训练模型时,因为每一个句子都会被多次输入到模型中用于参数学习,但是Google并没有在每次都mask掉这些单词,为什么这样呢?这么做的原因是如果句子中的某个Token100%都会被mask掉,那么在fine-tuning的时候模型就会有一些没有见过的单词。加入随机Token的原因是因为Transformer要保持对每个输入token的分布式表征,否则模型就会记住这个[mask]是这个token。至于单词带来的负面影响,因为一个单词被随机替换掉的概率只有15%*10% =1.5%,这个负面影响其实是可以忽略不计的。另外文章指出由于每次只预测15%的单词,因此模型收敛的比较慢。

  • 根据上下文预测被[mask]标记的原始的词,由于Transformer编码器不知道它将被要求预测哪些单词,或者哪些已经被随机单词替换,因此它必须对每个输入词保持分布式的上下文表示。此外,由于随机替换在所有词中只发生1.5%,所以并不会影响模型对于语言的理解

Next sentence prediction(下个句子预测):判断B句子是否是A句子的下一个句子,如果是的话输出’IsNext‘,否则输出’NotNext‘,当为每个预训练样本选择句子 A 和 B 时。50%的几率是选择语料中真正顺序相连的两个句子,它们符合‘IsNext’关系;50%的几率是第二个句子从语料库中抛色子,随机选择一个拼到第一个句子后面,它们符合’NotNext‘关系。这个关系保存在图4中的[CLS]符号中,也就是说最终[CLS]的隐藏状态输出用于这个分类

Fine-tuning
Fine-tuning阶段参考OpenAI GPT的Fine-tuning方式,直接用在下游任务中,不过BERT没有用语言模型辅助微调这个策略

激活函数
BERT激活函数选用Gelu函数(高斯误差线性单元),GELU的非线性变化是一种符合预期的随机正则变换方式,比relu好,relu缺乏数据的统计特性,而Gelu则在relu的基础上加入了统计的特性可以赋予其统计学关系。论文中提到在好几个深度学习任务中都优于Relu的效果
在这里插入图片描述
或者近似认为 Gelu(x)≈ xσ(1.702x)

总结
通常来说,绝大部分 NLP 问题可以如下的四类任务中:

  • 一类是序列标注,这是最典型的 NLP任务,比如中文分词,词性标注,命名实体识别,语义角色标注等都可以归入这一类问题,它的特点是句子中每个单词要求模型根据上下文都要给出一个分类类别
  • 第二类是分类任务,比如我们常见的文本分类,情感计算等都可以归入这一类。它的特点是不管文章有多长,总体给出一个分类类别即可
  • 第三类任务是句子关系判断,比如 Entailment,QA,语义改写,自然语言推理等任务都是这个模式,它的特点是给定两个句子,模型判断出两个句子是否具备某种语义关系
  • 第四类是生成式任务,比如机器翻译,文本摘要,写诗造句,看图说话等都属于这一类。它的特点是输入文本内容后,需要自主生成另外一段文字

对于这四类任务。BERT如何改造输入输出部分使得大部分 NLP 任务都可以使用 Bert 预训练好的模型参数呢?

对于句子关系类任务,很简单,和 GPT 类似,加上一个起始和终结符号,句子之间加个分隔符即可。对于输出来说,把第一个起始符号对应的 Transformer 最后一层位置上面串接一个 softmax 分类层即可。对于分类问题,与 GPT 一样,只需要增加起始和终结符号,输出部分和句子关系判断任务类似改造;对于序列标注问题,输入部分和单句分类是一样的,只需要输出部分 Transformer 最后一层每个单词对应位置都进行分类即可。从这里可以看出,上面列出的 NLP 四大任务里面,除了生成类任务外,Bert 其它都覆盖到了,而且改造起来很简单直观。

猜你喜欢

转载自blog.csdn.net/zhdywdl/article/details/88608874