完成日期:2019.08.12
内容从文章:Generalized Language Models整理翻译
GloVe,CBOW,SkipGram等浅层模型学习的Embedding存在一个严重的问题,那就是每个词只有一个固定的Embedding,完全忽略了词上下文环境的不同对语义的影响。
比如说:你别打扰他,他正在算账呢! 好了,这回算你赢,下回我再跟你算账!
又比如:这些苹果又大又红。 你刚刚买的苹果手机真不错。
明显,这两句中的“算账”和“苹果”完全是不同的含义。基于浅层模型学到的embedding更多学习的是词与词之间共现的一种概率分布,学习到的语义和结构的信息对比contextual语言模型还是有限的。
因此早期词嵌入的用法是将他们用作特定任务的外部特征,在一定程度上对模型性能的改进是有限的。
预训练的核心思想是借助深度学习模型复杂的结构和强大的非线性表示学习能力,学习到海量数据种存在的本质(知识),把这些知识以向量或者参数的形式存储起来,并通过feature或者parameter sharing的形式迁移到其他想相关的领域种。
在自然语言领域中,这些共享的embedding或隐含层状态(hidden state)或模型参数(model parameter)往往编码了丰富的词法、句法和语义信息。
Learned in Translation: Contextualized Word Vectors (McCann et al. 2017)
Cove,是上下文词向量(Contextual Word Vectors)的缩写,是一种由机器翻译领域中的Seq2Seq+Attention模型的Encoder学习得到的Word Embedding。和传统的Word Embedding不同,CoVe词向量表示的是整个输入句子的函数。
神经机器翻译( NMT )模型由标准的双层双向LSTM构成的encoder,和带Attention Module的双层单向LSTM构成的decoder组成。假设先采用英-德翻译任务进行模型预训练。encoder学习并优化英语单词的embedding,以便将其翻译成德语。一般而言,encoder应该在将单词转换成另一种语言之前捕获该语言相关的高级语义和句法含义,encoder输出用于为各种下游语言任务提供基于上下文化的word embedding。
CoVe的局限性是显而易见的:
随后,ELMO通过无监督的预训练方式克服了问题(1),OpenAI GPT和BERT通过无监督的预训练+task-specific的有监督的fine-tuning进一步克服了这两个问题。
Deep contextualized word representations (Peters, et al, 2018)
ELMO,是Embedding from Language Model的缩写,通过无监督预训练多层双向LSTM模型来学习带上下文信息的(Contextualized)单词表示。
双向语言模型( bi-LM )是ELMO的基础。模型的输入是由n个token构成的序列,( x1,…,xn),语言模型根据历史的序列预测(x1…xi-1)下一个token xi的概率。
两个方向上的预测过程都是由多层LSTMs建模的,给定输入词条 xi得到隐状态为h→i,ℓ和h←i,ℓ。最后一层的输出的隐状态为hi,L=[h→i,L;h←i,L]作为输出层的输入,用于得到最终的输出yi。模型共享embedding层和softmax层,分别由θe和θs参数化表示。
在L层biLM之上,ELMO通过学习task-specific线性组合,将所有隐状态堆在一起。词条xi的隐状态表示包含2L+1向量:
Ri={hi,ℓ∣ℓ=0,…,l},其中,h0,ℓ代表embedding层的输出,且hi,ℓ=[h→i,ℓ;h←i,ℓ]。S(task)表示加权求和中每个任务的权重(通过softmax进行归一化)。缩放因子γ(task)用于校正biLM隐状态分布和task-specific表示分布之间的不一致性。
为了评估不同层的隐状态具体捕获了什么样的信息,ELMO分别被应用于语义密集型(semantic-intensive)和语法密集型(syntax-intensive)任务,使用biLM的不同层中的表示(Representation)处理:
对比研究表明,ELMO底层表示学习到了很多句法特征,而在高层表示学习到更多语义特征。因为不同的层倾向于学习不同类型的信息,所以将它们堆叠在一起会更有帮助。
类似于CoVe可以帮助不同类型的下游任务,ELMO embedding也可以嵌入到下游不同类型任务的模型中。此外,对于某些任务(如SNLI和SQuAD,但不是SRL),把ELMO embedding加入到输出层也有帮助。
ELMO提出的改进对于具有少量监督训练数据集的任务来说是非常有帮助的。有了ELMO,也可以用更少的标记数据来获得更好的性能。
语言模型的预训练是无监督的,理论上,由于无标签的文本语料库非常丰富,预训练可以尽可能地扩大规模。然而,它仍然依赖于task-specific的模型,因此这种改进只是渐进的,而为每个任务寻找一个好的模型架构仍然不是一件容易的事情。
Semi-Supervised Sequence Modeling with Cross-View Training(Clark等人,2018)
在ELMO中,两个独立的模型在两个不同的训练阶段进行无监督的预训练和task-specific的有监督地学习。Cross-View训练(Cross-View Training,CVT)将两个训练阶段组合成一个统一的半监督学习过程,其中bi-LSTM编码器输出的表示(representation)通过带标签数据上的监督学习和辅助任务(auxiliary tasks)上无标签数据的无监督学习来改进。
该模型由两层双向LSTM编码器和初级预测模块(Primary Prediction Module)组成。在训练过程中,交替给模型输入带标签和不带标签的数据batch。
使用带标签的训练样本训练模型时,所有的模型参数都通过标准的监督学习来更新。loss是标准的交叉熵(standard cross entropy)。无监督训练时,初级预测模块仍然可以产生一个“soft”目标,尽管我们不知道它们的精确程度。在几个辅助任务中,预测器只看到和处理与输入相关的信息,例如只在一个方向上使用编码器隐状态表示。期望辅助任务输出与主要预测目标匹配以获得完整的输入视图。
这样,编码器被迫将整个上下文的知识提取为部分表示(partial representation)。在这个阶段,biLSTM编码器被反向传播,但是主要预测模块是固定的。loss是最小化辅助预测和主要预测之间的差异(distance)。
当同时训练多个任务时,CVT为额外的任务增加了几个预测模型。它们都共享同一个句子表示编码器。在有监督训练期间,一旦随机选择了一项任务,相应预测器和表示编码器(representation encoder)中的参数就会更新。对于无标签的训练样本,通过最小化每个任务的辅助输出和主要预测目标之间的差异这种联合学习的方式来优化编码器。
多任务学习鼓励模型学习更具通用性的词表示(representation),同时产生了一个不错的副产品:来自无标签数据的all-tasks-labeled 样本。考虑到跨任务标签是有用的,但是相当罕见,它们是宝贵的数据标签。
理论上,主要的预测模块(primary prediction module)可以采用任何形式,通用或特定于某个任务的设计。CVT论文中的例子包括这两种情况。
在像NER或POS类似的序列标注任务构成的联合学习任务中,预测器模块的输出端通常包含由两个全连接层和一个softmax层构成的概率预测器,预测label概率分布。对于每个词条xi,我们采用对应任务输出的隐状态,h1(i)和h2(i)作为softmax层的输入:
前向或后向LSTM状态仅仅作为辅助任务第一层的输入。因为他们只保持局部的文本信息,无论是在左边还是右边,他们都必须像语言模型一样学习,试图根据上下文预测下一个标签。fwd和bwd辅助任务只朝着一个方向。未来和过去的任务分别在向前和向后的方向上向前迈进了一步。
上图序列标注任务依赖于四个辅助预测模型,它们的输入只涉及一个方向的隐状态:向前、向后、未来和过去。
请注意,如果主预测模块采用了dropout,则dropout层在使用有标签数据进行训练时照常工作,但在使用无标签数据进行训练期间为辅助任务生成“soft”目标时不适用。
在机器翻译任务中,主要预测模块被一个标准的单向LSTM decoder所取代,这是值得注意的。有两个辅助任务:
Universal Language Model Fine-tuning for Text Classification(Howard & Ruder,2018年)
ULMFiT首次尝试了Generative Pretrained LM +Task-Specific微调的想法,其收到的启发来自ImageNet预训练用于计算机视觉任务取得了巨大成功。基本模型是AWD-LSTM。
ULMFiT遵循三个步骤,并在下游语言分类任务种获得了良好的迁移学习效果:
1)一般LM预训练:基于维基百科文本数据。
2)标任务LM微调:ULMFiT提出了两种用于稳定微调的训练技术。
3 )目标任务分类器微调:预处理LM后面增加了两个FFN(feed-forward layers)层,并增加了一个softmax层获得目标输出概率分布。
串联池化(Concat pooling)通过mean-pooling和max-pooling从历史隐状态种抽取特征,拼接起来以得到最终的隐状态。
逐步解冻(Gradual unfreezing)有助于避免灾难性遗忘问题(Catastrophic Forgetting),方法是从最后一层开始逐渐unfreezing模型的层。首先,最后一层解冻并微调一个epoch。然后解冻下一层。重复这个过程,直到所有层的参数都被调整。
Improving Language Understanding by Generative Pre-Training (Radford等人,2018年)
与ELMO的想法类似,OpenAI GPT,Generative Pre-training Transformer的缩写,通过在大量免费文本语料库上进行训练,将无监督语言模型扩展到更大的规模。
GPT与ELMO有两个主要区别:
与传统的Transformer架构相比,Transformer解码器模型丢弃了encoder部分,因此模型只有一个输入。输入句子embedding经过多层Transfomer处理。每一层都由一个multi-head self-attention层和一个pointwise feed-forward层构成。最终经过softmax层输出在目标词条上的概率分布。
Loss是负对数似然度(negative log-likelihood),与ELMO相同,但没有反向计算(序列从后往前的计算)。比方说,k大小的上下文窗口位于目标单词之前,损失如下:
字节对编码(BPE)用于编码输入序列。 BPE最初在20世纪90年代被提出作为数据压缩算法,然后被用来解决机器翻译中的开放词汇问题,因为在翻译成新语言时很容易遇到罕见和未知的单词。受到由于稀有和未知单词通常可以分解为多个子词的情况所启发,BPE通过迭代和贪婪地合并频繁的字符对来找到最佳的单词分词。
OpenAI GPT提出的最实质性的升级是摆脱task-specific模型,直接使用预先训练的语言模型!
以分类为例。比方说,在带标签的数据集中,每个输入都有n个标签,x=(x1,…,xn),还有一个标签y。GPT首先通过预先训练的Transformer解码器处理输入序列x,最后一个tokenxn的最后一层输出是hL(n)。然后,只有一个新的可训练权重矩阵Wy,它可以预测类别标签上的分布。
Loss是最小化真实标签的负对数似然度。此外,添加LMloss作为辅助loss被认为是有益的,因为:
基于类似的设计,对于其他任何下游任务不需要更改网络结构。如果任务输入包含多个句子,则在每对句子之间添加一个特殊的分隔符( $ )。这个定界符标签的embedding是一个我们需要学习的新参数,但是它应该非常小。
对于句子相似性任务,因为排序无关紧要,所以两个排序都包括在内。对于多项选择任务,上下文与每个答案候选项配对。
OpenAI GPT在第一阶段,语言模型的生成性预训练可以吸收尽可能多的自由文本(free text)。然后在第二个阶段,利用小的带标注数据集和一组最小的新参数对模型进行微调,以适应特定的任务。
GPT的一个局限性是它的单向特性—该模型只被训练来预测未来left-to-right context,这限制了GPT的学习能力
BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (Devlin等人,2019年)
BERT,是Bidirectional Encoder Representations from Transformer的缩写是GPT的直系后代:在自由文本上训练一个大型语言模型,然后在没有定制网络架构的情况下微调特定任务。
与GPT相比,BERT主要有3点不同:
BERT的模型架构是一个多层双向Transformer编码器。
为了鼓励双向预测和句子级理解,BERT的训练被分成两个辅助任务,而不是基本的语言任务(也就是说,在给定的上下文中预测下一个标签)。
毫无疑问的是,基于一个word双向上下文学习得到的representation,无论是句法上还是语义上,都比仅依赖上文学习到的representation要好。BERT通过对“掩码语言模型”任务的训练来鼓励模型实现这一目标:
随机屏蔽每个序列中15 %的token。因为如果我们只用一个特殊的占位符[MASK]替换屏蔽的token,那么在微调期间将永远不会遇到这个特殊的token。因此,BERT采用了几种启发式技巧
(a)以80 %的概率,用[MASK]替换所选单词;
(b)以10 %的概率,替换为一个随机的单词;
(c)以10 %的概率,保持不变。
该模型只预测缺失的单词,但是它没有关于哪些单词已经被替换或者哪些单词应该被预测的信息。输出大小仅为输入大小的15%。
这一思想其实和传统的Skip-Gram模型中的Negative Sampling的思想其实很类似。
上述两项辅助任务的训练数据可以从任何单语语料库中轻松生成。因此,训练的语料规模是无限的。训练的loss是平均屏蔽LM似然和平均下一句预测似然之和。
输入embedding是三个部分的总和:
请注意,第一个标签都是[ CLS ]—一个占位符,稍后将用于下游任务的预测。
BERT微调只需要添加几个新参数,就像OpenAI GPT一样。
对于分类任务,我们通过获取特殊的第一token[CLS]、hL~[ CLS ]的最终隐状态,并将其乘以一个小权重矩阵,softmax(hL~[ CLS ], Wcls),得到其预测输出。
对于像SQuAD这样的QA任务,我们需要预测给定问题在给定段落中的text span。BERT预测每个标签的两个概率分布,即text span的开始和结束。只有两个新的小矩阵,Ws和We,是在微调过程中新学到的,softmax( h(i)LWs )和oftmax(hL(i)We )定义了两个概率分布。
总的来说,用于下游任务微调的附加部分非常少—一两个权重矩阵将Transformer的隐状态转换成可解释的格式。
汇总表比较了OpenAI GPT和BERTfine-tuning之间的差异。
Language Models are Unsupervised Multitask Learners
OpenAI GPT-2语言模型是GPT的直接继承者。与GPT-2与GPT-1相比,模型结构基本一致,任然采用多层单向Transformer模型,主要是在训练数据方面有很大不同:
GPT-2的预训练任务仅仅包含第一步预训练语言模型。所有下游语言任务都被构建为预测条件概率,没有任务特定的微调。
LM模型非常适合处理文本生成任务(Text Generation)。
机器翻译任务,比如,从英语到汉语,被构造出如下的条件LM:“英语句子=汉语句子”和“目标英语句子=”。
例如,条件概率的预测看起来像: P (?|I like green apples. =我喜欢绿苹果。A cat meows at him. =一只猫对他喵。It is raining cats and dogs. = " )
QA任务的格式与机器翻译类似,把问题和答案放在一起构成Context。
摘要抽取任务是在抽取完文章的上下文信息之后,通过添加 TL:DR: 来触发的。
与最初的GPT相同,GPT-2输入采用BPE处理,使用UTF-8字节序列。每个字节可以在8bits中表示256个不同的值,而UTF-8中一个字符最多可以使用4个字节,总共支持最多2的31次方个字符。因此,对于字节序列表示,只需要大小为256的词汇表,不需要担心预处理、分词等。尽管有这些好处,当前字节级(byte-level)的LMs与SOTA词级别(word-level)的LMs的性能差距仍然不可忽略。
BPE通过贪心的方式合并频繁共现的字节对。以防止它生成多个版本的常用词(比如对于dog,生成dog. dog! dog?),GPT-2防止BPE跨类别合并字符(因此dog不会与标点符号合并,如。,!还有?)。这些技巧有助于提高最终字节分段的质量。
使用字节序列表示,GPT-2能够为任何Unicode字符串分配概率,而不需要任何预处理步骤。
与GPT相比,GPT-2除了具有更多的Transformer层和参数之外,只包含了很少的架构修改: