雷锋网AI科技评论编者按:本文拓展自NAACL 2019教程“NLP领域的迁移学习”,这个教程是由Matthew Peters、Swabha Swayamdipta、Thomas Wolf和我组织策划的。在这篇文章中,我强调了一些在这个领域中的见解和收获,并根据最近的工作进展更新了一部分资料。整篇文章的结构如下图。
图1
一、内容简介
我们在这篇文章中的对迁移学习的主要定义如图所示,迁移学习是一种从源设置中提取信息并将其应用于不同设定目标的方法。
图2:迁移学习过程的说明
在过去一年多的时间里,以预训练的语言模型形式进行的迁移学习已经在NLP领域中普及,为许多不同的任务带来了新的最好成绩。然而,迁移学习在自然语言处理中并不是最近才出现的。雷锋网举个简单的例子,命名实体识别(NER)任务的进展情况,如下所示。
图3:随时间推移在CoNLL-2003上的命名实体识别(NER)性能
纵观其历史, 在这项任务中大多数的进步已经是由不同形式的迁移学习推动的:从早期s带有辅助任务的自监督学习(Ando和Zhang,2005)和短语和单词集群(Lin和Wu,2009)语言模型嵌入(Peters等人, 2017)和预训练语言模型(Peters, Akbik, Baevski等人)。
在当前的自然语言处理领域中,普遍存在着不同类型的迁移学习。它们可以按照三个维度进行分类:1、源设定和目标设定是否处理相同的任务;2、源域和目标域的性质;3、学习任务的顺序。这样就可以把各种迁移学习分为图中的几类。
图4:NLP中迁移学习的分类(Ruder, 2019)
序列迁移学习是其中进步最大的那一类。通常的做法是,使用你选择的方法在一个大型文本语料库中的未标记数据上进行表征预训练,然后通过标注数据把学到的表征适配到一个有监督任务上。如下图。
图5: 序列迁移学习的一般过程
二、主要的研究课题
在应用这种范式的过程中,我们可以观察到以下几个主要的研究课题
1、单词表征(如今已经是带有语境的单词表征)
随着时间推移、技术发展,单词表征也更多地联系上下文的语义。像word2vec这样的早期方法 (Mikolov 等人, 2013)为每个单词学习了单独的表征,但与上下文没有联系。后来的方法就开始将这些表征的尺度拓展到了句子和文本级别(Le和Mikolov, 2014;Conneau等人,2017)。当前的方法能够基于单词的上下文不同而学到不同的表征(McCann等人,2017; Peters等人,2018)。
2、LM预训练
许多成功的预训练方法都是基于语言建模(LM)的变体。 LM的优点是它不需要任何人工注释,并且许多语言都有足够的文本资料学出一个不错的模型d。此外,LM是多用途的,可以通过各种目标函数,学习句子和单词的表征。
3、由浅入深
在过去的几年里,NLP领域中最先进的模型变得越来越深入。仅仅两年前,大多数任务上表现最佳的模型都还是2-3层的深度BiLSTM,只有机器翻译领域表现最好的模型是与众不同的16层(Wu 等人, 2016)。相比之下,目前的模型如BERT-Large和GPT-2由24个Transformer模块组成,而最新的模型甚至会更深。
4、预训练vs目标设定
预训练和目标任务的选择密切相关。例如,句子的表达对于单词级别的预测并没有用,而基于词组的预训练对于词组级的预测是重要的。总的来说,为了获得最佳的目标性能,而选择类似的预训练任务是有益的。
三、预训练
1. 为什么语言建模会如此有效?
预训练语言模型的取得了惊人的成功。语言建模成功的一个原因可能是,它是一项非常困难的工作,即使对于人类来说也不例外。为了有机会解决这个难题,模型需要学习语法,语义以及某些世界常识。给定足够的数据,大量参数和足够的计算能力,模型就可以有不错的学习成果。根据过往的实验来看,语言建模比翻译或自动编码等其它预训练工作更有效(Zhang ,Wang等人)。
最近对人类语言的预测率失真(PRD)的分析(Hahn and Futrell, 2019)研究表明,人类语言和语言建模都具有无穷高的统计复杂性,但语言建模可以在较低层次上模仿逼近人类语言。这一观察结果有两个启示:1)我们可以用相对较小的模型以获得较为精准的结果;2) 我们的模型有很大的拓展潜力。对于这两种启示,我们都有充足证据,我们可以在下一节中看到。
2. 样本效率
预训练的一个主要好处就是它减少了对有标注数据的需求。 在实际使用中,与非预训练模型相比,迁移学习模型通常只需要十分之一甚至更少的样本数量就达到类似的表现,如下图所示(Howard 和Ruder, 2018)。
图6:从零开始训练的模型(蓝色)与分别对标记目标数据(橙色)和未标记目标数据(绿色)进行微调的两个预训练模型(红色)的性能(Howard和Ruder, 2018)。
3、增大预训练规模
通常可以通过同时增加模型参数和预训练数据量的方式来改善预训练表征。但随着预训练数据量的增长,回报率开始下降。然而,如下图所示的当前的性能曲线并不表示我们已达到了稳定状态。因此,我们期待可以在更多数据基础上训练出更大的模型。
图7:平均GLUE数据与预训练的爬行数据量对比(Baevski等,2019)。
最近的例子是ERNIE 2.0,XLNet,GPT-2 8B和RoBERTa。 尤其是后者发现,简单地对BERT进行更长时间和更多数据的训练就可以得到更好的结果,而对GPT-2 8B进行更长时间和更多数据的训练则可以减少语言建模数据集上的困惑度(尽管幅度很小)。
4、跨语言预训练
预训练的一个主要作用是它可以帮助我们跨越数字语言间鸿沟,使我们能够为全世界超过6000种语言都学习到NLP模型。(其中大多数语言是缺乏资料的,这既是为每种语言都学习语言模型的难点,也是跨语言预训练有用的地方)跨语言学习的工作大多集中在训练不同语言中的单词嵌入,并学习如何使它们之间匹配度更高(Ruder 等人, 2019);同样地,我们也可以对上下文表征做同样的事情(Schuster 等人,2019)。另一种常见方法是共享子单词词汇表并在多种语言上训练一个模型(Devlin,Artetxe, Schwenk, Mulcaire, Lample和Conneau等人,2019)。
虽然这很容易实现,并且是一个很强大的跨语言基线,但它导致资源配置较低的语言代表性不足(Heinzerling和Strube,2019)。特别是多语言BERT已成为备受关注的话题(Pires ,Wu和Dredze等人,2019),虽然它有很好的零样本学习表现,但专门的单语模型仍然是具有极大竞争力的,同时也更有效率(Eisenschlos 等人, 2019).
5、实际权衡
预训练很费钱。我们在教程中使用的Transformer-XL样式模型的预训练在8个V100 gpu上花费了5-20小时(如果是1个V100那么就要花费几天的时间)才能达到一个好的效果。因此,共享预训练的模型非常重要。除了需要为transformer的学习速率预热外,预训练对超参数的选择并不怎么挑剔。一般来说,如果数据集足够大,模型就不应该有足够的容量来进行过度拟合。掩蔽语言建模(如BERT中所述)的训练速度通常比标准LM慢2-4倍,因为掩蔽一小部分单词对应着只有一小部分的训练指导信号。
四、表征中都有什么
我们已经证明,表征可以用来预测某些语言现象,如翻译或句法层次的匹配。使用语法进行预训练,能够取得较好的效果;即使没有明显地对语法进行编码,表征仍然可以学习到一些语法概念(Williams等人,2018)。
最近的工作进一步表明,当前最先进的模型可以有效地蒸馏出语法知识(Kuncoro等人., 2019)。网络架构通常决定了表征的内容。例如,已经观察到了BERT能够捕捉语法(Tenney等人)。对于捕捉到的信息,不同的模型架构会表现出不同的层间变化趋势。
图8:探究工作一般用于设置研究语境词表示中的语言知识(Liu 等人, 2019)
模型捕获的信息还取决于你如何看待它:可视化激活或是注意力权重能提供模型知识的总体情况,但只能针对几个样本进行分析;如果在学习到的表征基础上训练一个分类器作为探针,用它来预测某些属性,这种方法可以发现语料库级别的一些具体特点,但也可能引入探针本身带来的偏倚;最后,网络对照试验对于改进模型非常有用,但得到的结论可能会仅限于当前的任务。
五、适配
为了使预训练模型适应目标任务,我们可以做出若干不同方向上的决策:架构修改,优化方案以及是否要获得更多的学习信号。
1、架构修改
对于架构修改,我们有两个选项:
a)保持预训练的模型内部不变
简单的做法可以是在预训练的模型之上添加一个或多个线性层,通常是在Bert基础上增加。或者我们也可以使用模型输出作为另一个模型的输入。当目标任务需要预训练的嵌入有一些交互作用但目前的预训练模型执行不了时,这通常是有帮助的,例如以BERT为预训练模型但需要词汇表征或建立跨句子关系模型。
b)修改预先训练的模型内部架构
我们希望这样做的原因之一可能是为了适应结构不同的设定目标,例如一个具有多个输入序列的任务。在这种情况下,我们可以使用预训练的模型尽可能初始化结构不同的设定模型。我们还可以应用于特定项目的修改,例如添加、跳过或残余连接或警示。最后,修改目标任务的参数可以通过在预训练的模型层之间添加瓶颈模块(“适配器”)来减少需要精细调整的参数数量(Houlsby,Stickland和Murray等人,2019)。
图9:变压器(左)中使用的适配器层(右)(Houlsby等人,2019年)
六、优化方案
在优化模型方面,我们需要选择要更新哪些权重,以及何时、如何更新它们
1、要更新哪些权重
对于权重更新,我们可以选择微调或者不微调(预训练权重)
a)不要改变预训练的权重(特征提取)
在实际应用中,很多人会在预训练表征的基础上训练一个线性分类器。如果想要获得最好的性能,通常就不仅使用顶层的表征,而要学习层表征的线性组合 (Peters等人, 2018, Ruder 等人, 2019)。另一个做法是,预训练的表征可以作为下游模型中的特性。当添加适配器时,只训练适配器层。
图10:在单独的下游模型中使用预:训练的模型作为特征
b)改变预训练过程中的权重(微调)
采用预训练的权值作为下游模型参数的初始化值。然后,在适应阶段对整个预训练架构进行训练。
2、如何以及何时更新权重
选择顺序和如何更新权重的主要目的是要避免覆盖有用的预训练的信息并最大化正迁移。与此相关的是灾难性遗忘的概念(McCloskey&Cohen,1989;French,1999),是指一个模型忘记了它最初训练的任务。在大多数设置中,我们只关心目标任务的性能,但这可能因应用场合的不同而有所不同。
更新我们模型的参数的一个指导原则是,在时间上、强度上或与预训练的模型相比,自上而下地逐步更新:
a)时间上的逐步更新(冻结法)
对不同分布和不同任务的数据同时进行所有层的训练可能会导致性能不稳定,产生的解决方案较差。相反,我们单独训练网络中不同的层,让它们有时间适应新的任务和数据。这可以追溯到早期深层神经网络的分层训练(Hinton等人,2006;Bengio等人,2007)。最近的方法(Felbo等人,2017;Howard和Ruder,2018年;Chronopoulou等,2019年) 的变化主要在于共同训练的层的选择不同。 尚未对transformer模型的解冻进行详细的研究。
b)强度上的逐步更新(降低的学习率)
我们希望通过降低学习率,以避免覆盖有用的信息。较低的学习率在较低层次(因为它们会捕捉到很多的普遍信息)、训练早期(因为模型仍然需要适应目标分布)和训练后期(当模型接近结尾时)尤为重要。为此,我们可以使用判别性微调(Howard和Ruder,2018),它降低了每一层的学习速度,如下所示。为了在早期的训练中保持较低的学习率,可以使用三角学习速率计划,也就是transformer的学习率预热。(Liu等人,2019)最近指出,在训练的早期阶段,预热可以减少差异
图11:歧视性微调(Howard和Ruder,2018年)
c)逐步更新vs预训练模型(正则化)
最大限度地减少灾难性遗忘的一种方法是鼓励目标模型参数使用正则化项,减小与预训练模型的参数的差异性(Wiese等人,CoNLL 2017,Kirkpatrick等人,PNAS 2017)。
七、权衡与实际考虑
一般来说,需要从头开始训练的参数越多训练速度就越慢。特征提取需要添加比微调更多的参数(peters等人,2019),因此训练速度通常较慢。然而,当一个模型需要适应很多的任务时,特征提取更节省空间,因为它只需要在内存中存储一个预先训练过的模型的副本。适配器通过为每个任务添加少量的附加参数来达到平衡。
就性能而言,没有一种适配器方法能在所有设置中都带来带来最好的表现。如果源和目标任务不一致,特征提取似乎更可取(Peters等人,2019)。否则,特征提取和微调通常执行类似的操作,这取决于用于超参数调整的预算(微调通常需要对超参数进行更广泛的搜索和尝试)。据说,transformer比lstms更容易微调(对超参数不那么敏感),并且可以通过微调实现更好的性能。
然而,大型的预训练模型(如Bert-Large)在对小训练集的任务进行精细调整时,往往会导致性能退化。通常显示为“ON-off”:如下图所示,模型要么运行良好,要么根本不起作用。想要了解这种行为的条件和原因,目前来说还是一个等待解决的研究问题。
图12:BERT(红色)和BERT的20个随机重启的任务分数分布,在MNLI(绿色)上进行微调,每次任务的微调不超过5k(Phang等,2018)。
八、获得更多的学习信号
目标任务通常都缺少资源.我们通常可以通过组合多种不同的学习信号来提高迁移学习的性能
1、提高样本效率
如果存在相关的任务,我们可以先在相关任务上使用更多数据对模型进行微调,然后再对目标任务进行微调。这尤其有助于数据有限的情况和执行类似任务 (Phunet 等人,2018),并提高了目标任务的样本效率(Yogatama等人,2019)。
2、多任务微调
或者,我们也可以根据相关任务和目标任务的要求对模型进行共同微调。这个相关的任务也可以是一个无监督的辅助任务。语言建模是一个很好的选择,并且已经证明即使没有预训练也能起到帮助(Rei等人,2017年)。任务比率可以进行选择,逐渐减小辅助任务的比例,在训练结束时辅助任务的比例可以减小到0(Chronopoulou等人,NAACL,2019年)。语言模型微调也已经作为一个单独步骤使用在了ULMFiT中 (Howard和Ruder,2018)。最近,即便有很多个目标任务,多任务微调也可以带来收益 (Liu等人,2019;Wang等人,2019)。
3、数据集分割
我们可以使用只在数据的某个子集上训练的辅助任务,而不对辅助任务微调。为此,我们首先要分析模型的误差,采用启发式方法自动识别训练数据中的突出子集,然后与目标任务联合训练辅助任务。
4、半监督学习
我们还可以使用半监督学习方法,通过扰乱未标记的数据来使我们的模型预测更加准确。 干扰方式可以是噪声,掩蔽(Clark等人,2018)也可以是数据增强,(Xie 等人,2019)。
5、集成模型
为了提高性能,可以把不同超参数训练的模型、不同预训练模型精细调节得到的模型、乃至不同任务,不同数据集的子集上训练的模型集成起来
6、蒸馏
最后,大型模型或模型组合可能被提炼成小型单一模型。该模型也可以更加简单化 (Tang等人,2019年),也可以产生不同的归纳偏差(Kuncoro等人,2019年)。多任务微调也可以与提炼相结合(Clark等人,2019)。
九、下游应用
预训练大型模型在计算和环境影响方面的成本很高(Strubell等人,2019年)。只要有可能,最好使用开源模型。如果您需要训练自己的模型,请与社区分享您的预训练模型。
1、框架和函数库
为了共享和使用经过训练的模型,可以有不同的选择:
2、Hubs
Hubs是中央存储库,并能提供访问预训练模型的通用API 。最常见的两个Hub是TensorFlow Hub和PyTorch Hub。Hub通常使用起来很简单;但是,由于模型的源代码难以访问,所以它们更像一个黑匣子。此外,修改预训练模型架构的内部结构可能会很困难。
3、研究者发布了检查点模型
检查点文件通常包含了预训练模型的所有权重。与Hub相比,仍然需要创建模型图,需要单独加载模型权重。因此,检查点文件比Hub模块更难使用,但它可以让你完全控制模型内部。
4、第三方函数库
像是 AllenNLP, fast.ai和 pytorch-transformers这类的第三方函数库,可以轻松访问预训练模型。 此类库通常可实现快速实验,并涵盖了许多经典的示例以进行迁移学习。
十、有待解决的问题及未来发展方向
1、预训练语言模型的缺陷
预训练的语言模型仍然不擅长细粒度的语言任务(Liu等人,2019)、层次句法推理(Kuncoro等人,2019)和常识(Zellers等人,2019)。在自然语言生成方面仍然有所欠缺,特别是在长期的维系、关系和连贯性方面。微调的时候它们更倾向于过于过度拟合表面形式信息,目前仍然被视为是“效率极高的表面学习者”。
正如我们前面所指出的,特别是对少量数据进行微调的大型模型很难进行优化,而且存在高度的差异性。目前经过预训练的语言模型非常庞大。蒸馏和剪枝是处理这一问题的两种方法。
2、预训练任务
虽然语言建模目标经过试验正名是有效的,但它也有缺陷。最近,我们看到双向语境和词序列的建模尤为重要。也许最重要的是,语言建模鼓励人们关注语法和词的共现,并且只提供了用于理解语义和维系上下文弱信号。我们可以从其他形式的自我监督中汲取灵感。此外,我们还可以设计专门的预训练任务,学习某些关系(Joshi等人,2019年;Sun等人,2019年)。
雷锋网(公众号:雷锋网)小结,很难能从原始文本中学习某种类型的信息。最新的方法就是将结构化知识(Zhang等人,2019;Logan IV等人,2019年)或多模态(Sun等人,2019;Lu等人,2019)引入,作为缓解这一问题的两种潜在方式。
原文链接:http://ruder.io/state-of-transfer-learning-in-nlp/
。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/137177.html