论文:
https://s3-us-west-2.amazonaws.com/openai-assets/research-covers/language-unsupervised/language_understanding_paper.pdf
文章目录
- 提高语言理解的生成预训练方法
- 摘要
- 引言
- 相关工作
- 自然语言处理的半监督学习
- 无监督预训练
- 辅助训练目标
- 框架
- 无监督预训练
- 有监督微调
- 任务特定的输入转换
- 文本蕴涵
- 相似性
- 问答和常识推理
- 4 实验
- 4.1 设置
- 4.2 有监督微调
- 5 分析
- 6 结论
- 举个例子
- 预训练阶段
- 微调阶段
- 预测阶段
提高语言理解的生成预训练方法
摘要
自然语言理解包含了一系列多样的任务,例如文本蕴涵、问答、语义相似度评估和文档分类。尽管有大量未标记的文本语料库,但用于学习这些特定任务的标记数据稀缺,使得仅靠判别训练模型难以表现出色。我们展示了通过在多样的未标记文本语料上进行生成预训练,然后在每个特定任务上进行判别微调,可以在这些任务上实现显著的提升。与以往的方法相比,我们在微调过程中使用任务感知的输入转换,既能实现有效的迁移,又只需对模型架构做最小的改动。我们在广泛的自然语言理解基准测试中证明了我们方法的有效性。我们的通用任务无关模型在12个任务中有9个显著优于专为每个任务设计的判别训练模型。例如,我们在常识推理(Stories Cloze Test)上取得了8.9%的绝对提升,在问答(RACE)上取得了5.7%的提升,在文本蕴涵(MultiNLI)上取得了1.5%的提升。
引言
从原始文本中有效学习的能力对于缓解自然语言处理(NLP)中的监督学习依赖至关重要。大多数深度学习方法需要大量手动标记的数据,这限制了它们在许多缺乏标注资源的领域中的应用【61】。在这些情况下,可以利用未标记数据中的语言信息的模型,提供了一个有价值的替代方案,而不需要花费大量时间和成本来获取更多的标注数据。此外,即使在有大量监督数据的情况下,以无监督方式学习好的表示也能显著提高性能。迄今为止,最有力的证据是预训练的词嵌入【10, 39, 42】在提高各种NLP任务性能中的广泛使用【8, 11, 26, 45】。然而,从未标记文本中获取超过词级信息具有挑战性,主要有两个原因。首先,不清楚哪种优化目标最有效地学习对迁移有用的文本表示。最近的研究考察了各种目标,例如语言建模【44】、机器翻译【38】和话语连贯性【22】,每种方法在不同任务上都有优于其他方法的表现。其次,没有一致意见认为最有效的方法是将这些学到的表示迁移到目标任务。现有技术包括对模型架构进行特定任务的改动【43, 44】、使用复杂的学习方案【21】和添加辅助学习目标【50】。这些不确定性使得开发有效的语言处理半监督学习方法变得困难。
在本文中,我们探讨了一种使用无监督预训练和有监督微调结合的语言理解任务的半监督方法。我们的目标是学习一种通用表示,能够以最小的适应迁移到各种任务中。我们假设可以访问一个大型的未标记文本语料库和几个带有手动标注训练实例的数据集(目标任务)。我们的设置不要求这些目标任务与未标记语料在同一领域。我们采用两阶段训练过程。首先,我们在未标记数据上使用语言建模目标来学习神经网络模型的初始参数。随后,我们使用相应的监督目标将这些参数调整到目标任务。
对于我们的模型架构,我们使用Transformer【62】,它在机器翻译【62】、文档生成【34】和句法解析【29】等任务中表现出色。与循环网络等替代方法相比,这种模型选择为处理文本中的长期依赖提供了更结构化的记忆,从而在各种任务中实现了稳健的迁移性能。在迁移过程中,我们利用从遍历风格方法【52】中派生的任务特定输入调整,将结构化文本输入处理为一个连续的令牌序列。正如我们在实验中所展示的,这些调整使我们能够以最小的架构改动有效地进行微调。
我们在四类语言理解任务——自然语言推理、问答、语义相似性和文本分类上评估了我们的方法。我们的通用任务无关模型显著优于为每个任务专门设计的判别训练模型,在12个任务中有9个任务上显著提高了现有技术水平。例如,我们在常识推理(Stories Cloze Test)【40】上取得了8.9%的绝对提升,在问答(RACE)【30】上取得了5.7%的提升,在文本蕴涵(MultiNLI)【66】上取得了1.5%的提升,并在最近引入的GLUE多任务基准【64】上取得了5.5%的提升。我们还分析了预训练模型在四种不同设置下的零样本行为,证明它为下游任务获取了有用的语言知识。
相关工作
自然语言处理的半监督学习
我们的工作广泛地属于自然语言的半监督学习范畴。该范式吸引了大量关注,应用于序列标注【24, 33, 57】或文本分类【41, 70】等任务。最早的方法使用未标记数据计算词级或短语级统计量,然后将其用作监督模型的特征【33】。在过去几年中,研究人员证明了使用在未标记语料上训练的词嵌入【11, 39, 42】在提高各种任务性能中的好处【8, 11, 26, 45】。然而,这些方法主要转移词级信息,而我们旨在捕获更高级的语义。
无监督预训练
无监督预训练是半监督学习的一个特例,目标是找到一个好的初始化点,而不是修改监督学习目标。早期的工作探索了在图像分类【20, 49, 63】和回归任务【3】中使用这种技术。后续研究【15】表明,预训练作为一种正则化方案,可以提高深度神经网络的泛化能力。在最近的工作中,该方法已用于帮助训练各种任务的深度神经网络,如图像分类【69】、语音识别【68】、实体消歧【17】和机器翻译【48】。
与我们的工作最接近的研究涉及使用语言建模目标对神经网络进行预训练,然后在有监督的目标任务上进行微调。Dai等【13】和Howard和Ruder【21】遵循这种方法来改进文本分类。然而,尽管预训练阶段有助于捕获一些语言信息,但他们使用的LSTM模型将其预测能力限制在短范围内。相比之下,我们选择的Transformer网络允许我们捕获更长范围的语言结构,正如我们在实验中所展示的。此外,我们还展示了我们模型在包括自然语言推理、释义检测和故事完成等更广泛任务上的有效性。其他方法【43, 44, 38】在目标任务的监督模型训练中,将来自预训练语言或机器翻译模型的隐藏表示用作辅助特征。这需要为每个单独的目标任务引入大量新参数,而我们在迁移过程中对模型架构的改动最小。
辅助训练目标
添加辅助无监督训练目标是另一种半监督学习形式。Collobert和Weston【10】早期的工作使用了广泛的辅助NLP任务,如词性标注、分块、命名实体识别和语言建模,以提高语义角色标注的性能。最近,Rei【50】在他们的目标任务目标中添加了辅助语言建模目标,并在序列标注任务上展示了性能提升。我们的实验也使用了辅助目标,但正如我们所展示的,无监督预训练已经学习了许多与目标任务相关的语言方面。
框架
我们的训练过程分为两个阶段。第一阶段是在大规模文本语料库上学习高容量的语言模型。接着是微调阶段,我们使用标记数据将模型适应于判别任务。
无监督预训练
给定一个未标记的令牌语料库 U = { u 1 , … , u n } U = \{u_1, \ldots, u_n\} U={u1,…,un} ,我们使用标准的语言建模目标来最大化以下似然:
L 1 ( U ) = ∑ i log P ( u i ∣ u i − k , … , u i − 1 ; Θ ) L_1(U) = \sum_i \log P(u_i | u_{i-k}, \ldots, u_{i-1}; \Theta) L1(U)=i∑logP(ui∣ui−k,…,ui−1;Θ)
其中, k k k 是上下文窗口的大小,条件概率 P P P 由具有参数 Θ \Theta Θ 的神经网络建模。这些参数通过随机梯度下降【51】进行训练。在我们的实验中,我们使用多层Transformer解码器【34】作为语言模型
,它是transformer【62】的一个变体。该模型在输入上下文令牌上应用多头自注意操作,随后是逐位置前馈层,以生成目标令牌的输出分布:
h 0 = U W e + W p h l = t r a n s f o r m e r _ b l o c k ( h l − 1 ) ∀ i ∈ [ 1 , n ] P ( u ) = s o f t m a x ( h n W e T ) h_0 = U W_e + W_p \\ h_l = transformer\_block(h_{l-1}) \forall i \in [1,n] \\ P(u) = softmax(h_n W_e^T) h0=UWe+Wphl=transformer_block(hl−1)∀i∈[1,n]P(u)=softmax(hnWeT)
其中, U = ( u − k , … , u − 1 ) U = (u_{-k}, \ldots, u_{-1}) U=(u−k,…,u−1) 是上下文向量, n n n 是层数, W e W_e We 是令牌嵌入矩阵, W p W_p Wp 是位置嵌入矩阵。
有监督微调
在使用公式 (1) 中的目标训练模型后,我们将参数调整到有监督的目标任务。我们假设有一个标记数据集 C C C ,每个实例由一序列输入令牌 x 1 , … , x m x_1, \ldots, x_m x1,…,xm 和一个标签 y y y 组成。输入通过我们的预训练模型以获得最终transformer块的激活 h m l h_m^l hml ,然后将其输入到具有参数 W y W_y Wy 的线性输出层,以预测 y y y:
P ( y ∣ x 1 , … , x m ) = s o f t m a x ( h m l W y ) P(y | x_1, \ldots, x_m) = softmax(h_m^l W_y) P(y∣x1,…,xm)=softmax(hmlWy)
这给出了我们需要最大化的目标:
L 2 ( C ) = ∑ ( x , y ) log P ( y ∣ x 1 , … , x m ) L_2(C) = \sum_{(x, y)} \log P(y | x_1, \ldots, x_m) L2(C)=(x,y)∑logP(y∣x1,…,xm)
我们还发现,将语言建模作为辅助目标包含在微调中有助于学习:(a)改进监督模型的泛化能力,和(b)加速收敛。这与之前的工作【50, 43】一致,他们也观察到了使用这种辅助目标的性能提升。具体来说,我们优化以下目标(权重为 λ \lambda λ):
L 3 ( C ) = L 2 ( C ) + λ ⋅ L 1 ( C ) L_3(C) = L_2(C) + \lambda \cdot L_1(C) L3(C)=L2(C)+λ⋅L1(C)
总体来说,我们在微调期间所需的额外参数仅有 W y W_y Wy 和分隔符令牌的嵌入(在3.3节中描述)。
任务特定的输入转换
对于某些任务,如文本分类,我们可以直接按照上述描述微调我们的模型。某些其他任务,如问答或文本蕴涵,具有结构化输入,例如有序的句子对或文档、问题和答案的三元组。由于我们的预训练模型是在连续的文本序列上训练的,我们需要进行一些修改以应用于这些任务。以往的工作提出在转移表示之上学习特定任务的架构【44】。这种方法重新引入了大量的特定任务定制,并且不使用转移学习用于这些额外的架构组件。相反,我们使用遍历风格的方法【52】,将结构化输入转换为预训练模型可以处理的有序序列。这些输入转换使我们能够避免在跨任务的架构中进行广泛的更改。我们在下面简要描述这些输入转换,图1提供了视觉说明。所有转换都包括添加随机初始化的开始和结束令牌(,)。
文本蕴涵
对于蕴涵任务,我们将前提 p p p 和假设 h h h 的令牌序列连接起来,中间使用分隔符令牌($)。
相似性
对于相似性任务,两句被比较的句子没有固有顺序。为反映这一点,我们将输入序列修改为包含两种可能的句子顺序(中间有分隔符),并独立处理每个顺序以生成两个序列表示 h m l h_m^l hml ,然后将它们逐元素相加再输入线性输出层。
问答和常识推理
对于这些任务,我们给定一个上下文文档 z z z ,一个问题 q q q 和一组可能的答案 { a k } \{a_k\} {ak} 。我们将文档上下文和问题与每个可能的答案连接起来,中间添加一个分隔符令牌,得到 $[z; q; ; a k ] ; a_k] ;ak] 。每个序列都独立处理,随后通过softmax层归一化以生成对可能答案的输出分布。
4 实验
4.1 设置
无监督预训练 我们使用BooksCorpus数据集【71】进行语言模型训练。该数据集包含7000多本独特的未出版书籍,涵盖冒险、奇幻和浪漫等多种类型。重要的是,它包含长段的连续文本,使生成模型能够学习基于长程信息进行条件生成。另一种数据集1B Word Benchmark被类似的方法ELMo【44】使用,但它在句子级别被打乱,破坏了长程结构。我们的语言模型在这个语料库上达到了18.4的极低令牌级困惑度。
模型规范 我们的模型主要遵循原始Transformer工作【62】。我们训练了一个12层仅解码器的Transformer,带有掩码自注意头(768维状态和12个注意头)。对于逐位置前馈网络,我们使用了3072维的内部状态。我们使用Adam优化方案【27】,最大学习率为2.5e-4。学习率在前2000次更新中线性增加到最大值,然后使用余弦调度下降到0。我们在包含64个随机抽样的连续512个令牌的迷你批次上训练了100个周期。由于模型中广泛使用了层规范化【2】,简单的权重初始化N(0,0.02)已足够。我们使用了40,000次合并的字节对编码(BPE)词汇【53】以及0.1的残差、嵌入和注意力dropout率进行正则化。我们还采用了【37】提出的L2正则化的修改版本,在所有非偏置或增益权重上设定w=0.01。激活函数使用高斯误差线性单元(GELU)【18】。我们使用了学习的位置嵌入而不是原始工作中提出的正弦版本。我们使用ftfy库2清理BooksCorpus中的原始文本,标准化一些标点符号和空白,并使用spaCy分词器3。
微调细节 除非特别说明,我们重用无监督预训练的超参数设置。我们在分类器中添加了0.1的dropout率。对于大多数任务,我们使用6.25e-5的学习率和32的批量大小。我们的模型微调速度很快,大多数情况下3个周期的训练就足够了。我们使用线性学习率衰减调度,并在0.2%的训练中进行预热。 λ \lambda λ 设为0.5。
4.2 有监督微调
我们在多种有监督任务上进行实验,包括自然语言推理、问答、语义相似性和文本分类。这些任务的一部分是最近发布的GLUE多任务基准【64】的一部分,我们利用了这些任务。图1提供了所有任务和数据集的概述。
自然语言推理 自然语言推理(NLI)任务,也称为识别文本蕴涵,涉及阅读一对句子并判断它们之间的关系(蕴涵、矛盾或中立)。尽管最近对该任务有很多兴趣【58, 35, 44】,由于存在词汇蕴涵、共指和词汇及句法歧义等多种现象,该任务仍然具有挑战性。我们在五个具有不同来源的数据集上进行评估,包括图像字幕(SNLI)、转录语音、流行小说和政府报告(MNLI)、维基百科文章(QNLI)、科学考试(SciTail)或新闻文章(RTE)。
表2详细列出了我们的模型和先前最先进方法在不同NLI任务上的各种结果。我们的方法在五个数据集中的四个上显著优于基线,在MNLI上实现了最高1.5%的绝对提升,在SciTail上实现了5%的提升,在QNLI上实现了5.8%的提升,在SNLI上实现了0.6%的提升。这表明我们的模型在多个句子上推理和处理语言歧义方面的能力。在我们评估的较小数据集RTE(2490个示例)上,我们取得了56%的准确率,低于多任务biLSTM模型报告的61.7%。鉴于我们的方法在较大NLI数据集上的强劲表现,我们的模型可能也会从多任务训练中受益,但我们目前尚未探索这一点。
问答和常识推理 另一项需要单句和多句推理的任务是问答。我们使用最近发布的RACE数据集【30】,其中包括来自中学和高中的英语阅读文章和相关问题。与CNN【19】或SQuaD【47】等其他数据集相比,这个语料库被证明包含更多的推理类型问题,为我们训练处理长程上下文的模型提供了完美的评估。此外,我们还评估了故事完形测试【40】,它涉及从两个选项中选择正确的多句故事结尾。在这些任务上,我们的模型再次显著优于之前的最佳结果——在故事完形测试上提升了8.9%,在RACE上总体提升了5.7%。这表明我们的模型能够有效处理长程上下文。
语义相似性 语义相似性(或释义检测)任务涉及预测两句是否在语义上等价。挑战在于识别概念的重新措辞、理解否定和处理句法歧义。我们使用三个数据集进行此任务——Microsoft Paraphrase Corpus(MRPC)【14】(从新闻来源收集)、Quora Question Pairs(QQP)数据集【9】和Semantic Textual Similarity Benchmark(STS-B)【6】。在三个语义相似性任务中的两个上,我们取得了最先进的结果(表4),在STS-B上绝对提升1点。在QQP上的表现差距显著,较单任务BiLSTM + ELMo + Attn提高了4.2%的绝对值。
分类 最后,我们还在两个不同的文本分类任务上进行了评估。Linguistic Acceptability(CoLA)【65】包含专家对句子是否合乎语法的判断,测试了训练模型的内在语言偏见。而Stanford Sentiment Treebank(SST-2)【54】是一个标准的二元分类任务。我们的模型在CoLA上得到了45.4分,显著高于之前最佳结果35.0,展示了模型学习的内在语言偏见。模型还在SST-2上达到了91.3%的准确率,与最先进结果相当。我们还在GLUE基准上取得了72.8的总分,显著高于之前的最佳68.9分。
总的来说,我们的方法在我们评估的12个数据集中的9个数据集上取得了新的最先进结果,在许多情况下超过了集成方法。我们的结果还表明,我们的方法在不同规模的数据集上效果很好,从较小的数据集如STS-B(约5.7k训练示例)到最大的SNLI(约550k训练示例)。
5 分析
传递层数的影响 我们观察了从无监督预训练到有监督目标任务传递不同层数的影响。图2(左)展示了我们的方法在MultiNLI和RACE上的性能,作为传递层数的函数。我们观察到标准结果是传递嵌入提高了性能,并且每个Transformer层提供了额外的好处,在MultiNLI上全传递最多可提高9%。这表明预训练模型中的每一层都包含了对解决目标任务有用的功能。
零样本行为 我们希望更好地理解为什么transformer的语言模型预训练如此有效。一个假设是,为了提高其语言建模能力,基础生成模型学习了我们评估的许多任务,并且与LSTM相比,transformer的更结构化的记忆在迁移中起到了作用。我们设计了一系列启发式解决方案,使用基础生成模型在没有有监督微调的情况下执行任务。我们在图2(右)中可视化了这些启发式解决方案在生成预训练过程中的效果。我们观察到这些启发式方法的性能稳定并且随着训练逐渐提高,表明生成预训练支持了各种任务相关功能的学习。我们还观察到LSTM在零样本性能上表现出较高的方差,表明Transformer架构的归纳偏置在迁移中起到了作用。
对于CoLA(语言可接受性),示例的评分是生成模型分配的平均令牌对数概率,通过阈值来进行预测。对于SST-2(情感分析),我们在每个示例后添加了令牌“very”,并将语言模型的输出分布限制为“positive”和“negative”两个词,猜测它分配更高概率的词作为预测。对于RACE(问答),我们选择生成模型在文档和问题条件下分配最高平均令牌对数概率的答案。对于DPRD【46】(winograd schemas),我们用两个可能的指代替换定冠词,并预测生成模型在替换后的序列中分配更高平均令牌对数概率的解析。
消融研究 我们进行了三种不同的消融研究(表5)。首先,我们分析了在微调期间没有辅助LM目标的方法的性能。我们观察到辅助目标在NLI任务和QQP上有帮助。总体趋势表明,较大的数据集从辅助目标中受益,而较小的数据集则没有。其次,我们通过将我们的框架与单层2048单元LSTM进行比较,分析了Transformer的效果。我们观察到使用LSTM而不是Transformer时,平均分数下降了5.6。LSTM只在一个数据集上优于Transformer——MRPC。最后,我们还比较了直接在有监督目标任务上训练的Transformer架构,没有预训练。我们观察到缺乏预训练会在所有任务上降低性能,与我们的完整模型相比,性能下降了14.8%。
6 结论
我们引入了一个通过生成预训练和判别微调实现强大自然语言理解的框架。通过在包含长段连续文本的多样化语料库上进行预训练,我们的模型获取了大量的世界知识和处理长程依赖的能力,然后成功地迁移到解决问答、语义相似性评估、蕴涵判断和文本分类等判别任务上,在我们研究的12个数据集中的9个上提高了现有技术水平。使用无监督(预)训练来提升判别任务性能一直是机器学习研究的重要目标。我们的工作表明,实现显著的性能提升确实是可能的,并提供了关于哪些模型(Transformer)和数据集(具有长程依赖的文本)最适合这种方法的线索。我们希望这将有助于启发新的无监督学习研究,不仅在自然语言理解领域,还在其他领域,进一步提高我们对无监督学习何时以及如何起作用的理解。
举个例子
GPT-1方法是一个训练技巧,下面用例子展示如何迁移任务。
下面是一个基于GPT-1方法的代码示例,包括预训练和微调的步骤。这是一个简化的示例,使用了Hugging Face的Transformers库来演示如何进行生成预训练和判别微调。
预训练阶段
首先,我们需要准备一个大规模未标记文本数据集来进行预训练。为了简单起见,我们可以使用Hugging Face提供的文本数据集。
from transformers import GPT2Tokenizer, GPT2LMHeadModel, AdamW
from transformers import Trainer, TrainingArguments
import torch
from datasets import load_dataset# 加载数据集
dataset = load_dataset('wikitext', 'wikitext-2-raw-v1', split='train')# 加载GPT-2模型和分词器(GPT-1架构类似于GPT-2的架构)
tokenizer = GPT2Tokenizer.from_pretrained('gpt2')
model = GPT2LMHeadModel.from_pretrained('gpt2')# 预处理数据
def preprocess_function(examples):return tokenizer(examples['text'], truncation=True, padding='max_length', max_length=512)tokenized_dataset = dataset.map(preprocess_function, batched=True)# 设置训练参数
training_args = TrainingArguments(output_dir='./results',num_train_epochs=1,per_device_train_batch_size=8,save_steps=10_000,save_total_limit=2,
)# 使用Trainer进行训练
trainer = Trainer(model=model,args=training_args,train_dataset=tokenized_dataset,
)trainer.train()
微调阶段
在预训练完成后,我们可以将模型微调到具体任务上,例如情感分析(使用SST-2数据集)。
from transformers import GPT2ForSequenceClassification
from datasets import load_dataset
from transformers import Trainer, TrainingArguments# 加载SST-2数据集
dataset = load_dataset('glue', 'sst2')# 微调使用的模型
model = GPT2ForSequenceClassification.from_pretrained('gpt2', num_labels=2)# 预处理数据
def preprocess_function(examples):return tokenizer(examples['sentence'], truncation=True, padding='max_length', max_length=512)tokenized_dataset = dataset.map(preprocess_function, batched=True)# 设置训练参数
training_args = TrainingArguments(output_dir='./results',num_train_epochs=3,per_device_train_batch_size=8,evaluation_strategy="epoch",save_steps=10_000,save_total_limit=2,
)# 使用Trainer进行微调
trainer = Trainer(model=model,args=training_args,train_dataset=tokenized_dataset['train'],eval_dataset=tokenized_dataset['validation'],
)trainer.train()
预测阶段
微调完成后,我们可以使用模型进行预测。
# 加载测试数据
test_dataset = dataset['test'].map(preprocess_function, batched=True)# 使用微调后的模型进行预测
predictions = trainer.predict(test_dataset)
predicted_labels = predictions.predictions.argmax(-1)# 打印一些预测结果
for i in range(10):print(f"Text: {test_dataset[i]['sentence']}")print(f"Predicted label: {predicted_labels[i]}")print(f"True label: {test_dataset[i]['label']}")
这个代码示例展示了如何使用生成预训练和判别微调的方法训练一个语言模型,并将其应用于具体的自然语言处理任务。通过这种方法,可以显著提高模型在不同任务上的性能。