reference:
https://zhuanlan.zhihu.com/p/49271699
https://zhuanlan.zhihu.com/p/353054197
好的语言表示,应该能够捕捉文本数据中的:隐含的语法规则,常识知识。例如,词汇含义,语法结构,语义角色,甚至到语学方面(指代消解等)。
语言表示学习的主要思想为:用低维实数向量(当然也有fp32, fp16, int8等单浮点数和8-bit整数的向量)来表示一段文本,虽然每个维度的浮点数没有具体的含义,但是向量整体表示了具体的概念。
有两种词嵌入(word embedding)的方法:上下文无关的(文脉无关的)和文脉相关的。其区别就在于一个词的嵌入表示vector是否根据其所在的context而动态发生变化。
语言模型是为了衡量哪个句子更像一句话,核心函数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是被如何学会的。
Word2Vec的网络结构与NNLM基本类似,但是训练方法有所不同(NNLM的训练方式为:输入一个单词的上文,去预测这个单词)。Word2Vec有两种训练方法:
Word2Vec和NNLM训练方式不一样的原因在于:
- NNLM的主要任务是要学习一个解决语言模型任务的网络结构,语言模型就是要看到上文预测下文,而word embedding只是一个副产品;
- Word2Vec目标单纯就是要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这层参数使用新的训练集合训练也需要跟着训练过程更新掉。
Word Embedding其实对于很多下游NLP任务是有帮助的,但是效果其实没有那么好,问题在于Word Embedding存在的多义词问题。
对于多义词,Word Embedding是无法进行区分的。以上图为例,不论什么上下文句子经过word2vec,都是预测相同的单词bank,而同一个单词占用一行的参数空间,这就导致了两种不同的上下文信息被编码到相同的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”。
静态Word Embedding无法解决多义词的问题,那么ELMO引入上下文动态调整单词的embedding后多义词问题解决了吗?
如上图所示:对于Glove训练出的Word Embedding来说,多义词比如play,根据它的embedding 找出的最接近的其它单词大多数集中在体育领域,这很明显是因为训练数据中包含play的句子中体 育领域的数量明显占优导致;而使用ELMO,根据上下文动态调整后的embedding不仅能够找出对 应的“演出”的相同语义的句子,而且还可以保证找出的句子中的play对应的词性也是相同的,这是 超出期待之处。之所以会这样,是因为第一层LSTM编码了很多句法信息,这在 这里起到了重要作用。
- 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就是这一模式的典型开创者。
无上下文的词嵌入
对于词x和词表v: x∈v,将x映射到一个向量ex∈RDe ,使用一个查询表:D矩阵(每一列对应到一个词),De为超参数,代表了词向量的维度(50/100/200……)
存在的问题:
上下文相关的词嵌入
为了解决多义词问题,以及基于单词天然和语境相关的考量,需要区分不同语境下的词的语义。
给定一个文本序列: x1,x2,…,xT ;每个token xt∈V 可以是一个word或者sub-word,则该序列对应的上下文相关表示可以表示为:[h1, h2,…,hT] = fenc(x1,x2,…,xT),其中,fenc为神经编码器,ht为xt对应的语境嵌入(ht与全体x1,x2,…,xT都相关)。
如上图所示,(a)为卷积网络(窗口=3),h2由x1,x2,x3决定;(b)为循环神经网络(LSTM/GRU……),h2由h1,h3和x2决定;©为全连接自注意力结构。
对于NLP任务,缺乏大规模人工标注的数据,但是有超大规模的文本库
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,两个句子中间再加个分隔符即可;
- 对文本相似性判断问题,把两个句子顺序颠倒下做出两个输入即可,这是为了告诉模型句子顺序不重要;
- 对于多项选择问题,则多路输入,每一路把文章和答案选项拼接作为输入即可。
- 如果把语言模型改造成双向效果可能会更好
Bert采用和GPT完全相同的两阶段模型,首先是语言模型预训练;其次是使用Fine-Tuning模式解决下游任务。和GPT的最主要不同在于在预训练阶段采用了类似ELMO的双向语言模型,当然另外一点是语言模型的数据规模要比GPT大。
不论如何,从这里可以看出,NLP四大类任务都可以比较方便地改造成Bert能够接受的方式。这其实是Bert的非常大的优点,这意味着它几乎可以做任何NLP的下游任务,具备普适性,这是很强的。
从上图可见,如果我们把GPT预训练阶段换成双向语言模型,那么就得到了Bert;而如果我们把ELMO的特征抽取器换成Transformer,那么我们也会得到Bert。所以Bert最关键两点在于:①特征抽取器采用Transformer;②预训练的时候采用双向语言模型。
BERT模型本身的创新点在于:①Masked 双向语言模型;②Next Sentence Prediction
随机选择语料中15%的单词,把它抠掉,也就是用[Mask]掩码代替原始单词,然后要求模型去正确预测被抠掉的单词。但是这里有个问题:训练过程大量看到[mask]标记,但是真正后面用的时候是不会有这个标记的,这会引导模型认为输出是针对[mask]这个标记的,但是实际使用又见不到这个标记,这自然会有问题。为了避免这个问题,Bert改造了一下,15%的被选中要执行[mask]任务的单词中,只有80%真正被替换成[mask]标记,10%被随机替换成另外一个单词,10%情况这个单词还待在原地不做改动。
BERT的输入:
BERT的输入部分是个线性序列,两个句子通过分隔符[SEP]分割,最前面和最后增加两个标识符号。每个单词有三个embedding:
- 位置信息embedding:这是因为NLP中单词顺序是很重要的特征,需要在这里对位置信息进行编码;
- 单词embedding:这个就是之前一直提到的单词embedding;
- 句子embedding,因为前面提到训练数据都是由两个句子构成的,那么每个句子有个句子整体的embedding项对应给每个单词。
把单词对应的三个embedding叠加,就形成了Bert的输入。
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这种两阶段解决思路,而且效果应该会有明显提升。
上图给出了NLP在PTMs思想下的一般性神经网络架构,例如BERT,从从word sequence出发,经过上下文相关编码器之后,得到H=[h1, …, hn]张量。然后H再扔给具体任务相关的模型,进行下一步fine-tuning。
预训练过程本质上预训练是通过设计好一个网络结构来做语言模型任务,然后把大量甚至是无穷尽的无标注的自然语言文本利用起来,预训练任务把大量语言学知识抽取出来编码到网络结构中,当手头任务带有标注信息的数据有限时,这些先验的语言学特征当然会对手头任务有极大的特征补充作用,因为当数据有限的时候,很多语言学现象是覆盖不到的,泛化能力就弱,集成尽量通用的语言学知识自然会加强模型的泛化能力。如何引入先验的语言学知识其实一直是NLP尤其是深度学习场景下的NLP的主要目标之一,不过一直没有太好的解决办法,而ELMO/GPT/Bert的这种两阶段模式看起来无疑是解决这个问题自然又简洁的方法,这也是这些方法的主要价值所在。
对于NLP的发展: