【AICon】探索RAG 技术在实际应用中遇到的挑战及应对策略!AICon精华内容已上线73%>>> 了解详情
写点什么

一文看懂自然语言处理中迁移学习的现状

  • 2019-08-28
  • 本文字数:8984 字

    阅读完需:约 29 分钟

一文看懂自然语言处理中迁移学习的现状

本文对北美计算语言学联合会 2019 年出版的《自然语言处理中迁移学习教程》NAACL 2019 tutorial on Transfer Learning in NLP)进行了拓展。

本文 The State of Transfer Learning in NLP最初发布于Sebastian Ruder 个人博客,经原作者 Sebastian Ruder 授权,由 InfoQ 中文站翻译并分享。


该教程由 Matthew Peters、Swabha Swayamdipta、Thomas Wolf 和我共同撰写。在本文中,我将重点介绍一些重要的见解和要点,并根据最近的研究工作提供了更新。下图展示了本文的结构:



本教程的幻灯片Colaboratory notebook代码都可以在网上获得。


译注: Colaboratory 是一个 Google 研究项目,旨在帮助传播机器学习培训和研究成果。它是一个 Jupyter 笔记本环境,不需要进行任何设置就可以使用,并且完全在云端运行。Colaboratory 笔记本存储在 Google 云端硬盘中,并且可以共享,就如同你使用 Google 文档或表格一样。Colaboratory 可免费使用。

引言

要了解什么是迁移学习,请阅读这篇博客文章《迁移学习:机器学习的下一个前沿》(Transfer Learning - Machine Learning’s Next Frontier)。我们在本文中的定义如下所示:


迁移学习是一种从源设置中提取知识并将其应用于不同目标设置的方法。


上图是迁移学习过程的一个实例。


上图是迁移学习过程的一个实例。


在短短一年多的时间里,以预训练语言模型形式的迁移学习,在自然语言处理中已经变得无处不在,并为各种任务的最新进展做出了贡献。然而,迁移学习在自然语言处理中并非新近才出现的新事物。一个例证是命名实体识别(Named Entity Recognition,NER)任务的进展情况,如下图所示。


上图展示了随着时间的推移,CoNLL-2003(English)上的命名实体识别的性能变化。


上图展示了随着时间的推移,CoNLL-2003(English)上的命名实体识别的性能变化。


纵观其历史,这项任务的大多主要改进都是由不同形式的迁移学习推动的。从早期具有辅助任务的自我监督学习(


Ando、Zhang,2005 年


)和短语与词簇(


Lin、Wu,2009 年


),再到语言模型嵌入(


Peters 等人,2017 年


)和预训练语言模型(


Peters 等人,2018 年



Akbik 等人,2018 年



Baevski 等人,2019 年


)。


在当前的自然语言处理中,常见的迁移学习类型有很多种。这些可以大致按照三个维度进行分类,基于:


  1. 源和目标设置是否处理相同的任务。

  2. 源域和目标域的性质。

  3. 学习任务的顺序。


我们可以在下面的分类中看到这些差异:


上图是自然语言处理中迁移学习的分类法。(Ruder,2019 年)


上图是自然语言处理中迁移学习的分类法。(Ruder,2019 年)


顺序迁移学习是迄今为止带来最大改进的形式。通常的做法是,使用你选择的方法在大型未标记文本语料库中的表示(Representations)进行预训练,然后使用标记数据将这些表示适应于受监督的目标任务,如下图所示:


上图展示了顺序迁移学习的一般过程。


上图展示了顺序迁移学习的一般过程。

主要主题

在如何应用这一范例中,可以观察到几个主要的主题:


从单词到上下文单词


随着时间的推移,表示包含了更多的上下文。早期的方法,如 word2vec(Mikolov 等人,2013 年),就已经学会了每个单词独立于上下文的单一表示法。之后的方法将这些表示扩展到句子和文档中(Le、Nikolov,2014 年Conneau 等,2017 年)。当前的方法学习基于单词的上下文变化的单词表示(McCann 等,2017 年Peters 等,2018 年)。


语言建模预训练


许多成功的预训练方法都是基于语言建模(Language Modelliing,LM)的变体。语言建模的优点是不需要任何人工注释,并且许多语言有足够的文本可用于学习合理的模型。此外,语言建模是多方面的,能够用各种各样的目标函数来学习句子和单词的表示。


