目录
1.ELMo
1.1 模型结构
1.2 训练过程
1.3 使用过程
1.4 ELMo的输入
1.5 其它
2.GPT
2.1 训练过程
2.2 使用过程
2.3 如何改造下游任务
3.Bert
3.1 训练过程
3.2 使用过程
3.3 如何改造下游任务
3.4 跟其它语言模型的对比与关系
3.5 Masked语言模型
3.6 Next Sentence Prediction
3.7 输入部分的处理
3.8 输出部分的处理
由于静态词向量无法解决一词多义问题,引入动态词向量
1.首先使用字符级卷积神经网络(convolutional neural network, CNN)来将文本中的词转换成原始词向量(raw word vector)
2.将这些原始词向量输入双向语言模型中第一层
3.前向迭代中包含了该词以及该词之前的一些词汇或语境的信息
4.后向迭代包含了该词之后的信息
5.这两种迭代的信息组成了中间词向量(intermediate word vector)
6.这些中间词向量被输入到模型的下一层
7.最终表示(ELMo)就是原始词向量和两个中间词向量的加权和
在预训练中,采用双向LSTM对上下文进行编码,上下文使用静态的word embedding,对每层LSTM,将上文向量与下文向量进行拼接作为当前向量,利用大量的语料训练这个网络。对于一个新的句子,可以有三种表示,最底层的word embedding, 第一层的双向LSTM层的输出,这一层能学习到更多句法特征,第二层的双向LSTM的输出,这一层能学习到更多词义特征。经过ELMo训练,不仅能够得到word embedding, 又能学习到一个双层双向的神经网络。一层双向LSTM有两个输出,一个来自正向,一个来自负向,这两个一个代表前面信息对该词的影响的输出,一个代表后面信息对该词影响的输出,都能拿来当作词向量用,所以一层就会有两个词向量,两层就有4个,再加上最开始的输入--raw word vectors,就有4+1,也就有了2L+1个词向量。
可以将ELMo看作一个多层的LSTM来用作训练语言模型,目标就是最小化损失函数,并且进行反向传播更新:
输入是一个句子,先分成token,每一个token再根据其中的每个字符进行编码并进行拼接,加上起始和结尾符,再加上为了统一单词长度的padding,最后经过CNN层,再池化,每一个词就得到一个词向量。
1.ELMo是一个预训练好的语言模型,而不是一个预训练的词向量,其中的参数已经经过大量的语料库调好了。
2.词向量是在真实下游任务中产生的,所以根据输入不同,任务不同,同一个词得到的词向量是不同的。
3.可以将训练过程看作是特征提取的过程,在实际任务中,对于输入的句子,使用ELMo这个语言模型处理它,得到输出的向量,拿来做词向量。
GPT是“Generative Pre-Training”的简称,从名字看其含义是指的生成式的预训练。GPT也采用两阶段过程,第一个阶段是利用语言模型进行预训练,第二阶段通过Fine-tuning的模式解决下游任务。GPT的预训练过程,其实和ELMo是类似的,主要不同在于两点:首先,特征抽取器不是用的RNN,而是用的Transformer,它的特征抽取能力要强于RNN;其次,GPT的预训练虽然仍然是以语言模型作为目标任务,但是采用的是单向的语言模型,单向的含义是指:ELMo在做语言模型预训练的时候,为了预测目标单词同时使用了上文和下文,而GPT则只采用Context-before这个单词的上文来进行预测,而抛开了下文。它没有把单词的下文融合进来,这限制了其在更多应用场景的效果。
原本,对于不同的下游任务来说,本来你可以任意设计自己的网络结构,现在不行了,你要向GPT的网络结构看齐,把任务的网络结构改造成和GPT的网络结构是一样的。然后,在做下游任务的时候,利用第一步预训练好的参数初始化GPT的网络结构,这样通过预训练学到的语言学知识就被引入到你手头的任务里来了。再次,你可以用手头的任务去训练这个网络,对网络参数进行Fine-tuning,使得这个网络更适合解决手头的问题。
GPT论文给了一个改造施工图如上:对于分类问题,不用怎么动,加上一个起始和终结符号即可;对于句子关系判断问题,比如Entailment,两个句子中间再加个分隔符即可;对文本相似性判断问题,把两个句子顺序颠倒下做出两个输入即可,这是为了告诉模型句子顺序不重要;对于多项选择问题,则多路输入,每一路把文章和答案选项拼接作为输入即可。从上图可看出,这种改造还是很方便的,不同任务只需要在输入部分施工即可。
Bert采用和GPT完全相同的两阶段模型,首先是语言模型预训练;其次是使用Fine-Tuning模式解决下游任务。和GPT的最主要不同在于在预训练阶段采用了类似ELMo的双向语言模型,当然另外一点是语言模型的数据规模要比GPT大。
第二阶段,Fine-Tuning阶段,这个阶段的做法和GPT是一样的。当然,它也面临着下游任务网络结构改造的问题,在改造任务方面Bert和GPT有些不同。
首先,在nlp中的各项任务可分类为:
根据不同的任务,改造方式也不同:
Bert如何改造输入输出部分使得大部分NLP任务都可以使用Bert预训练好的模型参数呢?上图给出示例,对于句子关系类任务,很简单,和GPT类似,加上一个起始和终结符号,句子之间加个分隔符即可。对于输出来说,把第一个起始符号对应的Transformer最后一层位置上面串接一个softmax分类层即可;对于分类问题,与GPT一样,只需要增加起始和终结符号,输出部分和句子关系判断任务类似改造;对于序列标注问题,输入部分和单句分类是一样的,只需要输出部分Transformer最后一层每个单词对应位置都进行分类即可。
从上图可见,Bert其实和ELMo及GPT存在千丝万缕的关系,比如如果把GPT预训练阶段换成双向语言模型,那么就得到了Bert;而如果我们把ELMO的特征抽取器换成Transformer,那么我们也会得到Bert。所以你可以看出:Bert最关键两点,一点是特征抽取器采用Transformer;第二点是预训练的时候采用双向语言模型。
上一篇笔记提到了CBOW方法,它的核心思想是:在做语言模型任务的时候,要预测的单词抠掉,然后根据它的上文Context-Before和下文Context-after去预测单词。其实Bert怎么做的?Bert就是这么做的。从这里可以看到方法间的继承关系。
Masked语言模型本质思想其实是CBOW,但是细节方面有改进。
Masked双向语言模型具体做法:随机选择语料中15%的单词,把它抠掉,也就是用[Mask]掩码代替原始单词,然后要求模型去正确预测被抠掉的单词。但是这里有个问题:训练过程大量看到[mask]标记,但是真正后面用的时候是不会有这个标记的,这会引导模型认为输出是针对[mask]这个标记的,但是实际使用又见不到这个标记,这自然会有问题。为了避免这个问题,Bert改造了一下,15%的被上天选中要执行[mask]替身这项光荣任务的单词中,只有80%真正被替换成[mask]标记,10%被随机替换成另外一个单词,10%情况这个单词不做改动。
“Next Sentence Prediction”,指的是做语言模型预训练的时候,分两种情况选择两个句子,一种是选择语料中真正顺序相连的两个句子;另外一种是第二个句子从语料库中随机选择一个拼到第一个句子后面。我们要求模型除了做上述的Masked语言模型任务外,附带再做个句子关系预测,判断第二个句子是不是真的是第一个句子的后续句子。之所以这么做,是考虑到很多NLP任务是句子关系判断任务,单词预测粒度的训练到不了句子关系这个层级,增加这个任务有助于下游句子关系判断任务。所以可以看到,它的预训练是个多任务过程。这也是Bert的一个创新。
Bert的输入部分是个线性序列,两个句子通过分隔符分割,最前面和最后增加两个标识符号。每个单词有三个embedding:位置信息embedding,这是因为NLP中单词顺序是很重要的特征,需要在这里对位置信息进行编码;单词embedding,这个就是我们之前一直提到的单词embedding;第三个是句子embedding,因为前面提到训练数据都是由两个句子构成的,那么每个句子有个句子整体的embedding项对应给每个单词,第一个句子可能用0表示,第二个用1,只有一个句子的时候可能只用0。把单词对应的三个embedding叠加,就形成了Bert的输入。第一个token很有用,它本身没有任何意义,在进行self-attention时,会获取下文所有信息(编码整个句子的语义),不像其他单词,在self-attention时获取最多的信息是来自于自己。注意这里的分词会把“playing”分成“play”和“##ing”两个Token,这种把词分成更细粒度的Word Piece的方法是一种解决未登录词的常见办法。
参考资料:从Word Embedding到Bert模型—自然语言处理中的预训练技术发展史 - 知乎