他山之石 | 百度大小模型联动及落地实践

2022-11-17 09:10:49 浏览数 (1)

作者 | 刘佳祥 百度 资深研发工程师 整理 | DataFunTalk

大家好,这里是NeeNLP。近年来,NLP 领域模型发展迅猛,尽管这些模型在效果上带来了显著提升,但它们通常拥有数亿到千亿,乃至万亿的参数,导致训练模型需要较高的计算成本,阻碍了模型实际落地。

举个例子,对于 Baseline 为 4000 万参数的模型,参数增加到 15 亿,整体成本上涨 37 倍,增加到百亿模型成本则上涨 70-80 倍,实际无法承受这么高的成本。

今天,我们分享百度提出的一种大小模型联动的学习方式,小模型可以通过知识蒸馏从大模型中学习,并可以在许多下游任务中达到与大模型相似的性能,从而使其在推理时更轻、更快,同时小模型可以反哺大模型提升大模型的训练精度。

整体分享从以下两个部分展开:

  • 大模型带动小模型训练,提升小模型的收益
  • 小模型反馈促进大模型的学习

01

基础背景知识

蒸馏学习:知识蒸馏采取 Teacher-Student 的架构:将复杂且大的模型作为 Teacher,Student 模型结构较为简单,用 Teacher 来辅助 Student 模型的训练,Teacher 学习能力强,可以将它学到的知识迁移给学习能力相对弱的 Student 模型,以此来增强 Student 模型的泛化能力。复杂笨重但是效果好的 Teacher 模型不上线,单纯是个导师角色,真正部署上线进行预测任务的是灵活轻巧的 Student 小模型。

预训练任务:预训练任务一般包含两步:

① 在大量无标注数据上进行训练得到预训练模型;

② 在具体的业务数据上微调预训练模型。

预训练本质是迁移学习,一般分为两个阶段,第一个阶段主要在大量无标注的数据训练一个预训练模型,耗时几个星期到几个月不等;训练完成之后,预训练模型在小的数据上进行微调,耗时大约一天。

模型蒸馏一般可以分为任务相关蒸馏和任务无关蒸馏。

(a)任务相关蒸馏

(b)任务无关蒸馏

任务相关蒸馏:在微调阶段蒸馏,微调阶段得到针对任务的 Teacher 模型,用 Teacher 模型指导 Student 模型学习。这样做的优势是效果较好,一般教师模型在业务数据上的模型效果基本上是小模型的效果天花板;劣势是教师模型随着下游任务数量的增多而不断增加,维护成本较高。

任务无关蒸馏:在预训练阶段蒸馏,在蒸馏阶段没有一个明确的目标或者目标是自监督的目标,这样它和下游的任务相关程度较低。这个时候加入蒸馏,模型具备一定的训练基础,比不加蒸馏的模型效果好。这种方式的优势是在预训练蒸馏后下游不需要再蒸馏,劣势是整体效果的天花板较低。

02

大小模型联动

1. 大模型带动小模型

①改进1:基于任务相关的蒸馏改进

首先我们将蒸馏拆解为四个元素:蒸馏目标、学生、老师和数据。

在二阶段蒸馏任务中,第一阶段先在通用数据上进行简单的蒸馏,之后在第二个阶段在下游的数据上进行一个蒸馏,这是之前比较符合直觉的二阶段范式。如果利用两阶段进行学习,那蒸馏中的教师、数据和我们的目标已经发生变化。我们认为这种变化不是非常完美的。

我们提出的方法是一种渐进式的蒸馏方案,在原来的二阶段蒸馏中加入多个阶段,在每个阶段只变换一个元素进行蒸馏。比如在第二个阶段 GED,只将通用的 Teacher 换成 Fine Tune 后的 Teacher;在第三个阶段,将通用的大规模数据变成任务数据,让模型在数据分布上进行光滑的变换;在最后的阶段进行完整的蒸馏。

在实验中,我们是四层模型,相比 Bert-Base 快了 9.4 倍,在性能上 Bert-Base 是 79.6,我们的均值是 78,当均值提升 9-10 倍时,损失 1.6,整体来看效果是不错的。

②改进2:任务无关的模型蒸馏改进

任务无关的整体优势是在预训练蒸馏,下游任务直接使用,最大的优势是使用方便。

我们提出的方案是多 Student 的蒸馏框架:在训练的时候一个 Teacher 模型同时训练几个 Student 模型,期间 Teacher 模型只需要训练一遍,同时产出不同尺寸的 Student 模型直接供下游使用,这种方法的问题是下游任务的上限较低。