从浅到深


在过去的几年里,自然语言处理中最先进的模型已经变得越来越深入。直到两年前,大多数任务的技术水平都是 2~3 层的 BiLSTM,机器翻译是具有 16 层的离群值(outlier)(https://arxiv.org/abs/1609.08144">Wu 等人,2016 年)。相比之下,目前的模型,如 BERT-Large 和 GPT-2 这样的模型,由 24 个 Transformer 组组成,最近的模型甚至更深。


预训练与目标任务


预训练和目标任务的选择紧密相连。例如,句子表示对于单词级的预测没有用处,而基于跨度的预训练对跨度级预测很重要。总的来说,为了获得最佳的目标性能,选择类似的预训练任务是有益的。

预训练

为什么语言建模如此有效?

预训练的语言模型所取得的巨大成功着实让人惊讶。语言建模之所以取得成功的原因之一可能是,即使对于人类来说,这也是一项非常困难的任务。为了有机会解决这一任务,模型需要学习语法、语义以及关于世界的某些事实。给定足够的数据、大量的参数和足够的计算,模型就可以完成合理的工作。根据经验来看,语言建模比其他预训练任务(如翻译或自动编码)更有效(Zhang 等人,2018 年Wang 等人,2019 年


最近对人类语言的预测率失真(predictive-rate distortion,PRD)分析(Hahn、Futrell,2019 年)表明,人类语言和语言建模具有无限的统计复杂性,但在较低水平上可以很好地近似。这一观察结果有两个含义:


  1. 用相对较小的模型可以得到较好的结果。

  2. 模型有很大的扩展潜力。


对于这两个含义,我们都有经验证据,将在下一节中出示这些证据。

样本效率

预训练的主要好处之一是,它减少了对带注释数据的需求。在实践中,与未经训练的模型相比,迁移学习通常可以获得类似的性能,后者所需的样本数量要少 10 倍或更多,如下图 ULMFiT 模型所示的那样(Howard、Ruder,2018 年)。


上图中,从零开始训练的模型(蓝色曲线)与两个预训练模型性能为别在标记的目标数据(橙色曲线)以及未标记的目标数据(绿色曲线)上进行微调。(Howard、Ruder,2018 年)


上图中,从零开始训练的模型(蓝色曲线)与两个预训练模型性能为别在标记的目标数据(橙色曲线)以及未标记的目标数据(绿色曲线)上进行微调。(Howard、Ruder,2018 年)

扩展预训练

通常可以通过共同增加模型参数的数量和预训练数据的数量来改进预训练表示。随着预训练数据数量的增加,返回开始减少。然而,当前的表现曲线(如下图所示),并不表示我们已经达到稳定状态。因此,我们可以期待在更多数据上训练更大的模型。


上图展示了使用不同数量的 Common Crawl 数据的平均 GLUE 得分。(Baevski,2019 年)


上图展示了使用不同数量的 Common Crawl 数据的平均 GLUE 得分。(Baevski,2019 年)


这种趋势的最新例子是


ERNIE 2.0



XLNet



GPT-2 8B



RoBERTa


。后者尤其发现,简单地对 BERT 进行更长时间和更多数据的训练,可以改善结果;而 GPT-2 减少了对语言建模数据集的困惑(虽然只有相对较小的因素)。

跨语言的预训练

预训练的一个主要承诺是,它可以帮助我们弥合数字语言的鸿沟,并使我们能够学习世界上 6000 多种语言中的更多自然语言处理模型。许多关于跨语言学习的研究工作都集中在训练不同语言中单独的词嵌入并学习如何排列它们(Ruder 等人,2019 年)。同样,我们可以学习结合上下文表示(Schuster 等人,2019 年)另一种常见的方法是共享一个子词汇表,并在多种语言上训练一个模型(Devlin 等人,2019 年Artetxe、Schwenk,2019 年Mulcaire 等人,2019 年Lample、Conneau,2019 年)。虽然这很容易实现,而且是一个强有力的跨语言基线,但它会导致低资源语言的表示不足(Heinzerling、Strube,2019年)。特别是多语言 BERT 已经成为最近备受关注的话题(Pires 等人,2019 年Wu、Dredze,2019 年)。尽管零样本的性能表现强大,但专用的单语语言模型往往更有竞争力,同时更有效率(Eisenschlos 等人,2019 年)。

实际考虑

预训练的成本很高。我们在教程中使用的 Transformer-XL 样式模型在 8 块 V100 图形处理器上进行预训练需要 5~10 个小时(若使用一块 V100 则需要几天的时间),才能达到良好的困惑度(perplexity)。因此,共享预训练模型非常重要。预训练对于超参数的选择是相对稳健的,除了 Transformer 需要对学习率进行“热身”外。作为一般规则,如果数据集足够大,模型应该没有足够的容量来进行过拟合。掩码语言建模(Masked language modeling)(如 BERT)的训练速度通常比标准的语言建模慢 2~4 倍,因为掩码只有一小部分单词产生的信号会更小。


译注:信息论中,困惑度度量概率分布或概率模型的预测结果与样本的契合程度,困惑度越低则契合越准确。该度量可以用于比较不同模型之优劣。

表示中有哪些内容?

表示(Representations)已经被证明,可以预测某些语言现象,例如翻译中的对齐或句法层次。在使用语法进行预训练时,可以获得更好的性能;即使没有显式地度语法进行编码,表示仍然可以学习一些语法的概念(Williams 等人,2018 年)。最近的工作进一步表明,语法知识可以有效地提炼到最先进的模型中(Kuncoro 等人,2019 年)。网络架构通常决定表示中的内容。例如,已经观察到 BERT 可以捕获语法(Tenney 等人,2019 年Goldberg,2019 年)。不同的架构在它们捕获的信息方面显示了不同的分层趋势(Liu 等人,2019 年)。


上图展示了探究任务的一般设置,用于研究上下文词汇表示中的语言知识。(Liu 等人,2019 年)


上图展示了探究任务的一般设置,用于研究上下文词汇表示中的语言知识。(Liu 等人,2019 年)


模型捕获的信息也取决于你如何看待它:可视化激活或注意力权重提供了模型知识的鸟瞰图,但侧重于一些样本;为了预测某些特性(如上所述)而训练分类器的探测器发现了语料库范围内的特定特性,但也可能会引入它们自己的偏差;最后,网络消融(network ablations)对于改进模型非常有用,但有可能是针对特定任务的。

适应

为了使预训练模型适应目标任务,我们可以在几个正交方向上进行决策:架构修改、优化方案,以及是否获得更多的信号。

架构修改

对于架构修改,我们有两个常规选项:


  1. 保持预训练模型内部不变


这可以像在预训练模型上添加一个或多个线性层一样简单,这通常是通过 BERT 来完成的。相反,我们也可以使用模型输出作为单独模型的输入,当目标任务需要预训练的嵌入中不可用的交互时,例如跨度表示或跨句关系建模时,这通常是有意的。


  1. 修改预训练模型内部架构


我们这样做的原因之一是为了适应一个结构不同的目标任务,比如具有多个输入序列的目标任务。在这种情况下,我们可以使用预训练模型来初始化尽可能多的结构不同的目标任务模型。我们可能希望应用特定于任务的修改,比如添加跳过或残差连接(residual connections)或注意力。最后,通过在预训练模型的隔层之间添加瓶颈模块(“适配器”),修改目标任务参数可以减少需要微调的参数数量(Houlsby 等人,2019 年Stickland、Murray,2019 年)。


上图中,Transformer 块(左)中使用的适配器层(右)。(Houlsby 等人,2019 年)


上图中,Transformer 块(左)中使用的适配器层(右)。(Houlsby 等人,2019 年)

优化方案

在优化模型方面,我们可以选择哪些权重需要更新,以及更新权重的方式和时间。

哪些权重需要更新

为了更新权重,我们可以调整或不调整(预训练权重):


  1. 不要改变预训练权重(特征提取)


在实践中,线性分类器在预训练的表示上进行训练的。最佳性能通常是通过不仅使用顶层的标识,而且学习层的标识的线性组合来实现的(Peters 等人,2018 年Ruder 等人,2019 年)。或者,预训练的报时可以用作下游模型中的特征。当添加适配器时,只训练适配器层。


上图中展示了在单独的下游模型中使用预训练模型作为特征。


上图中展示了在单独的下游模型中使用预训练模型作为特征。


  1. 更改预训练权重(微调)


预训练权重用作下游模型参数的初始化。然后,在适应阶段对整个预训练架构进行训练。

如何以及何时更新权重

选择顺序以及如何更新权重的主要动机是,我们希望避免覆盖有用的预训练信息,并对语言移转(positive transfer)进行最大化。与此相关的是灾难性遗忘(catastrophic forgetting)的概念(McCloskey、Cohen,1989 年French,1999 年),如果一个模型忘记了它最初被训练的任务,就会发生这种情况。在大多数设置中,我们只关心目标任务的性能,但这可能会因应用程序而异。


更新模型参数的指导原则是从上到下依次更新参数,包括时间、强度或与预训练模型进行比较:


  1. 渐进式时间(冻结)


主要是从直觉上来看,在不同分布和任务的数据上,同时训练所有层可能会导致不稳定性,并得到很差的解决方案。相反,我们对每个层进行单独的训练,让它们有时间去适应新的任何和数据。这可以追溯到早期深度神经网络的分层训练(Hinton 等人,2006 年Bengio 等人,2007 年)。最近的方法(Felbo 等人,2017 年Howard、Ruder,2018 年Chronopoulou 等人,2019 年)主要是在一起训练的层组合上有所不同;所有的参数最终一起训练。对于 Transformer 模型的解冻,尚未进行详细的研究。


  1. 渐进式强度(较低的学习率)


我们希望使用较低的学习率来避免覆盖有用的信息。在较低层(因为它们获取更多的一般信息)、在训练早期(因为模型仍需要适应目标分步)和训练后期(当模型接近收敛时),较低的学习率尤为重要。为此,我们可以使用区分(Discriminative)微调(Howard、Ruder,2018 年),它会降低每一层的学习率,如下所示。为了在训练早期保持较低的学习率,可以使用三角学习率计划表,也称为 Transformer 的学习率“预热”。Liu 等人(2019 年)最近指出,“预热”可以减少训练早期阶段的差异。


上图中展示的是区分微调(Howard、Ruder,2018 年)。


上图中展示的是区分微调(Howard、Ruder,2018 年)。


  1. 渐进式与预训练模型(正则化)


最小化灾难性遗忘的一种方法是,利用正则化项,鼓励目标模型参数保持接近预训练模型的参数(Wiese 等人,CoNLL 2017Kirkpatrick 等人,PNAS 2017)。

权衡和实际考虑

一般来说,你需要从头开始训练的参数越多,训练就越慢。特征提取需要添加比微调更多的参数(Peters 等人,2019 年),因此训练通常比较慢。然而,当模型需要适应许多任务时,特征提取更省空间,因为它只需在内存中存储预处理模型的一个副本即可。适配器通过为每个任务添加少量附加参数来达到平衡。


在性能方面,没有哪种适应方法在每种环境下都明显优越。如果源任务和目标任务不同,那么特征提取似乎更可取(Peters 等人,2019 年)。否则,特征提取和微调通常执行类似的操作,尽管这取决于超参数调优的可用预算(微调往往需要更广泛的超参数搜索)。有趣的是,与 LSTM 相比,Transformer 更容易进行微调(对超参数不是那么敏感),通过微调可以获得更好的性能。


然而,大型预训练模型(例如 BERT-Large)在对小型训练集的任务进行微调时,容易出现性能下降。在实践中,观察到的行为通常是“开 - 关”的:从下图中可以看出,模型要么运行良好,要么根本不起作用。了解这种行为的条件和原因,目前还是一个有待研究的问题。


上图为跨 20 个随机重新启动的得分分布图。得分分别来自 BERT(红色)和在 MNLI 上微调的 BERT(绿色)。当微调的单次任务不超过 5K 示例时,BERT 在 MNLI(绿色)上进行微调。(Phang 等人,2018年)


上图为跨 20 个随机重新启动的得分分布图。得分分别来自 BERT(红色)和在 MNLI 上微调的 BERT(绿色)。当微调的单次任务不超过 5K 示例时,BERT 在 MNLI(绿色)上进行微调。(Phang 等人,2018 年)

获得更多信号

目标任务通常是低资源任务。我们通常可以通过组合各种信号来提高迁移学习的效果:

顺序适应

如果有相关任务可用,我们可以在对目标任务进行微调之前,先在相关任务上使用更多数据对模型进行微调。这对于数据有限和类似任务的任务尤其有用(Phang 等人,2018 年),并能提高目标任务的采样效率(Yogatama 等人,2019 年)。

多任务微调

或者,我们也可以在相关任务上与目标任务一起对模型进行共同微调。相关任务也可以是非监督的辅助任务。语言建模就是一个很好的选择,而且已经证明,即使没有经过预训练,它也能有所帮助(Rei 等人,2017 年)。任务比率可以选择性地进行“退火”,以在训练结束时不再强调辅助任务(Chronopoulou 等人,NAACL 2019)。语言模型微调在 ULMFiT 中作为一个独立步骤来使用(Howard、Ruder,2018 年)。最近,即使有许多目标任务,多任务微调也带来了改进(Liu 等人,2019 年Wang 等人,2019 年)。

数据集切片

我们可以使用仅针对数据的特定子集进行训练的辅助头,而不是使用辅助任务进行微调。为此,我们首先分析模型的误差,利用启发式算法自动识别训练数据中具有挑战性的子集,然后与主头一起训练辅助头。

半监督学习

我们还可以使用半监督学习方法,通过扰动(perturbation)未标记的样本,使模型的预测更加一致。扰动可以是噪声、掩蔽(Clark 等人,2018 年),或数据扩增,如回译(back-translation)(Xie 等人,2019 年)。


译注:Sennrich 等人于 2015 年提出了一个非常高效的数据增强方案,我们称之为 “回译(back-translation)”,即从目标语言到源语言的辅助翻译系统首先在可用的并行数据上进行训练,然后用于从大的目标端的单语语料库中生成翻译。然后将这些翻译的组成对以及与其相对应的参考目标(ground truth targets)用作原始翻译系统的附加训练数据。

组合

为了提高性能,可以组合使用不同超参数进行微调的模型预测、使用不同与处理模型微调的模型预测、或者在不同目标任务或数据集切片进行训练的模型预测。

提炼

最后,大型模型或模型组合可以被提炼为一个单一的、较小的模型。该模型也可以简单得多(Tang 等人,2019 年),或者具有不同的归纳偏向(inductive bias)(Kuncoro 等人,2019 年)。多任务微调也可以与提炼结合(Clark 等人,2019 年)。

下游应用

对大型模型进行预处理,不仅在计算方面,而且在环境问题方面都是很昂贵的(Strubell 等人,2019 年)。只要有可能,最好使用开源模型。如果你需要训练自己的模型,请与社区分享你的预训练模型。

框架和库

对于共享和访问语序努力安模型,有不同的选项可供选择:


Hub


Hub (枢纽中心)是中央存储库,它为访问预训练模型提供了公共 API。两个最常见的 Hub 是 TensorFlow HubPyTorch Hub。Hub 通常使用起来很简单;然而,它们更像是一个黑匣子,因为模型的源代码并不能轻易访问到。此外,修改预训练模型架构的内部结构可能很困难。


作者发布的检查点


检查点文件通常包含预训练模型的所有权重。与 Hub 模块相比,模型图仍然需要创建,并且需要单独加载模型权重。因此,检查点文件比 Hub 模块更难使用,但为你提供了对模型内部的完全控制。


第三方库


一些第三方库,如 AllenNLPfast.aipytorch-transformer,可以方便地访问预训练模型。这类库通常能够快速进行实验,并涵盖许多迁移学习的标准用例。


有关如何将这些模型和库用于下游任务的示例,请查看幻灯片、Colaboratory notebook代码中的代码片段

未解决问题及未来方向

还有许多未解决的问题,以及有趣的未来研究方向。下面只是一个更新的选择,要了解更多的信息,请查看幻灯片

预训练语言模型的缺陷

预训练语言模型仍然不擅长细粒度的语言任务(Liu 等人,2019 年)、层次句法推理(Kuncoro 等人,2019 年)和常识(当你把事情弄得很复杂时;Zellers 等人,2019 年)。它们在自然语言生成方面仍未取得成功,特别是无法维护长期的依赖性、关系和连贯性。经过微调后,它们也倾向于过拟合表面形式的信息,并且仍然可以被视为“快速表面学习者”。


正如我们在上面所提到的,特别是对少量数据进行微调的大型模型很难进行优化,并且还会存在较大的差异。目前的预训练语言模型也非常庞大。提炼和修剪是解决这一问题的两种方法。

预训练任务

虽然语言建模目标已经证明在经验上是有效的,但它也有其不足之处。最近,我们发现,双向上下文和建模连续单词序列很重要。也许最重要的是,语言建模鼓励关注语法和单词的同现(co-occurrences),并且仅仅提供用于捕获语义和长期上下文的弱信号。我们可以从其他形式的自我监督中得到启发。此外,我们还可以设计专门的预训练任务,明确地学习某些关系(Joshi 等人,2019 年Sun 等人,2019 年)。


总的来说,从原始文本中学习某些类型的信息可谓蜀道之难。最近的方法结合了结构化只是(Zhang 等人,2019 年Logan IV 等人,2019 年)或利用多种多模(Sun 等人,2019 年Lu 等人,2019 年)作为两种潜在的方法来缓解这一问题。


作者介绍:


Sebastian Ruder,供职于 EurNLP,研究科学家,研究方向为自然语言处理迁移学习,目标是让自然语言处理变得更容易。


原文链接:


The State of Transfer Learning in NLP


公众号推荐:

2024 年 1 月,InfoQ 研究中心重磅发布《大语言模型综合能力测评报告 2024》,揭示了 10 个大模型在语义理解、文学创作、知识问答等领域的卓越表现。ChatGPT-4、文心一言等领先模型在编程、逻辑推理等方面展现出惊人的进步,预示着大模型将在 2024 年迎来更广泛的应用和创新。关注公众号「AI 前线」,回复「大模型报告」免费获取电子版研究报告。

AI 前线公众号
2019-08-28 08:008700
用户头像

发布了 522 篇内容, 共 237.2 次阅读, 收获喜欢 1543 次。

关注

评论

发布
暂无评论
发现更多内容

网络攻防学习笔记 Day92

穿过生命散发芬芳

网络攻防 8月日更

解密NFT,进军元宇宙,区块链与价值实体将如何链接?

CECBC

Java 代理模式

gin

Java 代理 Proxy

gopher成长之路(二):听万俊峰老师演讲有感

非晓为骁

学习 个人成长 gopher

01 设计模式之单例模式

陈皮的JavaLib

设计模式 单例模式 8月日更

Discourse 图片上传的更新

HoneyMoose

服装生产流程管理在明道云的实现

明道云

【LeetCode】矩阵中战斗力最弱的 K 行Java题解

Albert

算法 LeetCode 8月日更

【前端 · 面试 】HTTP 总结(一)—— HTTP 概述

编程三昧

面试 大前端 HTTP 8月日更

架构师实战营 模块九总结

代廉洁

架构实战营

Convolutional Neural Network (CNN)

毛显新

神经网络 深度学习 tensorflow 图像识别

架构师实战营 模块九作业(设计电商秒杀系统)

代廉洁

架构实战营

架构实战营毕业总结

白发青年

#架构实战营

非典型开发者的形象三变

脑极体

docker个人理解与安装

小鲍侃java

8月日更

pyinstaller 打包

橙橙橙橙汁丶

菜鸡学习python

Augus

8月日更

聊聊实时数仓架构设计

水滴

实时数仓 数仓架构 8月日更 数仓建设思路

做行业的底层架构者 为区块链+提供更多可能

CECBC

Linux中Shell重定向

入门小站

Linux

架构训练营模块 2 作业 - 学生信息管理系统的架构文档 - 江哲

江哲

带你全面了解 Git 系列 02 - 常用 Git 技巧

淼💦 淼

git GitHub

毕业设计-秒杀业务

白发青年

架构实战营

具备货币属性的比特币,会成为一种货币吗?

CECBC

架构实战营-毕业设计

泄矢的呼啦圈

架构实战营

李运华老师(前阿里P9)架构实战营 毕业总结

代廉洁

架构实战营

现代分布式架构设计原则-可靠性

余朋飞

稳定性 可用性 弹性 可靠性

Git的基本操作

卢卡多多

git flow git reset 8月日更

「SQL数据分析系列」13. 索引和约束

数据与智能

sql 索引 位图

Python OpenCV 图像处理之傅里叶变换,取经之旅第 52 篇

梦想橡皮擦

8月日更

手把手撸二叉树之叶子相似的树

HelloWorld杰少

面试 大前端 二叉树 数据结构与算法 8月日更

一文看懂自然语言处理中迁移学习的现状_AI&大模型_Sebastian Ruder_InfoQ精选文章