NLP中的预训练技术发展史
从图像领域的预训练说起
自从深度学习火起来后,从预训练模型进行迁移学习就是做图像或者视频领域的一种高效又常规的做法。
那么图像领域怎么做预训练呢?
- 对于图像来说一般是CNN的多层叠加网络结构,可以先用某个训练集合比如训练集合A或者训练集合B对这个网络进行预先训练,在A任务上或者B任务上学会网络参数,然后存起来以备后用。
- 假设我们面临第三个任务C,网络结构采取相同的网络结构,在比较浅的几层CNN结构,网络参数初始化的时候可以加载A任务或者B任务学习好的参数,其它CNN高层参数仍然随机初始化。
- 之后我们用C任务的训练数据来训练网络,此时有两种做法:
- 一种是浅层加载的参数在训练C任务过程中不动,这种方法被称为“Frozen”;
- 另外一种是底层网络参数尽管被初始化了,在C任务训练过程中仍然随着训练的进程不断改变,这种一般叫“Fine-Tuning”,顾名思义,就是更好地把参数进行调整使得更适应当前的C任务。一般图像或者视频领域要做预训练一般都这么做。
预训练模型有以下几个好处:
- 首先,如果手头训练集数据量较少的话,由于Resnet/Densenet/Inception等网络结构层数深参数庞大,直接训练非常容易过拟合,但是如果其中大量参数通过大的训练集合比如ImageNet预先训练好直接拿来初始化大部分网络结构参数,然后再用C任务手头比较可怜的数据量上Fine-tuning过程去调整参数让它们更适合解决C任务,那事情就好办多了。
- 即使手头任务训练数据较多,加个预训练过程也能极大加快任务训练的收敛速度,所以这种预训练方式是老少皆宜的解决方案,另外疗效又好,所以在做图像处理领域很快就流行开来。
那么问题来了,为何预训练和迁移学习这个方法是可行的呢?
- 根据一些相关的论文研究,对于层级的CNN结构来说,不同层级的神经元学习到了不同类型的图像特征,由底向上特征形成层级结构。
- 比如一个人脸识别任务,训练好网络后,把每层神经元学习到的特征可视化。最底层的神经元学到的是点和线等特征,再往上层学到的是五官的轮廓,再上学到的是人脸的轮廓,逐步形成了特征的层级结构,最底层的特征往往是自然界中普遍存在的边角线弧线等底层基础特征,越往上层则是具体的物体的概念
- 正因为此,所以通过大规模预训练好的网络参数,尤其是底层的网络参数抽取出特征跟具体任务越无关,具备任务的通用性,所以这是为何一般用底层预训练好的参数初始化新任务网络参数的原因。
- 而高层特征跟任务关联较大,所以最终采用Fine-tuning用新数据集学习高层特征概念。
那么问题又来了,既然预训练在CV证实了效果惊人,那NLP呢?
其实2003年的word embedding就是NLP里的早期预训练技术,一般加到下游任务里,都能有1到2个点的性能提升,只是没有那么耀眼的成功而已。
直到2013年最火的用语言模型,谷歌的Word2Vec横空出世,NLP预训练模型才逐步进入视野。
Word2Vec有两种训练方法:
- 一种叫CBOW,核心思想是从一个句子里面把一个词抠掉,用这个词的上文和下文去预测被抠掉的这个词;
- 第二种叫做Skip-gram,和CBOW正好反过来,输入某个单词,要求网络预测它的上下文单词。
- 而你回头看看,NNLM是怎么训练的?是输入一个单词的上文,去预测这个单词。这是有显著差异的。为什么Word2Vec这么处理?原因很简单,因为Word2Vec和NNLM不一样,NNLM的主要任务是要学习一个解决语言模型任务的网络结构,语言模型就是要看到上文预测下文,而word embedding只是无心插柳的一个副产品。但是Word2Vec目标不一样,它单纯就是要word embedding的,这是主产品,所以它完全可以随性地这么去训练网络。
使用Word2Vec,就可以获得每个单词的Word Embedding,上图的例子可以看出效果还是很不错的,一个单词表达成Word Embedding后,很容易找出语义相近的其它词汇。
我们的主题是预训练,那么问题是Word Embedding这种做法能算是预训练吗?这其实就是标准的预训练过程。要理解这一点要看看学会Word Embedding后下游任务是怎么用它的。
假设如上图所示,我们有个NLP的下游任务,比如QA。
所谓问答问题,指的是给定一个问题X,给定另外一个句子Y,要判断句子Y是否是问题X的正确答案。它的使用就是把句子中每个单词以Onehot形式作为输入,然后乘以学好的Word Embedding矩阵Q,就直接取出单词对应的Word Embedding了。
这乍看上去好像是个查表操作,不像是预训练的做法是吧?其实不然,那个Word Embedding矩阵Q其实就是网络Onehot层到embedding层映射的网络参数矩阵。所以使用Word Embedding等价于把Onehot层到embedding层的网络用预训练好的参数矩阵Q初始化了
。这跟前面讲的图像领域的低层预训练过程其实是一样的,区别无非Word Embedding只能初始化第一层网络参数,再高层的参数就无能为力了。下游NLP任务在使用Word Embedding的时候也类似图像有两种做法,一种是Frozen,就是Word Embedding那层网络参数固定不动;另外一种是Fine-Tuning,就是Word Embedding这层参数使用新的训练集合训练也需要跟着训练过程更新掉。
那么新问题来了,为什么这样训练及使用Word Embedding的效果没有期待中那么好呢?Word Embedding存在什么问题?
多义词问题。
一词多义在中英文中都是正常的现象。那么多义词对Word Embedding来说有什么负面影响?
如上图所示,比如多义词Bank有两个常用含义,但是Word Embedding在对bank这个单词进行编码的时候,是区分不开这两个含义的,在用语言模型训练的时候,不论什么上下文的句子经过word2vec,都是预测相同的单词bank,而同一个单词占的是同一行的参数空间,这导致两种不同的上下文信息都会编码到相同的word embedding空间里去。所以word embedding无法区分多义词的不同语义,这就是它的一个比较严重的问题。
从Word Embedding到ELMO
ELMO是“Embedding from Language Models”的简称,ELMO的论文题目:“Deep contextualized word representation”(深层语境化的词汇表征)更能体现其精髓,而精髓在哪里?
在此之前的Word Embedding本质上是个静态的方式,所谓静态指的是训练好之后每个单词的表达就固定住了,以后使用的时候,不论新句子上下文单词是什么,这个单词的Word Embedding不会跟着上下文场景的变化而改变,所以对于比如Bank这个词,它事先学好的Word Embedding中混合了几种语义 ,在应用中来了个新句子,即使从上下文中(比如句子包含money等词)明显可以看出它代表的是“银行”的含义,但是对应的Word Embedding内容也不会变,它还是混合了多种语义。
ELMO的本质思想是:我事先用语言模型学好一个单词的Word Embedding,此时多义词无法区分,不过这没关系。在我实际使用Word Embedding的时候,单词已经具备了特定的上下文了,这个时候我可以根据上下文单词的语义去调整单词的Word Embedding表示,这样经过调整后的Word Embedding更能表达在这个上下文中的具体含义,自然也就解决了多义词的问题了。所以ELMO本身是个根据当前上下文对Word Embedding动态调整的思路。
ELMO采用了典型的两阶段过程:
- 第一个阶段是利用语言模型进行预训练;
- 第二个阶段是在做下游任务时,从预训练网络中提取对应单词的网络各层的Word Embedding作为新特征补充到下游任务中。
上图展示的是其预训练过程,它的网络结构采用了双层双向LSTM,目前语言模型训练的任务目标是根据单词
$W_i$
的上下文去正确预测单词 $W_i$ , $W_i$ 之前的单词序列Context-before称为上文,之后的单词序列Context-after称为下文。
图中左端的前向双层LSTM代表正方向编码器,输入的是从左到右顺序的除了预测单词外 $W_i$ 的上文Context-before;右端的逆向双层LSTM代表反方向编码器,输入的是从右到左的逆序的句子下文Context-after;每个编码器的深度都是两层LSTM叠加。这个网络结构其实在NLP中是很常用的。使用这个网络结构利用大量语料做语言模型任务就能预先训练好这个网络,如果训练好这个网络后,输入一个新句子 $S_new$ ,句子中每个单词都能得到对应的三个Embedding:最底层是单词的Word Embedding,往上走是第一层双向LSTM中对应单词位置的Embedding,这层编码单词的句法信息更多一些;再往上走是第二层LSTM中对应单词位置的Embedding,这层编码单词的语义信息更多一些。
也就是说,ELMO的预训练过程不仅仅学会单词的Word Embedding,还学会了一个双层双向的LSTM网络结构,而这两者后面都有用。
那么预训练好网络结构后,如何给下游任务使用呢?
上图展示了下游任务的使用过程:
- 比如我们的下游任务仍然是QA问题,此时对于问句X,我们可以先将句子X作为预训练好的ELMO网络的输入,这样句子X中每个单词在ELMO网络中都能获得对应的三个Embedding.
- 之后给予这三个Embedding中的每一个Embedding一个权重a,这个权重可以学习得来,根据各自权重累加求和,将三个Embedding整合成一个。
- 然后将整合后的这个Embedding作为X句在自己任务的那个网络结构中对应单词的输入,以此作为补充的新特征给下游任务使用。这一类预训练的方法被称为“Feature-based Pre-Training”。
那么ELMO引入上下文动态调整单词的embedding后多义词问题几乎完美解决。上图给了个例子,使用ELMO,根据上下文动态调整后的embedding不仅能够找出对应的“演出”的相同语义的句子,而且还可以保证找出的句子中的play对应的词性也是相同的,这是超出期待之处。之所以会这样,是因为我们上面提到过,第一层LSTM编码了很多句法信息,这在这里起到了重要作用。
ELMO有什么值得改进的缺点:
- 首先,一个非常明显的缺点在特征抽取器选择方面,ELMO使用了LSTM而不是Transformer
- 另外一点,ELMO采取双向拼接这种融合特征的能力可能比Bert一体化的融合特征方式弱
ELMO这种预训练方法和图像领域的预训练方法对比,发现两者模式看上去还是有很大差异的。除了以ELMO为代表的这种基于特征融合的预训练方法外,NLP里还有一种典型做法,这种做法和图像领域的方式就是看上去一致的了,一般将这种方法称为“基于Fine-tuning的模式”,而GPT就是这一模式的典型开创者。
GPT的诞生
GPT是“Generative Pre-Training”的简称,从名字看其含义是指的生成式的预训练。
GPT也采用两阶段过程
- 第一个阶段是利用语言模型进行预训练
- 第二阶段通过Fine-tuning的模式解决下游任务。
主要不同在于两点:
- 首先,特征抽取器不是用的RNN,而是用的Transformer,Transformer的特征抽取能力是要强于RNN
- 其次,GPT的预训练虽然仍然是以语言模型作为目标任务,但是采用的是单向的语言模型,GPT只采用Context-before这个单词的上文来进行预测,而抛开了下文。
大杀器Bert
Bert采用和GPT完全相同的两阶段模型:
- 首先是语言模型预训练;
- 其次是使用Fine-Tuning模式解决下游任务。
- 和GPT的最主要不同在于在预训练阶段采用了类似ELMO的双向语言模型
- 另外一点是语言模型的数据规模要比GPT大。
Bert其实和ELMO及GPT存在千丝万缕的关系:
- 比如如果我们把GPT预训练阶段换成双向语言模型,那么就得到了Bert;
- 而如果我们把ELMO的特征抽取器换成Transformer,那么我们也会得到Bert。
- 所以你可以看出,Bert最关键两点,一点是特征抽取器采用Transformer;第二点是预训练的时候采用双向语言模型。
对于Transformer来说,怎么才能在这个结构上做双向语言模型任务呢?BERT用的就是前面提到了CBOW方法,它的核心思想是:在做语言模型任务的时候,我把要预测的单词抠掉,然后根据它的上文Context-Before和下文Context-after去预测单词。
从这里可以看出,Bert在模型方面其实没有太大创新,更像一个最近几年NLP重要技术的集大成者,Bert本身的效果好和普适性强才是最大的亮点。
Masked双向语言模型做法:
- 随机选择语料中15%的单词,把它抠掉,也就是用[Mask]掩码代替原始单词,然后要求模型去正确预测被抠掉的单词。
- 但是这里有个问题:训练过程大量看到[mask]标记,但是真正后面用的时候是不会有这个标记的,这会引导模型认为输出是针对[mask]这个标记的,但是实际使用又见不到这个标记,这自然会有问题。
- 为了避免这个问题,Bert改造了一下,15%的[mask]单词中,只有80%真正被替换成[mask]标记,10%被随机替换成另外一个单词,10%概率不变。
总结来说,bert最主要的意义在于:
- 近年来NLP重大突破的集大成者
- 充分利用了大量的无监督文本数据,将语言学知识融入其中
- 充分展示了transformer的特征提取能力
- 奠定了超大规模预训练+具体任务finetuning的二阶段训练方式
- 揭开了NLP超大规模预训练数据的的军备竞赛(只有大厂玩得动?)
本文参考张俊林博士的从Word Embedding到Bert模型—自然语言处理中的预训练技术发展史 ,仅供学习。
- 本文作者: Jason
- 本文链接: https://caicaijason.github.io/2019/11/22/NLP中的预训练技术发展史/
- 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!