任务无关蒸馏中比较经典的工作是微软 MiniLM。左边是L层的 Teacher 架构,右边是 M 层的 Student 网络架构,通常 L>M。MiniLM 提出把最后一层的 QK 的 Attention 作为蒸馏的信号,让 Teacher 教导 Student ,用 KL 散度求两个 Attention 之间的距离作为 Student 的学习信号。在另外一方面,将 Teacher 的 Value 和 Value 进行相乘得到一个交互矩阵作为 Attention 信号的补充,也让 Student 去学。这种学习方式可以有效帮助预训练和下游的任务。

但是在这个方案中 Student 模型无法学习到最后一层 Transformer Block 的 FFN 层内容,我们认为这种方式有待改进的,所以我们提出一种 ALD 模型假如现在想要一个六层的 Student 模型,那我们在蒸馏的时候,我们选择使用七层的模型进行蒸馏,在用的时候只要交付下面六层的模型。这样做的好处是六层的模型中每一层的参数都是训练过的,更进一步地,在下游数据集 Fine Tune 的时候,六层和七层可以一起做 Fine Tune。在下游数据中验证,如果只用前六层比没有 ALD 的前六层效果更好。如果六层七层一起做 Fine Tune,效果依赖数据,有些数据集有效果,有些没有。

我们分别测试 GPU 和 CPU 上的蒸馏效果,横轴表示速度,纵轴是通用公开数据集的平均结果,上面这条红线是我们的模型效果。从图上可以看出,在同样的速度下,我们的模型效果是最好的。再横向比较,实现效果最好的情况下,我们的模型也比别人的快。这个得益于两方面——一方面是我们的蒸馏方案,另一方面是我们在 Paddle 上的一些推理优化。

现在这几个模型已经在 Paddle NLP 上开源,右边是二维码和链接,大家有时间可以体验一下。

2. 小模型带动大模型

这里我们主要进行了两个工作:①反向蒸馏②小模型做样本价值判断帮助大模型加速收敛

先介绍小模型反向蒸馏大模型,整体架构基于 KIPT 框架,大模型训练前期利用小模型作为 Teacher 指导大模型帮助大模型快速收敛。正常来说,是大模型的产出信号传给小模型,但是现在正好相反,小模型产出的信号反传给了大模型。原始的 KIPT 的论文一直在验证理解类任务,这和百度搜索的场景类似,比如在百度的搜索框里面中输入了一个查询词 Query,我们要去找很多和 Query 相关的文档呈现给用户。通常这种匹配有很多种做法,刚才讲的双塔单塔其实都是在做类似的事情。

我们在双塔这个匹配的场景上做了一个实验:假如我们有一个已经训好的 55 兆大小的匹配模型,现在我们可以通过让模型变大来增强效果,实验右边是我们在几个数据集上的一个评价。灰线是我们在加入了这个反向蒸馏之前的一个曲线,蓝线是加入反向蒸馏之后的一个策略曲线,可以看到效率提升的效果很明显。

第二个点是利用小模型作样本价值判断。

背景是大模型训练过程耗时较久,我们考虑到在训练过程中每一条样本的价值是相同的吗?每一条样本都需要训练吗?学习过的样本还需要在学习吗?

因此我们引入了一种学术界的方法,可以利用小模型作为样本价值判断模型帮助大模型快速学习。首先先准备一个小模型,将小模型在下游数据集上进行 Fine Tune 得到样本价值判断模型。第二步将大模型在全量数据集上进行训练得到预训练模型,计算预训练模型和样本价值判断模型的 Loss 差值,定义这个 Loss 之差是样本的价值,然后按照这个价值进行排序选出 Top K 的样本进行梯度回传,通过这样的方式让更有价值的样本影响大模型的训练。

样本价值背后的逻辑是假设左边是大模型的 Loss,右边是小模型的 Loss,如果大模型的 Loss 大于小模型的 Loss,说明大模型还没有学会这条样本,小模型已经学会了,小模型可以反哺大模型;如果两个 Loss 都小说明它是一个非常简单的样本。大模型的 Loss 小,小模型的 Loss 大,说明这条样本是小模型的分布之外的样本,就没有必要继续学它。按照这样的推演逻辑,去把高价值的样本保留下进行学习,从相关的测试可以看出,黄线是加入了这个策略之后的效果,蓝线是加入策略之前的效果,我们可以看到在达到同样的指标的情况下,该方法需要的步数更短;纵向来看,最终的效果也有提升。

03

总结

今天分享的是大模型和小模型联动,主要是大模型带动小模型,包括任务相关和任务无关的两种蒸馏方式。小模型带动大模型,一方面有反向蒸馏去加速收敛,另一方面是可以做一些样本价值判断,在收敛的同时帮助提升模型效果。

nlp

0 人点赞