作者:哈工大SCIR 徐啸
来源:Transfer Learning in Natural Language Processing Tutorial (NAACL 2019)
作者:Sebastian Ruder, Matthew Peters, Swabha Swayamdipta, Thomas Wolf
相关资源:
Slides: tiny.cc/NAACLTransfer
Colab: tiny.cc/NAACLTransferCo
Code: github.com/huggingface/
Ruder 对教程进行了一定扩展的博文 The State of Transfer Learning in NLP
AI科技评论 已对此文进行了翻译
Sebastian Ruder: Transfer Learning in Open-Source Natural Language Processing (spaCy IRL 2019)
本文小结:本文为教程的篇,包含教程的 0-2 部分。主要是对迁移学习的介绍以及预训练方面的经典方法。
提纲
介绍:本节将介绍本教程的主题:迁移学习当前在自然语言处理中的应用。在不同的迁移学习领域中,我们主要定位于顺序迁移学习 sequential transfer learning 。
预训练:我们将讨论无监督、监督和远程监督的预训练方法。
表示捕获了什么:在讨论如何在下游任务中使用预训练的表示之前,我们将讨论分析表示的方法,以及观察到它们捕获了哪些内容。
调整:在这个部分,我们将介绍几种调整这些表示的方法,包括特征提取和微调。我们将讨论诸如学习率安排、架构修改等的实际考虑。
下游应用程序:本节,我们将重点介绍预训练的表示是如何被用在不同的下游任务中的,例如文本分类、自然语言生成、结构化预测等等。
开放问题和方向:在后一节中,我们将提出对未来的展望。我们将突出待解决的问题以及未来的研究方向。
0. 前言
A Survey on Transfer Learning, Pan and Yang (2010) 摘要:在许多机器学习和数据挖掘算法中,一个主要的假设是训练和未来的数据必须在相同的特征空间中,并且具有相同的分布。然而,在许多实际应用程序中,这种假设可能不成立。例如,我们有时在一个感兴趣的领域中有一个分类任务,但是我们只在另一个感兴趣的领域中有足够的训练数据,并且后者可能位于不同的特征空间或遵循不同的数据分布。在这种情况下,如果成功地进行知识迁移,就可以避免昂贵的数据标记工作,从而大大提高学习性能。近年来,迁移学习作为一种新的学习框架应运而生。本研究的重点是分类和回顾目前迁移学习在分类、回归和聚类问题上的进展。在本研究中,我们讨论了迁移学习与其他相关机器学习技术的关系,如领域适应、多任务学习、样本选择偏差以及协变量偏移。同时,我们也探讨了迁移学习研究中一些潜在的未来问题。
为什么要在自然语言处理任务中使用迁移学习 ?
许多 NLP 任务共享关于语言的常识 (例如语言表示、结构相似性)
跨任务共享的、不同层次的,含义和结构的表示
任务之间可以互通有无——例如语法和语义
带注释的数据很少,应当尽可能多地利用其进行监督学习
经验上看,迁移学习促成了许多有监督的 NLP 任务的 SOTA (如分类、信息提取、问答等)。
为什么要在自然语言处理任务中使用迁移学习 ?(经验之谈)
自然语言处理任务中的迁移学习种类
Ruder (2019)
迁移学习包括 Transductive 与 Inductive 两种:
Transductive:相同的任务;但只有原领域的标注数据
不同的领域:领域适应
不同的语言:跨语种学习
Inductive:不同的任务;只有目标领域的标注数据
同时学习任务:多任务学习
顺序学习任务:顺序迁移学习(教程重点)
这篇tutorial与什么有关?
目标:提供NLP中迁移方法的广泛概述,重点介绍截至目前(2019年年中)成功的经验方法。
提供实用的动手建议→在教程结束时,每个人都有能力将新的进展应用到文本分类任务
这不是:全面的(不可能在一个教程中涵盖所有相关的论文!)
(Bender Rule:本教程主要针对用英语完成的工作,对其他语言的可扩展性取决于数据和资源的可用性。)
1. 介绍
Sequential transfer learning 指的是在一个任务/数据集上学习后迁移到其他任务/数据集上。
预训练的任务和数据集
Unlabeled data and self-supervision
很容易收集非常大的语料库:维基百科,新闻,网页抓取,社交媒体等。
利用分布假设进行训练:“You shall know a word by the company it keeps”(Firth, 1957),通常形式化为训练某种语言模型的变体
关注使用有效的算法以利用丰富的数据
Supervised pretraining
在视觉领域很常见,但由于缺乏大型监督数据集,在NLP中较少
机器翻译
NLI 用于学习句子表示
任务特定——从一个问答数据集迁移到另一个
目标任务和数据集
目标任务通常是监督的,并跨越一系列常见的NLP任务:
句子或文档分类(例如情感分类)
句子对分类(如NLI, paraphrase)
单词级别(如序列标注、抽取问答)
结构化预测(例如解析)
生成(例如对话、总结)
从单词到文本中的单词
语言模型预训练
许多成功的预训练方法都是基于语言模型的
非正式地,语言模型学习
不需要人工注释
许多语言都有足够的文本来学习高容量模型
语言模型是“多才多艺”的——可以学习句子和单词的表示,具有多种目标函数
由浅到深
Bengio et al 2003: A Neural Probabilistic Language Model Devlin et al 2019: BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding
预训练任务 vs 目标任务
预训练任务的选择和目标任务是耦合的
句子/文档表示对单词级别的预测没有帮助
词向量可以跨上下文进行池化,但通常会被其他方法超越 (Attention)
在语境词向量中,双向语境非常重要
通常:相似的预训练和目标任务 → 好结果
2. 预训练
语言模型预训练
词向量
为什么要词嵌入?
词嵌入是可以学习的参数
在不同任务中,共享表示
低维空间更好计算——难以处理稀疏向量
无监督预训练 : 神经网络之前
词向量预训练
word2vec
以 CBOW 为例,输入层将目标词语境 c 中的每一个词向量简单求和(也可求平均)后得到语境向量,然后直接与目标词的输出向量求点积,目标函数也就是要让这个与目标词向量的点积取得大值,对应的与非目标词的点积尽量取得小值。
word2vec 的出现,极大促进了 NLP 的发展,尤其是促进了深度学习在 NLP 中的应用(不过word2vec 算法本身其实并不是一个深度模型,它只有两层全连接),利用预训练好的词向量来初始化网络结构的层几乎已经成了标配,尤其是在只有少量监督数据的情况下,如果不拿预训练的 embedding 初始化层,几乎可以被认为是在蛮干。
Word2vec 与 NNLM 都是语言模型,但不同的是 word2vec 的重点是通过训练语言模型从而得到词向量,因此以词向量为重点对 NNLM 进行了改进优化,并且使用 CBOW 和 Skip-gram 两种方式学习词向量,GloVe 则通过构建共现矩阵,不通过传统的 SVD 进行计算复杂度较高的矩阵分解,而是使用平方误差促使点积尽可能得接近共现概率的对数,因为如果使向量点积等于共现概率的对数,向量差异就会成为共现概率的比率即单词 j 出现在单词 i 的上下文中的概率,这一比值蕴含了语义信息。
相比word2vec,GloVe却更加充分的利用了词的共现信息,word2vec中则是直接粗暴的让两个向量的点乘相比其他词的点乘大,至少在表面上看来似乎是没有用到词的共现信息,不像GloVe这里明确的就是拟合词对的共现频率。
fastText 则是利用带有监督标记的文本分类数据完成训练,框架和 CBOW 一致,不过输入数据不再是 bag-of-words 的信息,还加上了 ngram 信息,这就加入了语序信息,而且输出的是当前输入文本的类别。此外还引入 subword 来处理长词,处理 OOV 问题。
句子和文档向量
无监督篇章嵌入 (Le & Mikolov, 2014)
PV-DM的全称是 Distributed Memory Model of Paragraph Vectors,和CBOW类似,也是通过上下文预测下一个词,不过在输入层的时候,同时也维护了一个文档ID映射到一个向量的look-up table,模型的目的便是将当前文档的向量以及上下文向量联合输入模型,并让模型预测下一个词,训练结束后,对于现有的文档,便可以直接通过查表的方式快速得到该文档的向量,而对于新的一篇文档,那么则需要将已有的look-up table添加相应的列,然后重新走一遍训练流程,只不过此时固定好其他的参数,只调整look-up table,收敛后便可以得到新文档对应的向量了。PV-DBOW的全称则是Distributed Bag of Words version of Paragraph Vector,和Skip-gram类似,通过文档来预测文档内的词,训练的时候,随机采样一些文本片段,然后再从这个片段中采样一个词,让PV-DBOW模型来预测这个词,以此分类任务作为训练方法,说白了,本质上和Skip-gram是一样的。这个方法有个致命的弱点,就是为了获取新文档的向量,还得继续走一遍训练流程,并且由于模型主要是针对文档向量预测词向量的过程进行建模,其实很难去表征词语之间的更丰富的语义结构,所以这两种获取文档向量的方法都未能大规模应用开来。
Skip-Thought
借鉴 Skip-gram 的思想,Skip-thoughts 直接在句子间进行预测,也就是将 Skip-gram 中以词为基本单位,替换成了以句子为基本单位,具体做法就是选定一个窗口,遍历其中的句子,然后分别利用当前句子去预测和输出它的上一句和下一句。
不过和普通框架不一样的是,Skip-thoughts有两个Decoder。在今天看来,这个框架还有很多不完善或者可以改进的地方(作者也在论文中分别提到了这些future works),比如输入的Encoder可以引入attention机制,从而让Decoder的输入不再只是依赖Encoder后一个时刻的输出;Encoder和Decoder可以利用更深层的结构;Decoder也可以继续扩大,可以预测上下文中更多的句子;RNN也不是的选择,诸如CNN以及2017年谷歌提出的Transformer的结构也可以利用进来,后来果不其然,谷歌的BERT便借鉴了这一思路。
-
Quick-thoughts 在此基础上进一步改进,将生成任务改为分类任务。具体说来就是把同一个上下文窗口中的句子对标记为正例,把不是出现在同一个上下文窗口中的句子对标记为负例,并将这些句子对输入模型,让模型判断这些句子对是否是同一个上下文窗口中,很明显,这是一个分类任务。可以说,仅仅几个月之后的BERT正是利用的这种思路。而这些方法都和Skip-thoughts一脉相承。
自编码器预训练
半监督序列学习
论文提出了两个方法,用无标签数据进行无监督训练的参数来初始化有监督学习的模型:一种是用基础的语言模型,另一种是用seq2seq自编码模型(sequence autoencoder, SA-LSTM),encoder 输入为WXYZ,decoder输出为依然为WXYZ。和普通的seq2seq模型相比不同的是,这里的encoder和decoder隐层是共享的。有种提前让循环神经网络学会句子的表达,再之后根据标签去学习分类的能力的思想。
有监督的句子嵌入
Paragram-phrase: uses paraphrase database for supervision, best for paraphrase and semantic similarity (Wieting et al.2016)
InferSent: bi-LSTM trained on SNLI + MNLI (Conneau et al.2017)
GenSen: multitask training(skip-thought, machine translation, NLI, parsing) (Subramanian et al. 2018)
InferSent 是在斯坦福的SNLI(Stanford Natural Language Inference)数据集上训练的模型,而后将训练好的模型当做特征提取器,以此来获得一个句子的向量表示,再将这个句子的表示应用在新的分类任务上,来评估句子向量的优劣。框架结构如下图所示
这个框架底层是一个 Encoder,也就是终要获取的句子向量提取器,然后将得到的句子向量通过一些向量操作后得到句子对的混合语义特征,后接上全连接层并做 SNLI 上的三分类任务。
上下文相关词向量
动机:词向量将所有的上下文都压缩到一个单一向量中
关键想法:不是每个单词学习一个向量,而是学习依赖于上下文的向量。
context2vec
基于 CBOW 框架,为了捕捉句子语境的本质,使用双向 LSTM 提取特征。
TagLM
TagLM workflow
与上文无关的单词嵌入 + RNN model 得到的 hidden states 作为特征输入
Char CNN / RNN + Token Embedding 作为 bi-LSTM 的输入
得到的 hidden states 与 Pre-trained bi-LM(冻结的) 的 hidden states 连接起来输入到第二层的 bi-LSTM 中
Seq2Seq的无监督预训练
提出一种通用的提高seq2seq模型的无监督训练方法。seq2seq模型的encoder和decoder的权重用两个预训练语言模型初始化然后微调。
seq2seq模型的缺点:监督学习的语料有限,容易过拟合。本文提出了改善seq2seq效果的无监督训练方法。在微调阶段,训练任务为语言模型任务和seq2seq的联合任务。(开始fune-tuning可能导致灾难性的遗忘:模型在语言模型上的性能急剧下降,可能损害模型的泛化能力。为保证模型不在有监督语料上过拟合,在fine-tuning阶段继续单语言语言模型任务,seq2seq和语言模型任务的损失相加作为终损失)
此外还用了残差连接,Encoder 和 Decoder 之间也用了 Attention。
CoVe
CoVe更侧重于如何将现有数据上预训练得到的表征迁移到新任务场景中,而之前的句子级任务中大多数都只把迁移过程当做一个评估他们表征效果的手段,因此观念上有所不同
也有使用训练好的序列模型为其他NLP模型提供上下文的想法
想法:机器翻译是为了保存意思,所以这也许是个好目标?
使用seq2seq + attention NMT system中的Encoder,即 2层 bi-LSTM ,作为上下文提供者
所得到的 CoVe 向量在各种任务上都优于 GloVe 向量
但是,结果并不像其他更简单的NLM培训那么好,所以似乎被放弃了
也许NMT只是比语言建模更难?
或许有一天这个想法会回来?
ELMo
使用长上下文而不是上下文窗口学习 word token 向量(这里,整个句子可能更长)
学习深度Bi-NLM,并在预测中使用它的所有层
训练一个双向LM
目标是 performant 但LM不要太大
使用2个biLSTM层
这两个biLSTM NLM层有不同的用途/含义
低层更适合低级语法,例如
词性标注(part-of-speech tagging)、句法依赖(syntactic dependency)、NER
高层更适合更别的语义
情绪、Semantic role labeling 语义角色标记 、question answering、SNLI
目标函数为
(仅)使用字符CNN构建初始单词表示
如下图所示,在输入层和输出层均使用了如下CNN结构,减少了参数规模,解决了 OOV 问题,并且每一个词向量的计算可以预先做好,更能够减轻inference阶段的计算压力
2048 个 char n-gram filters 和 2 个 highway layers,512 维的 projection
4096 dim hidden/cell LSTM状态,使用 512 dim的对下一个输入的投影
使用残差连接
绑定 token 的输入和输出的参数(softmax),并将这些参数绑定到正向和反向LMs之间
ELMo学习biLM表示的特定任务组合
这是一个创新,TagLM 中仅仅使用堆叠LSTM的顶层,ELMo 认为BiLSTM所有层都是有用的
衡量ELMo对任务的总体有用性,是为特定任务学习的全局比例因子
是 softmax 归一化的混合模型权重,是 BiLSTM 的加权平均值的权重,对不同的任务是不同的
对于每一个词,可以根据下面的式子得到它的向量,其中 γ 是一个scale因子,加入这个因子主要是想要将ELMo的向量与具体任务的向量分布拉平到同一个分布水平,这个时候便需要这么一个缩放因子了。另外, 便是针对每一层的输出向量,利用一个softmax的参数来学习不同层的权值参数,因为不同的任务需要的词语意义的粒度也不一致,一般认为浅层的表征比较倾向于句法,而高层输出的向量比较倾向于语义信息,因此通过一个softmax的结构让任务自动去学习各层之间的权重,自然也是比较合理的做法。
此外,ELMo 还使用了 Exploring the Limits of Language Modeling 中提出的 char-based CNN 结构,应用到输入层和输出层上,减少了参数规模,并解决了令人头痛的 OOV 问题。
ELMo 使用 LSTM 而不是 Transformer 作为特征抽取器,而很多研究已经证明了Transformer提取特征的能力是要远强于LSTM的;另外,ELMO 采取双向拼接这种融合特征的能力可能比 Bert 一体化的融合特征方式弱,但是,这只是一种从道理推断产生的怀疑,目前并没有具体实验说明这一点。
ELMo 代表着基于特征融合的预训练方法,而 GPT 则是基于Fine-tuning的模式的开创者。
ULMFit
在大型通用领域的无监督语料库上使用 biLM 训练
在目标任务数据上调整 LM
对特定任务将分类器进行微调
使用合理大小的“1 GPU”语言模型,并不是真的很大
在LM调优中要注意很多
ULMFit的预训练和finetune过程主要可以分为三个阶段,分别是在大规模语料集上(比如Wikitext 103,有103million个词)先预训练,然后再将预训练好的模型在具体任务的数据上重新利用语言模型来finetune一下(这是次finetune,叫做LM finetune),尔后再根据具体任务设计的一个模型上,将预训练好的模型当做这个任务模型的多层,再一次finetune(这是第二次finetune,如果是分类问题的话可以叫做Classifier finetune)
其中 T 是一个阈值,而 K 则是总共的迭代次数,这个式子的意思就是把迭代到第T次之后,对该参数在其后的第 T 轮到后一轮之间的所有值求平均,从而得到后模型的该参数值,而相应的,普通的SGD则是直接取作为后模型的参数值。
并且在每个时间步之间都是用一个全连接层,并且使用DropConnect的方法随机drop掉一些连接减少一些过拟合的风险
微调技巧
有区分的微调
针对不同的层在训练更新参数的时候,赋予不同的学习率。这里的出发点是,一般来说,对于NLP的深度学习模型来说,不同层的表征有不同的物理含义,比如浅层偏句法信息,高层偏语义信息,因此对于不同层的学习率不同,自然就是比较合理的了。原文也给出了具体的选择:先指定后一层的学习率,然后根据下式得到前面层的学习率,基本思想是让浅层的学习率要更小一些。
斜三角学习率
在finetune的阶段,希望能够先稳定住原来已经在大规模语料集上已经预训练好的参数,所以选择一个比较小的finetune学习率;尔后希望能够逐步加大学习率,使得学习过程能够尽量快速;后,当训练接近尾声时,逐步减小学习率,这样让模型逐渐平稳收敛(这个思想大概借鉴了2017年谷歌提出Transformer时用到的warm up的学习率调节方法,这个方法也是在训练的时候先将学习率逐步增大,尔后再逐步减小)。因此,这样一个三段论式的学习过程,用图表示如下:
逐渐解冻
主要思想是把预训练的模型在新任务上finetune时,逐层解冻模型,也就是先finetune后一层,然后再解冻倒数第二层,把倒数第二层和后一层一起finetune,然后再解冻第三层,以此类推,逐层往浅层推进,终finetune整个模型或者终止到某个中间层。这样做的目的也是为了finetune的过程能够更平稳。
因为ULMFiT中包含了两次finetune,即在新任务上用语言模型finetune和在新任务上finetune训练一个终的task-specifi-model(比如分类器),而论文中主要把discriminative fine-tuning, slanted triangular learning rates这两个技巧用在了语言模型的finetune阶段,把后一个gradual unfreezing的技巧应用在终task-specifi-model的finetune阶段。
使用大型的预训练语言模型是一种提高性能的非常有效的方法
GPT
GPT也采用两阶段过程,个阶段是利用语言模型进行预训练,第二阶段通过Fine-tuning的模式解决下游任务。下图展示了GPT的预训练过程(按照论文中的说法,GPT中使用的Transformer是只用了Decoder),其实和ELMO是类似的,主要不同在于两点:首先,特征抽取器不是用的RNN,而是用的Transformer,上面提到过它的特征抽取能力要强于RNN,这个选择很明显是很明智的;其次,GPT的预训练虽然仍然是以语言模型作为目标任务,但是采用的是单向的语言模型,所谓“单向”的含义是指:语言模型训练的任务目标是根据单词的上下文去正确预测单词 ,GPT则只采用这个单词的上文来进行预测,而抛开了下文。
下游任务怎么使用 GPT 呢?首先,对于不同的下游任务来说,本来你可以任意设计自己的网络结构,现在不行了,你要向GPT的网络结构看齐,把任务的网络结构改造成和GPT的网络结构是一样的。然后,在做下游任务的时候,利用步预训练好的参数初始化GPT的网络结构,这样通过预训练学到的语言学知识就被引入到你手头的任务里来了,这是个非常好的事情。再次,你可以用手头的任务去训练这个网络,对网络参数进行Fine-tuning,使得这个网络更适合解决手头的问题。
对于NLP各种花样的不同任务,怎么改造才能靠近GPT的网络结构呢?
GPT论文给了一个改造施工图如上,其实也很简单:对于分类问题,不用怎么动,加上一个起始和终结符号即可;对于句子关系判断问题,比如Entailment,两个句子中间再加个分隔符即可;对文本相似性判断问题,把两个句子顺序颠倒下做出两个输入即可,这是为了告诉模型句子顺序不重要;对于多项选择问题,则多路输入,每一路把文章和答案选项拼接作为输入即可。从上图可看出,这种改造还是很方便的,不同任务只需要在输入部分施工即可。
BERT
Bert 采用和GPT完全相同的两阶段模型,首先是语言模型预训练;其次是使用Fine-Tuning模式解决下游任务。和GPT的主要不同在于在预训练阶段采用了类似ELMO的双向语言模型,当然另外一点是语言模型的数据规模要比GPT大。
BERT主要的几个特征分别是
利用了真双向的Transformer
为了利用双向信息,改进了普通语言模型成为完形填空式的Mask-LM(Mask-Language Model)
利用Next Sentence Prediction任务学习句子级别信息
进一步完善和扩展了GPT中设计的通用任务框架,使得BERT能够支持包括:句子对分类任务、单句子分类任务、阅读理解任务和序列标注任务
预训练阶段
因为Encoder中用了Self-attention机制,而这个机制会将每一个词在整个输入序列中进行加权求和得到新的表征,更通俗的说法是每一个词在经过Self-attention之后,其新的表征将会是整个输入序列中所有词(当然也包括它本身)的加权求和。在ELMo与GPT中,它们并没有用上这种交融模式,也就是它们本质上还是一个单向的模型,ELMo稍微好一点,将两个单向模型的信息concat起来,GPT则只用了单向模型,这是因为它没有用上Transformer Encoder,只用了Decdoer的天生基因决定的,其实,很多人就把这种left-to-right的Transformer框架叫做Decoder,因为事实上Decoder就是如此(具体做的时候需要提前把未来待生成的词做好mask,细节上通过上三角矩阵来实现),这也是OpenAI把他们的模型叫做"Generative"的原因所在。
“GPT则只用了单向模型,这是因为它没有用上Transformer Encoder,只用了Decdoer的天生基因决定的” ,个人认为主要想表述的是 GPT 使用 Transformer 架构时,受限于传统的语言模型,产生的假双向的问题,简单来说就是GPT并没有像 Transformer 中的 encoder 一样对整句话进行 self-attention ,而是像 Decoder 一样,预测每个单词时只有其上文进行了 self-attention
Masked-LM 双向Transformer下的语言模型
然而在语言模型中,我们通过某个词的上下文语境预测当前词的概率,如果直接把这个套用到Transformer的Encoder中,会发现待预测的输出和序列输入已经糅合在一块了。那么,如何解决Self-attention中带来了表征性能卓越的双向机制,却又同时带来了信息泄露的这一问题?Bert 受到完形填空任务的启发:输入序列依然和普通Transformer保持一致,只不过把挖掉的一个词用"[MASK]"替换 ,Transformer的Encoder部分按正常进行,输出层在被挖掉的词位置,接一个分类层做词典大小上的分类问题,得到被mask掉的词概率大小。
直接把普通语言模型中的生成问题(正如GPT中把它当做一个生成问题一样,虽然其本质上也是一个序列生成问题),变为一个简单的分类问题,并且也直接解决了Encoder中多层Self-attention的双向机制带来的泄密问题(单层Self-attention是真双向,但不会带来泄密问题,只有多层累加的Self-attention才会带来泄密问题),使得语言模型中的真双向机制变为现实。
不过,BERT针对如何做“[MASK]”,做了一些更深入的研究,它做了如下处理
选取语料中所有词的15%进行随机mask
选中的词在80%的概率下被真实mask
选中的词在10%的概率下不做mask,而被随机替换成其他一个词
选中的词在10%的概率下不做mask,仍然保留原来真实的词
这使得Transformer编码器不知道它将被要求预测哪些单词或哪些单词已被随机单词替换,因此它被迫保持每个输入标记的分布式上下文表示。
预测下一句
利用和借鉴了Skip-thoughts方法中的句子预测问题,来学习句子级别的语义关系,具体做法则是将两个句子组合成一个序列,当然组合方式会按照下面将要介绍的方式,然后让模型预测这两个句子是否是先后近邻的两个句子,也就是会把"Next Sentence Prediction"问题建模成为一个二分类问题。训练的时候,数据中有50%的情况这两个句子是先后关系,而另外50%的情况下,这两个句子是随机从语料中凑到一起的,也就是不具备先后关系,以此来构造训练数据。句子级别的预测思路和之前介绍的Skip-thoughts基本一致,当然更本质的思想来源还是来自于word2vec中的skip-gram模型。
要求模型除了做上述的Masked语言模型任务外,附带再做个句子关系预测,判断第二个句子是不是真的是个句子的后续句子。之所以这么做,是考虑到很多NLP任务是句子关系判断任务,单词预测粒度的训练到不了句子关系这个层级,增加这个任务有助于下游句子关系判断任务。所以可以看到,它的预训练是个多任务过程。这也是Bert的一个创新。
spanBERT 与 RoBERTa 两篇文章对此提出了质疑,感兴趣的读者可以自行阅读~
在预训练阶段,因为有两个任务需要训练:Mask-LM和Next Sentence Prediction,因此BERT的预训练过程实质上是一个Multi-task Learning,具体说来,BERT的损失函数由两部分组成,部分是来自于Mask-LM的单词级别的分类任务,另一部分是句子级别的分类任务,通过这两个任务的联合学习,可以使得BERT学习到的表征既有token级别的信息,同时也包含了句子级别的语义信息。具体的损失函数如下
Fine-Tuning 阶段
输入层:如果输入只有一个句子的话,则直接在句子的前后添加句子的起始标记位和句子的结束符号,在BERT中,起始标记都用“[CLS]”来表示,结束标记符用"[SEP]"表示,对于两个句子的输入情况,除了起始标记和结束标记之外,两个句子间通过"[SEP]"来进行区分。除了这些之外,BERT还用了两个表示当前是句子A还是句子B的向量来进行表示,对于句子A来说,每一词都会添加一个同样的表示当前句子为句子A的向量,相应的,如果有句子B的话,句子B中的每一个词也都会添加一个表示当前句子为句子B的向量。
NLP 的四大任务:
序列标注,这是典型的NLP任务,比如中文分词,词性标注,命名实体识别,语义角色标注等都可以归入这一类问题,它的特点是句子中每个单词要求模型根据上下文都要给出一个分类类别。
分类任务,比如我们常见的文本分类,情感计算等都可以归入这一类。它的特点是不管文章有多长,总体给出一个分类类别即可。
句子关系判断,比如Entailment,QA,语义改写,自然语言推理等任务都是这个模式,它的特点是给定两个句子,模型判断出两个句子是否具备某种语义关系。
生成式任务,比如机器翻译,文本摘要,写诗造句,看图说话等都属于这一类。它的特点是输入文本内容后,需要自主生成另外一段文字。
对于种类如此繁多而且各具特点的下游NLP任务,Bert如何改造输入输出部分使得大部分NLP任务都可以使用Bert预训练好的模型参数呢?上图给出示例,对于句子关系类任务,很简单,和GPT类似,加上一个起始和终结符号,句子之间加个分隔符即可。对于输出来说,把个起始符号对应的Transformer后一层位置上面串接一个softmax分类层即可。对于分类问题,与GPT一样,只需要增加起始和终结符号,输出部分和句子关系判断任务类似改造;对于序列标注问题,输入部分和单句分类是一样的,只需要输出部分Transformer后一层每个单词对应位置都进行分类即可。从这里可以看出,上面列出的NLP四大任务里面,除了生成类任务外,Bert其它都覆盖到了,而且改造起来很简单直观。尽管Bert论文没有提,但是稍微动动脑子就可以想到,其实对于机器翻译或者文本摘要,聊天机器人这种生成式任务,同样可以稍作改造即可引入Bert的预训练成果。只需要附着在S2S结构上,encoder部分是个深度Transformer结构,decoder部分也是个深度Transformer结构。根据任务选择不同的预训练数据初始化encoder和decoder即可。这是相当直观的一种改造方法。当然,也可以更简单一点,比如直接在单个Transformer结构上加装隐层产生输出也是可以的。不论如何,从这里可以看出,NLP四大类任务都可以比较方便地改造成Bert能够接受的方式。这其实是Bert的非常大的优点,这意味着它几乎可以做任何NLP的下游任务,具备普适性,这是很强的。
后,我们再次总结下BERT的几个主要特点:
Transformer Encoder因为有Self-attention机制,因此BERT自带双向功能
因为双向功能以及多层Self-attention机制的影响,使得BERT必须使用Cloze版的语言模型Masked-LM来完成token级别的预训练
为了获取比词更别的句子级别的语义表征,BERT加入了Next Sentence Prediction来和Masked-LM一起做联合训练
为了适配多任务下的迁移学习,BERT设计了更通用的输入层和输出层 然后,我们再来看看BERT的工作都站在了哪些“巨人肩膀”上:
针对点,双向功能是Transformer Encoder自带的,因此这个“巨人肩膀”是Transformer
第二点中Masked-LM的巨人肩膀是语言模型,CBOW以及Cloze问题
第三点中Next Sentence Prediction的“巨人肩膀”是Skip-gram,Skip-thoughts和Quick-thoughts等工作
第四点中,对输入层和输出层的改造,借鉴了T-DMCA以及GPT的做法
为什么语言模型效果好?
语言建模是一项非常困难的任务,即使对人类来说也是如此。
预期语言模型将任何可能的上下文压缩到一个向量中,该向量概括了可能的完成后的句子。
“They walked down the street to ???”
为了有机会解决这个任务,模型必须学习语法、语义、对世界事实编码等等。
给定足够的数据、一个巨大的模型和足够的计算,就可以完成一项合理的工作!
从经验上看,语言模型比翻译,自编码更有效:“Language Modeling Teaches You More Syntax than Translation Does” (Zhang et al. 2018)
预训练的有趣属性
1. 样本高效
ELMo 中的实验对比
预训练的一个主要好处就是它减少了对有标注数据的需求。在实际使用中,与非预训练模型相比,迁移学习模型通常只需要十分之一甚至更少的样本数量就达到类似的表现,如下图(ULMFIT Howard and Ruder, 2018)所示。
ULMFit中的实验对比
2. 扩大预训练规模
上图为 GloVe 中增加语料库规模对模型准确度的影响。
数据集越大越好,并且维基百科数据集比新闻文本数据集要好
因为维基百科就是在解释概念以及他们之间的相互关联,更多的说明性文本显示了事物之间的所有联系
而新闻并不去解释,而只是去阐述一些事件
不同数据量的 Crawl 数据作为预训练的平均 GLUE 效果
通常,我们可以通过同时增加模型参数和预训练数据量的方式来改善预训练表征。但随着预训练数据量的增长,回报率开始下降。但如上图所示的当前的性能曲线,并不表示我们已达到了稳定状态。因此,我们期待可以在更多数据基础上训练出更大的模型。
近的这种趋势的例子是ERNIE 2.0,XLNet,GPT-2 8B, 和 RoBERTa。特别是后者发现,简单地对 BERT 进行更长时间和更多数据的训练就可以得到更好的结果,而对 GPT-2 8B 进行更长时间和更多数据的训练则可以减少语言建模数据集上的困惑度(尽管只是相对较小的因素)
跨语言预训练
在训练跨语言词嵌入方面做了大量工作(Overview: Ruder et al. (2017))
想法:分别训练每种语言,然后对齐
Recent work aligning ELMo: Schuster et al., (NAACL 2019)
ACL 2019 Tutorial on Unsupervised Cross-lingual Representation Learning
关键思想:通过在多种语言上训练一个模型,实现跨语言的词汇表和表示。
优点:易于实现,可单独进行跨语言预培训
缺点:低资源语言导致其表示学习的不够好
LASER: Use parallel data for sentence representations(Artetxe & Schwenk, 2018)
Multilingual BERT: BERT trained jointly on 100 languages
Rosita:Polyglot contextual representations(Mulcaire et al., NAACL 2019)
XLM: Cross lingual LM (Lample & Conneau, 2019)
本期责任编辑:崔一鸣
本期编辑:顾宇轩