WordEmbedding
Word2Vec/Glove
- CBOW:mask词后利用上下文预测。 (Bert)
- Skip-gram: 输入mask的词,预测上下文。
NNLM是输入上文预测下文。
使用Word2Vec或者Glove,通过做语言模型任务,就可以获得每个单词的Word Embedding。(word enbeding是标准的预训练过程。)
QA,就是问答问题,所谓问答问题,指的是给定一个问题X,给定另外一个句子Y,要判断句子Y是否是问题X的正确答案。
预训练的下游任务中,关键是网络如何使用训练好的Word Embedding,和NNLM一样,句子中的每个单词以Onehot形式作为输入,然后乘学好的Word Embedding矩阵Q,结果就是单词对应的Word Embedding。Word Embedding矩阵其实就是网络Onehot层到embedding层映射的网络参数矩阵。
即,Word Embedding等价于把Onehot层到embedding层的网络预训练好的参数矩阵Q初始化了。Word Embedding只能初始化第一层网络参数,在下游NLP任务的使用中,一种是Frozen,就是Word Embedding那层网络参数固定不动;另外一种就是Fine-Tuning,九十Word Embedding这层参数使用新的训练集训练也需要跟着训练过程更新。
Word Embedding对很多下游NLP任务有帮助,但不大。主要原因是Word Embedding存在一定的问题。即多义词问题。
比如多义词Bank,有两个常用含义,但是Word Embedding在对bank这个单词进行编码的时候,是区分不开这两个含义的,因为它们尽管上下文环境中出现的单词不同,但是在用语言模型训练的时候,不论什么上下文的句子经过word2vec,都是预测相同的单词bank,而同一个单词占的是同一行的参数空间,这导致两种不同的上下文信息都会编码到相同的word embedding空间里去。所以word embedding无法区分多义词的不同语义,这就是它的一个比较严重的问题。
针对多义词问题,ELMO提供了一种简洁优雅的解决方案。
从Word Embedding到ELMO(Deep contextualized word representation)
ELMO是“Embedding from Language Models”的简称,ELMO的本质思想是:事先用语言模型学好一个单词的Word Embedding,此时多义词无法区分,在实际使用WordEmbedding的时候,单词具备特定的上下文,这时再根据上下文单词的语义调整单词的Word Embedding表示,这样经过调整后的Word Embedding更能表达此上下文的具体含义。所以ELMO本身是个根据当前上下文对Word Embedding动态调整的思路。
ELMO采用了典型的两阶段过程,第一个阶段是利用语言模型进行预训练;第二个阶段是在做下游任务时,从预训练网络中提取对应单词的网络各层的Word Embedding作为新特征补充到下游任务中。如果训练好这个网络后,输入一个新句子 ,句子中每个单词都能得到对应的三个Embedding:最底层是单词的Word Embedding,往上走是第一层双向LSTM中对应单词位置的Embedding,这层编码单词的句法信息更多一些;再往上走是第二层LSTM中对应单词位置的Embedding,这层编码单词的语义信息更多一些。
上面介绍的是ELMO的第一阶段:预训练阶段。那么预训练好网络结构后,如何给下游任务使用呢?上图展示了下游任务的使用过程,比如我们的下游任务仍然是QA问题,此时对于问句X,我们可以先将句子X作为预训练好的ELMO网络的输入,这样句子X中每个单词在ELMO网络中都能获得对应的三个Embedding,之后给予这三个Embedding中的每一个Embedding一个权重a,这个权重可以学习得来,根据各自权重累加求和,将三个Embedding整合成一个。然后将整合后的这个Embedding作为X句在自己任务的那个网络结构中对应单词的输入,以此作为补充的新特征给下游任务使用。对于上图所示下游任务QA中的回答句子Y来说也是如此处理。因为ELMO给下游提供的是每个单词的特征形式,所以这一类预训练的方法被称为“Feature-based Pre-Training”。至于为何这么做能够达到区分多义词的效果,你可以想一想,其实比较容易想明白原因。
上面这个图是TagLM采用类似ELMO的思路做命名实体识别任务的过程,其步骤基本如上述ELMO的思路,所以此处不展开说了。TagLM的论文发表在2017年的ACL会议上,作者就是AllenAI里做ELMO的那些人,所以可以将TagLM看做ELMO的一个前导工作。
前面我们提到静态Word Embedding无法解决多义词的问题,那么ELMO引入上下文动态调整单词的embedding后多义词问题解决了吗?解决了,而且比我们期待的解决得还要好。上图给了个例子,对于Glove训练出的Word Embedding来说,多义词比如play,根据它的embedding找出的最接近的其它单词大多数集中在体育领域,这很明显是因为训练数据中包含play的句子中体育领域的数量明显占优导致;而使用ELMO,根据上下文动态调整后的embedding不仅能够找出对应的“演出”的相同语义的句子,而且还可以保证找出的句子中的play对应的词性也是相同的,这是超出期待之处。之所以会这样,是因为我们上面提到过,第一层LSTM编码了很多句法信息,这在这里起到了重要作用。
那么站在现在这个时间节点看,ELMO有什么值得改进的缺点呢?首先,一个非常明显的缺点在特征抽取器选择方面,ELMO使用了LSTM而不是新贵Transformer,Transformer是谷歌在17年做机器翻译任务的“Attention is all you need”的论文中提出的,引起了相当大的反响,很多研究已经证明了Transformer提取特征的能力是要远强于LSTM的。如果ELMO采取Transformer作为特征提取器,那么估计Bert的反响远不如现在的这种火爆场面。另外一点,ELMO采取双向拼接这种融合特征的能力可能比Bert一体化的融合特征方式弱,但是,这只是一种从道理推断产生的怀疑,目前并没有具体实验说明这一点。
我们如果把ELMO这种预训练方法和图像领域的预训练方法对比,发现两者模式看上去还是有很大差异的。除了以ELMO为代表的这种基于特征融合的预训练方法外,NLP里还有一种典型做法,这种做法和图像领域的方式就是看上去一致的了,一般将这种方法称为“基于Fine-tuning的模式”,而GPT就是这一模式的典型开创者。
从Word Embedding到GPT
GPT是“Generative Pre-Training”的简称,从名字看其含义是指的生成式的预训练。GPT也采用两阶段过程,第一个阶段是利用语言模型进行预训练,第二阶段通过Fine-tuning的模式解决下游任务。上图展示了GPT的预训练过程,其实和ELMO是类似的,GPT和EMLo的不同点有两个:
- 首先,特征抽取器不是用的RNN,而是用的Transformer,上面提到过它的特征抽取能力要强于RNN,这个选择很明显是很明智的;
- 其次,GPT的预训练虽然仍然是以语言模型作为目标任务,但是采用的是单向的语言模型。
所谓“单向”的含义是指:语言模型训练的任务目标是根据 W i W_i Wi 单词的上下文去正确预测单词 W i W_i Wi , W i W_i Wi之前的单词序列Context-before称为上文,之后的单词序列Context-after称为下文。
ELMO在做语言模型预训练的时候,预测单词 W i W_i Wi同时使用了上文和下文,而GPT则只采用Context-before这个单词的上文来进行预测,而抛开了下文。这个选择现在看不是个太好的选择,原因很简单,它没有把单词的下文融合进来,这限制了其在更多应用场景的效果,比如阅读理解这种任务,在做任务的时候是可以允许同时看到上文和下文一起做决策的。如果预训练时候不把单词的下文嵌入到Word Embedding中,是很吃亏的,白白丢掉了很多信息。
Transformer是个叠加的“自注意力机制(Self Attention)”构成的深度网络,是目前NLP里最强的特征提取器,注意力这个机制在此被发扬光大,从任务的配角不断抢戏,直到Transformer一跃成为踢开RNN和CNN传统特征提取器,荣升头牌,大红大紫。
attention: https://zhuanlan.zhihu.com/p/37601161
transformer1: https://jalammar.github.io/illustrated-transformer/
transformer2: http://nlp.seas.harvard.edu/2018/04/03/attention.html
GPT在第二阶段如何使用?
首先,下游任务需要改造成和GPT网络结构是一样的。
然后,在下游任务中,第一部使用预训练好的参数初始化GPT网络结构,这样通过GPT学到的语言知识就可以应用于当前任务。
再次,可以用当前任务训练网络,进行fine-tuning,使得网可以更好的解决当前问题。
这里引入了一个新问题:对于NLP各种花样的不同任务,怎么改造才能靠近GPT的网络结构呢?
GPT论文给了一个改造施工图如上,其实也很简单:对于分类问题,不用怎么动,加上一个起始和终结符号即可;对于句子关系判断问题,比如Entailment,两个句子中间再加个分隔符即可;对文本相似性判断问题,把两个句子顺序颠倒下做出两个输入即可,这是为了告诉模型句子顺序不重要;对于多项选择问题,则多路输入,每一路把文章和答案选项拼接作为输入即可。从上图可看出,这种改造还是很方便的,不同任务只需要在输入部分施工即可。
Bert
Bert采用和GPT完全相同的两阶段模型,首先是语言模型预训练;其次是使用Fine-Tuning模式解决下游任务。和GPT的最主要不同在于在预训练阶段采用了类似ELMO的双向语言模型,当然另外一点是语言模型的数据规模要比GPT大。
第二阶段,Fine-Tuning阶段,这个阶段的做法和GPT是一样的。
绝大部分NLP问题可以归入上图所示的四类任务中:
- 序列标注:这是最典型的NLP任务,比如中文分词,词性标注,命名实体识别,语义角色标注等都可以归入这一类问题,它的特点是句子中每个单词要求模型根据上下文都要给出一个分类类别。
- 分类任务: 常见的文本分类,情感计算等都可以归入这一类。它的特点是不管文章有多长,总体给出一个分类类别即可。
- 句子关系判断: 比如Entailment,QA,语义改写,自然语言推理等任务都是这个模式,它的特点是给定两个句子,模型判断出两个句子是否具备某种语义关系
- 生成式任务: 比如机器翻译,文本摘要,写诗造句,看图说话等都属于这一类。它的特点是输入文本内容后,需要自主生成另外一段文字。
Bert如何改造输入输出部分使得大部分NLP任务都可以使用Bert预训练好的模型参数?
- 句子关系类任务:和GPT类似,输入部分加上一个起始和终结符号,句子之间加个分隔符即可;对于输出来说,把第一个起始符号对应的Transformer最后一层位置上面串接一个softmax分类层即可。
- 分类问题: 与GPT一样,只需要增加起始和终结符号,输出部分和句子关系判断任务类似改造
- 序列标注问题:输入部分和单句分类是一样的,只需要输出部分Transformer最后一层每个单词对应位置都进行分类即可。
- 生成类任务: 只需要附着在S2S结构上,encoder部分是个深度Transformer结构,decoder部分也是个深度Transformer结构。根据任务选择不同的预训练数据初始化encoder和decoder即可。或直接在单个Transformer结构上加装隐层产生输出也是可以的。
NLP四大类任务都可以比较方便地改造成Bert能够接受的方式。这其实是Bert的非常大的优点,这意味着它几乎可以做任何NLP的下游任务,具备普适性,这是很强的。
梳理下几个模型之间的演进关系。从上图可见,Bert其实和ELMO及GPT存在千丝万缕的关系,比如如果我们把GPT预训练阶段换成双向语言模型,那么就得到了Bert;而如果我们把ELMO的特征抽取器换成Transformer,那么我们也会得到Bert。所以你可以看出:Bert最关键两点,一点是特征抽取器采用Transformer;第二点是预训练的时候采用双向语言模型。
那么新问题来了:对于Transformer来说,怎么才能在这个结构上做双向语言模型任务呢?