预训练语言模型的发展
reference:
https://zhuanlan.zhihu.com/p/49271699
https://zhuanlan.zhihu.com/p/353054197
- 第一代PTMs:目标是学习到好的word embeddings(词向量,例如一个词对应到一个200维度的向量),然后模型本身就被丢弃了。例如Word2Vec,GloVe。虽然这些pre-trained embeddings可以捕捉到词的“部分”语义信息,它们大多数是上下文无关的,无法捕捉到文脉中的更高级别的抽象和概念,例如多义词,语法结构,语义角色,以及指代分析。
- 第二代PTMs:集中在学习基于文脉的词向量表示,保留模型本身。例如,CoVe, ELMo, OpenAI GPTx以及BERT。在应用到下游任务的时候,模型本身(例如多层Transformer’s Encoder Layers)会被继续使用。
1. Word Embedding
1.1 语言表示学习
好的语言表示,应该能够捕捉文本数据中的:隐含的语法规则,常识知识。例如,词汇含义,语法结构,语义角色,甚至到语学方面(指代消解等)。
语言表示学习的主要思想为:用低维实数向量(当然也有fp32, fp16, int8等单浮点数和8-bit整数的向量)来表示一段文本,虽然每个维度的浮点数没有具体的含义,但是向量整体表示了具体的概念。
有两种词嵌入(word embedding)的方法:上下文无关的(文脉无关的)和文脉相关的。其区别就在于一个词的嵌入表示vector是否根据其所在的context而动态发生变化。
1.2 语言模型
语言模型是为了衡量哪个句子更像一句话,核心函数P的思想是根据句子中前面的一系列前导单词预测跟的单词的概率大小(理论上,可以引入单词上下文联合预测单词的出现概率)、
若使用神经网络结构去实现语言模型的任务,即要求训练后的网络能够做到:输入一句话的前面几个单词,网络能够输出后面紧跟的单词应该是哪个。
(1)原始的神经网络语言模型(NNLM,2003)
训练过程:学习任务是输入某个句中单词 Wt=“Bert” 前面句子的t-1个单词,要求网络正确预测单词Bert,即最大化:P(Wt=“Bert”|W1,W2,…W(t−1);θ)
- 前面任意单词 Wi 用Onehot编码(比如:0001000)作为原始单词输入;
- 之后乘以矩阵Q后获得向量 C(Wi) ;
- 每个单词的 C(Wi) 拼接,上接隐层,然后接softmax去预测后面应该后续接哪个单词。
这个 C(Wi) 是什么?这其实就是单词对应的Word Embedding值,那个矩阵Q包含V行,V代表词典大小,每一行内容代表对应单词的Word embedding值。只不过Q的内容也是网络参数,需要学习获得,训练刚开始用随机值初始化矩阵Q,当这个网络训练好之后,矩阵Q的内容被正确赋值,每一行代表一个单词对应的Word embedding值。
所以,通过这个网络学习语言模型任务,这个网络不仅自己能够根据上文预测后接单词是什么,同时获得一个副产品,就是那个矩阵Q,这就是单词的Word Embedding是被如何学会的。
1.3 用语言模型做Word Embedding的工具
1.3.1 Word2Vec (2013)
Word2Vec的网络结构与NNLM基本类似,但是训练方法有所不同(NNLM的训练方式为:输入一个单词的上文,去预测这个单词)。Word2Vec有两种训练方法:
- CBOW:从一个句子里面把一个词抠掉,用这个词的上文和下文去预测被抠掉的这个词
- Skip-gram:与CBOW相反,输入某个单词,要求网络预测它的上下文单词
Word2Vec和NNLM训练方式不一样的原因在于:
- NNLM的主要任务是要学习一个解决语言模型任务的网络结构,语言模型就是要看到上文预测下文,而word embedding只是一个副产品;
- Word2Vec目标单纯就是要word embedding的,这是主产品。
1.3.2 Glove
1.4 Word Embedding是一个标准的预训练过程
如何在下游任务中使用Word Embedding?
以QA下游任务为例,即:给定一个问题X,给定另一个句子Y,要判断句子Y是否是问题X的正确答案。假设所设计的网络如上图所示,获取Word Embedding 的方法与NNLM是一样的,学习到的网络参数矩阵Q的作用等价于将网络Onehot层映射到embedding层,因此Word Embedding等价于把Onehot层到embedding层的网络用预训练好的参数矩阵Q初始化了。下游NLP任务在使用Word Embedding的时候有两种做法:①Frozen:就是Word Embedding那层网络参数固定不动;②Fine-Tuning:就是Word Embedding这层参数使用新的训练集合训练也需要跟着训练过程更新掉。
1.5 Word Embedding存在的问题——多义词问题
Word Embedding其实对于很多下游NLP任务是有帮助的,但是效果其实没有那么好,问题在于Word Embedding存在的多义词问题。
对于多义词,Word Embedding是无法进行区分的。以上图为例,不论什么上下文句子经过word2vec,都是预测相同的单词bank,而同一个单词占用一行的参数空间,这就导致了两种不同的上下文信息被编码到相同的word embedding空间中去。
ELMO提供了一种简洁优雅的解决方案。
2. 从Word Embedding到ELMO
ELMO即“Embedding from Language Models”,是一种基于特征融合的预训练方法。
- 之前的Word Embedding方法本质上是静态的方式,也就是训练好之后每个单词的表达就固定住了,以后使用的时候,不论新句子上下文单词是什么,这个单词的Word Embedding不会跟着上下文场景的变化而改变(所以对于比如Bank这个词,它事先学好的Word Embedding中混合了几种语义 ,在应用中来了个新句子,即使从上下文中(比如句子包含money等词)明显可以看出它代表的是“银行”的含义,但是对应的Word Embedding内容也不会变,它还是混合了多种语义。)
- ELMO的本质思想是:事先用语言模型学好一个单词的Word Embedding,此时多义词无法区分;在实际使用Word Embedding的时候,单词已经具备了特定的上下文了,这个时候根据上下文单词的语义去调整单词的Word Embedding表示,这样经过调整后的Word Embedding更能表达在这个上下文中的具体含义,自然也就解决了多义词的问题了。所以ELMO本身是个根据当前上下文对Word Embedding动态调整的思路。
ELMO采用了典型的两阶段训练过程:
- 第一阶段:利用语言模型进行预训练。 如上图所示,网络结构采用双层LSTM,目前语言模型训练的任务目标是根据单词 Wi 的上下文去正确预测单词 Wi , Wi 之前的单词序列Context-before称为上文,之后的单词序列Context-after称为下文。图中左端的前向双层LSTM代表正方向编码器,输入的是从左到右顺序的除了预测单词外 Wi 的上文Context-before;右端的逆向双层LSTM代表反方向编码器,输入的是从右到左的逆序的句子下文Context-after;每个编码器的深度都是两层LSTM叠加(这个网络结构其实在NLP中是很常用的)。使用这个网络结构利用大量语料做语言模型任务就能预先训练好这个网络,如果训练好这个网络后,输入一个新句子 Snew ,句子中每个单词都能得到对应的三个Embedding:最底层是单词的Word Embedding,往上走是第一层双向LSTM中对应单词位置的Embedding,这层编码单词的句法信息更多一些;再往上走是第二层LSTM中对应单词位置的Embedding,这层编码单词的语义信息更多一些。也就是说,ELMO的预训练过程不仅仅学会单词的Word Embedding,还学会了一个双层双向的LSTM网络结构,而这两者后面都有用。
- 第二阶段:在做下游任务时,从预训练网络中提取对应单词的网络各层的Word Embedding作为新特征补充到下游任务中 以QA下游任务为例,此时对于问句X,可以先将句子X作为预训练好的ELMO网络的输入,这样句子X中每个单词在ELMO网络中都能获得对应的三个Embedding,之后给予这三个Embedding中的每一个Embedding一个权重a,根据各自权重累加求和,将三个Embedding整合成一个,然后将整合后的这个Embedding作为X句在自己任务的那个网络结构中对应单词的输入,以此作为补充的新特征给下游任务使用。对于QA的回答句子Y也是如此处理。因为ELMO给下游提供的是每个单词的特征形式,所以这一类预训练的方法被称为“Feature-based Pre-Training”。
- TagLM采用类似ELMO的思路做命名实体识别任务的过程:
2.1 ELMO解决多义词问题
静态Word Embedding无法解决多义词的问题,那么ELMO引入上下文动态调整单词的embedding后多义词问题解决了吗?
如上图所示:对于Glove训练出的Word Embedding来说,多义词比如play,根据它的embedding 找出的最接近的其它单词大多数集中在体育领域,这很明显是因为训练数据中包含play的句子中体 育领域的数量明显占优导致;而使用ELMO,根据上下文动态调整后的embedding不仅能够找出对 应的“演出”的相同语义的句子,而且还可以保证找出的句子中的play对应的词性也是相同的,这是 超出期待之处。之所以会这样,是因为第一层LSTM编码了很多句法信息,这在 这里起到了重要作用。
2.2 ELMO的缺点(与BERT/GPT对比)
- LSTM抽取特征的能力远弱于Transformer:在特征抽取器选择方面,ELMO使用了LSTM而不是Transformer,Transformer是谷歌在17年做机器翻译任务的“Attention is all you need”的论文中提出的,引起了相当大的反响,很多研究已经证明了Transformer提取特征的能力是要远强于LSTM的。如果ELMO采取Transformer作为特征提取器,那么估计Bert的反响远不如现在的这种火爆场面。
- 拼接方式双向融合特征融合能力偏弱:ELMO采取双向拼接这种融合特征的能力可能比Bert一体化的融合特征方式弱,但是,这只是一种从道理推断产生的怀疑,目前并没有具体实验说明这一点。
如果把ELMO这种预训练方法和图像领域的预训练方法对比,发现两者模式看上去还是有很大差异的。除了以ELMO为代表的这种基于特征融合的预训练方法外,NLP里还有一种典型做法,这种做法和图像领域的方式就是看上去一致的了,一般将这种方法称为“基于Fine-tuning的模式”,而GPT就是这一模式的典型开创者。
3. 对比总结
3.1 无上下文的词嵌入与上下文相关的词嵌入对比:
-
无上下文的词嵌入
对于词x和词表v: x∈v,将x映射到一个向量ex∈RDe ,使用一个查询表:D矩阵(每一列对应到一个词),De为超参数,代表了词向量的维度(50/100/200……)
存在的问题:
- 词嵌入为静态的,每个token固定一个embedding(即使表示不同的意思)
- OOV(未登录词)问题,即一个词不在预先定义好的词表里面的时候,就无法查询到其词向量。为了解决这个问题,有类似CharCNN, FastText,以及BERT中使用的Byte-Pair Encoding (BPE)等方案。主要思想即拆字,例如英文的单词被拆成类似prefix+stem+suffix这样的,中文就是按照字来建模(把中文字当成一个image,使用一个CNN model进行学习,得到embedding),等等。
-
上下文相关的词嵌入
为了解决多义词问题,以及基于单词天然和语境相关的考量,需要区分不同语境下的词的语义。
给定一个文本序列: x1,x2,…,xT ;每个token xt∈V 可以是一个word或者sub-word,则该序列对应的上下文相关表示可以表示为:[h1, h2,…,hT] = fenc(x1,x2,…,xT),其中,fenc为神经编码器,ht为xt对应的语境嵌入(ht与全体x1,x2,…,xT都相关)。
3.2 神经语境编码器分类
3.2.1 序列模型
- 基于CNN,设定窗口,然后对窗口内的若干词进行卷积操作,得到这个窗口内的词的嵌入表示;
- 基于LSTM/GRU的,基于单向(从左向右)或者双向的RNN模型,对整个序列进行建模,得到每个词的语境下的嵌入表示
3.2.2 非序列模型
- 例如树结构,图结构等等,例如Recursive NN (例如,建立在语法树上的对叶节点的单词和非叶节点的短语类别的嵌入表示),TreeLSTM, GCN等新型神经网络结构。很多都依赖于语法树,例如PCFG, dependency parsers’ trees等。
- 全连接自注意力模型:使用全连接图,来建立任意两个词之间的关系,并通过大规模无标注数据,让模型自动学习结构化信息。通常,两个词之间的”连接权重“会被自注意力机制动态计算。典型的代表就是Transformer中的multi-head self-attention网络结构。
3.3.3 分析
如上图所示,(a)为卷积网络(窗口=3),h2由x1,x2,x3决定;(b)为循环神经网络(LSTM/GRU……),h2由h1,h3和x2决定;©为全连接自注意力结构。
- 序列模型:局部性偏见,难以捕捉长距离交互;但是容易训练,并在若干NLP任务上取得了不错的结果
- 非序列模型(代表为Transformer):更强大,使用的参数更多,可以更好地覆盖长距离以来问题;但是需要大规模训练预料,容易在中小规模数据上过拟合。
3.4 为什么要预训练
对于NLP任务,缺乏大规模人工标注的数据,但是有超大规模的文本库
- 基于大规模文本库的预训练可以很好的学习到通用的语言表示,有助于下游应用任务;
- 提供更好的模型初始化方法,从而得到具有更好泛化能力的模型,并且加速目标任务的收敛速度;
- 可以被看成一种正则化的方法,防止模型在中小规模标注数据上过拟合。
4. 从Word Embedding到GPT
GPT即“Generative Pre-Training”,指生成式的预训练。
GPT也采用两阶段过程,第一个阶段是利用语言模型进行预训练,第二阶段通过Fine-tuning的模式解决下游任务。
- 第一阶段:预训练过程,与ELMO类似,主要不同在于两点:①特征抽取器不是用的RNN,而是用的Transformer,其特征抽取能力要强于RNN;②GPT的预训练虽然仍然是以语言模型作为目标任务,但是采用的是单向的语言模型,即:语言模型训练的任务目标是根据 Wi 单词的上下文去正确预测单词 Wi , Wi 之前的单词序列Context-before称为上文,之后的单词序列Context-after称为下文。ELMO在做语言模型预训练的时候,预测单词 Wi 同时使用了上文和下文,而GPT则只采用Context-before这个单词的上文来进行预测,而抛开了下文。这个选择现在看不是个太好的选择,原因很简单,它没有把单词的下文融合进来,这限制了其在更多应用场景的效果,比如阅读理解这种任务,在做任务的时候是可以允许同时看到上文和下文一起做决策的。
transformer学习:
Jay Alammar可视化介绍Transformer:https://jalammar.github.io/illustrated-transformer/
哈佛大学NLP研究组:http://nlp.seas.harvard.edu/2018/04/03/attention.html
- 第二阶段:Fine-tuning过程 对于各种NLP下游任务,如何进行改造?
- 对于分类问题,不用怎么动,加上一个起始和终结符号即可;
- 对于句子关系判断问题,比如Entailment,两个句子中间再加个分隔符即可;
- 对文本相似性判断问题,把两个句子顺序颠倒下做出两个输入即可,这是为了告诉模型句子顺序不重要;
- 对于多项选择问题,则多路输入,每一路把文章和答案选项拼接作为输入即可。
4.1 GPT的缺点(与BERT对比)
- 如果把语言模型改造成双向效果可能会更好
5. 从Word2Vec/ELMO/GPT到BERT
Bert采用和GPT完全相同的两阶段模型,首先是语言模型预训练;其次是使用Fine-Tuning模式解决下游任务。和GPT的最主要不同在于在预训练阶段采用了类似ELMO的双向语言模型,当然另外一点是语言模型的数据规模要比GPT大。
- 第一阶段:预训练阶段,与GPT相同;
- 第二阶段:Fine-Tuning阶段,与GPT类似。
5.1 NLP的几类问题
- 序列标注(句子中每个单词要求模型根据上下文都要给出一个分类类别):分词/POS Tag/NER/语义标注……
- 分类任务(不管文章有多长,总体给出一个分类类别即可):文本分类/情感计算……
- 句子关系判断(给定两个句子,模型判断出两个句子是否具备某种语义关系):Entailment/QA//语义改写/自然语言推理……
- 生成式任务(输入文本内容后,需要自主生成另外一段文字):机器翻译/文本摘要……
5.2 BERT如何改造下游任务
- 对于句子关系类任务,很简单,和GPT类似,加上一个起始和终结符号,句子之间加个分隔符即可。对于输出来说,把第一个起始符号对应的Transformer最后一层位置上面串接一个softmax分类层即可。
- 对于分类问题,与GPT一样,只需要增加起始和终结符号,输出部分和句子关系判断任务类似改造;
- 对于序列标注问题,输入部分和单句分类是一样的,只需要输出部分Transformer最后一层每个单词对应位置都进行分类即可。
- 对于机器翻译或者文本摘要,聊天机器人这种生成式任务,同样可以稍作改造即可引入Bert的预训练成果。只需要附着在S2S结构上,encoder部分是个深度Transformer结构,decoder部分也是个深度Transformer结构。根据任务选择不同的预训练数据初始化encoder和decoder即可。这是相当直观的一种改造方法。当然,也可以更简单一点,比如直接在单个Transformer结构上加装隐层产生输出也是可以的。
不论如何,从这里可以看出,NLP四大类任务都可以比较方便地改造成Bert能够接受的方式。这其实是Bert的非常大的优点,这意味着它几乎可以做任何NLP的下游任务,具备普适性,这是很强的。
5.3 Word2Vec、ELMO、GPT、BERT四者的关系
从上图可见,如果我们把GPT预训练阶段换成双向语言模型,那么就得到了Bert;而如果我们把ELMO的特征抽取器换成Transformer,那么我们也会得到Bert。所以Bert最关键两点在于:①特征抽取器采用Transformer;②预训练的时候采用双向语言模型。
5.4 如何使用transformer做双向语言模型任务
- 直观的思路:参考ELMO网络结构,将两个LSTM替换为两个transformer,一个负责正向,一个负责反向特征提取。
- BERT的做法:与CBOW方法类似,在做语言模型任务的时候,把要预测的单词抠掉,然后根据它的上文Context-Before和下文Context-after去预测单词。
5.4.1 BERT模型
BERT模型本身的创新点在于:①Masked 双向语言模型;②Next Sentence Prediction
随机选择语料中15%的单词,把它抠掉,也就是用[Mask]掩码代替原始单词,然后要求模型去正确预测被抠掉的单词。但是这里有个问题:训练过程大量看到[mask]标记,但是真正后面用的时候是不会有这个标记的,这会引导模型认为输出是针对[mask]这个标记的,但是实际使用又见不到这个标记,这自然会有问题。为了避免这个问题,Bert改造了一下,15%的被选中要执行[mask]任务的单词中,只有80%真正被替换成[mask]标记,10%被随机替换成另外一个单词,10%情况这个单词还待在原地不做改动。
- Masked 双向语言模型:本质思想与CBOW相似,细节上有所改进。
- Next Senctence Prediction:指的是做语言模型预训练的时候,分两种情况选择两个句子,一种是选择语料中真正顺序相连的两个句子;另外一种是第二个句子从语料库中随机选择一个拼到第一个句子后面。要求模型除了做上述的Masked语言模型任务外,附带再做个句子关系预测,判断第二个句子是不是真的是第一个句子的后续句子。之所以这么做,是考虑到很多NLP任务是句子关系判断任务,单词预测粒度的训练到不了句子关系这个层级,增加这个任务有助于下游句子关系判断任务。所以可以看到,它的预训练是个多任务过程。
5.4.2 BERT模型的输入输出
BERT的输入:
BERT的输入部分是个线性序列,两个句子通过分隔符[SEP]分割,最前面和最后增加两个标识符号。每个单词有三个embedding:把单词对应的三个embedding叠加,就形成了Bert的输入。
- 位置信息embedding:这是因为NLP中单词顺序是很重要的特征,需要在这里对位置信息进行编码;
- 单词embedding:这个就是之前一直提到的单词embedding;
- 句子embedding,因为前面提到训练数据都是由两个句子构成的,那么每个句子有个句子整体的embedding项对应给每个单词。
BERT的输出:
5.4.3 BERT的评价与意义
Bert借鉴了ELMO,GPT及CBOW,主要提出了Masked 语言模型及Next Sentence Prediction,但是这里Next Sentence Prediction基本不影响大局,而Masked LM明显借鉴了CBOW的思想。所以说Bert的模型没什么大的创新,更像最近几年NLP重要进展的集大成者。
如果归纳一下这些进展就是:首先是两阶段模型,第一阶段双向语言模型预训练,这里注意要用双向而不是单向,第二阶段采用具体任务Fine-tuning或者做特征集成;第二是特征抽取要用Transformer作为特征提取器而不是RNN或者CNN;第三,双向语言模型可以采取CBOW的方法去做(细节问题,不算太关键,前两个因素比较关键)。
Bert最大的亮点在于效果好及普适性强,几乎所有NLP任务都可以套用Bert这种两阶段解决思路,而且效果应该会有明显提升。
6. BERT的变体
7. GPT-X
8. 预训练过程的本质
上图给出了NLP在PTMs思想下的一般性神经网络架构,例如BERT,从从word sequence出发,经过上下文相关编码器之后,得到H=[h1, …, hn]张量。然后H再扔给具体任务相关的模型,进行下一步fine-tuning。
预训练过程本质上预训练是通过设计好一个网络结构来做语言模型任务,然后把大量甚至是无穷尽的无标注的自然语言文本利用起来,预训练任务把大量语言学知识抽取出来编码到网络结构中,当手头任务带有标注信息的数据有限时,这些先验的语言学特征当然会对手头任务有极大的特征补充作用,因为当数据有限的时候,很多语言学现象是覆盖不到的,泛化能力就弱,集成尽量通用的语言学知识自然会加强模型的泛化能力。如何引入先验的语言学知识其实一直是NLP尤其是深度学习场景下的NLP的主要目标之一,不过一直没有太好的解决办法,而ELMO/GPT/Bert的这种两阶段模式看起来无疑是解决这个问题自然又简洁的方法,这也是这些方法的主要价值所在。
对于NLP的发展:
- 需要更强的特征抽取器,尝试超越transformer
- 如何优雅(简洁)地引入大量无监督数据中包含的语言学知识