- API 文档
- CLI
- 集成指南
- 博客
高效的变换器 II:知识提取和微调
这篇由两部分组成的帖子着眼于如何通过探索对流行但计算要求很高的基于Transformer的语言建模技术的修改,来提高最先进的 NLP 的效率。
- 解释了为什么变换器的自注意机制具有高计算工作负载。
- 提出了替代的注意机制,该机制运行起来更高效,而且不会显着影响性能。
这篇文章将:
- 探索训练小型模型以重现大型模型输出的方法。
- 解释如何有效地微调语言模型。
- 提供我们对使用不同高效变换器方法的场景的建议。
上一篇文章介绍了 NLP 中语义表示学习的简史,并概述了变换器的自注意力机制的工作方式。 建议可能不熟悉这些内容的读者先阅读这些部分。 这篇文章还分享了上一篇文章中介绍的一些符号。
知识提取是更高效的 Transformer 的一个研究领域,它通过鼓励小型模型 (student) 重现大型模型 (teachers) 的输出来训练小型模型 (student)。 这项技术最初在计算机视觉中的分类任务中受到欢迎,但现已成功应用于包括 NLP 在内的多个领域。 典型的工作流是:
- 使用通用带注释的数据训练大型模型。
- 使用特定于任务的未注释数据(以及特定于任务的带注释的数据,如果可用)训练小型模型以模仿大型模型。
尽管此流程仍涉及训练大型模型,但这是一次性成本。 更频繁的预测任务将由小型模型完成,这种模型的运行效率要高得多。 因此,知识提炼是一种非常受欢迎的技术,用于在硬件受限的环境中(例如在移动设备上)运行机器学习。
考虑文档x和类标签y ,类标签属于C类别之一(即 y reg; {1,2,…, C })。 将大型模型f预测文档x具有类标签y = c的概率表示为p ( c ; f ( x ))。 此概率通常使用以下形式的函数计算:
其中,如果 y = c ,则为 I( c ; y )=1,否则为 0。
目标函数的示例包括:
- 极大似然类型的目标:
- 这等效于最小化p ( c ; f ) 和p ( c ; g ) 之间的 KB 散度。
- 对数之间的负均方误 (MSE):
针对特定任务的提取
biLSTM-SOFT模型通过尝试在分类任务上重现已微调的BERT模型的预测来执行特定于任务的提取。 对于学生模型,它使用单层双向 LSTM。 尽管这是一个递归模型,但由于只有一层,因此运行速度很快。
提纯目标是学生和教师 Logit 之间的负 MSE。 它的运行速度比提取它的 BERT 模型快 400 多倍,但准确性/F1 的性能会差 4-7 点(具体取决于任务)。
在预训练期间进行提取
到目前为止,这篇文章已经介绍了监督学习中的知识提取,因为这是最常用的设置。 但是, DistilBERT会在语言模型预训练和微调阶段执行知识提取。
如上一篇文章的背景知识部分所述,BERT 是使用掩码语言模型进行预训练的。 DistilBERT 将缺失的单词视为类标签,并使用极大似然样式的提取目标函数。 它使用 BERT 预测的缺失词概率分布作为提纯目标的软目标。 作者还添加了一个余弦嵌入目标,该目标可鼓励小型模型将其嵌入的方向与 BERT 生成的方向保持一致。
DistilBERT 采用与 BERT 相同的基本架构,但层数仅为 BERT 的一半,运行速度提高约 38%。 如果仅在预训练期间进行提取,则其保留了 BERT 97% 的性能。 作者还发现,在微调期间执行特定于任务的提取(使用也已针对同一任务进行过微调的 BERT 模型)可进一步提升性能。
利用 Transformer 架构
TinyBERT是一种与 DistilBERT 类似的方法,它在语言模型预训练和微调阶段执行知识提取。 但是,TinyBERT 通过专门利用 Transformer 架构的功能,直接从 BERT 的中间表示(而不仅仅是最终输出)中获取知识。
与 DistilBERT 一样,TinyBERT 采用与 BERT 相同的架构,但层数较少。 首先,定义从学生模型的每一层到教师模型层的映射,即每个学生层都与一个教师层相关联。 然后,它会根据学生图层使用以下三个提取目标函数之一:
- 嵌入层
- 最小化学生和教师嵌入矩阵之间的 MSE。
- 注意层
- 最小化学生和教师注意力矩阵之间的 MSE( 上 一篇文章 等式 (4) 中的 A )加上自注意力操作之后的前馈层的学生和教师输出之间的 MSE。
- 最终(预测)图层
- 使用极大似然式提纯目标来尝试匹配学生和教师的预测概率。 这与 DistilBERT 相同。
与提取出来的 BERT 模型相比,TinyBERT 的运行速度提高了 2 到 9 倍(取决于层数和隐藏状态大小)。 它在很多任务上都始终优于 DistilBERT,这表明与单独的最后一层相比,每一层的提纯目标都更有用。
如上一篇文章的“背景知识”部分所述,训练大型语言模型的最后一步通常是针对感兴趣的任务对其进行微调。 尽管此阶段的运行速度相对较快,但它通常仍涉及更新模型的所有参数。 这意味着硬件要求与预训练阶段相同。 鉴于通常会为每个任务单独运行微调步骤,因此这仍然是训练过程中成本昂贵的阶段。 因此,另一项研究着眼于减少微调期间要更新的参数数量。
微调权重的子集
避免更新模型的所有参数的一种方法是冻结某些图层。 Lee 等人。对此方法的有效性进行经验研究。 他们发现,对于 12 层的 BERT 模型,冻结前 9 层并仅微调最后 3 层,在大多数任务上至少可以达到完全微调性能的 90%。 但是,冻结整个语言模型并简单地训练最终预测层在所有任务中的性能都要差得多。
仅更新偏差项
大多数神经网络架构中的大多数操作都涉及将输入乘以矩阵,然后添加偏差项。 这些操作的组合方式决定了架构。
在 Transformer 中,偏差项(例如上一篇文章中的等式 (1)–(3) 中的b项)所占参数不到总参数的 0.1%。 因此, BitFit建议仅在微调期间更新这些参数,并冻结其余参数。 如果带注释的训练数据有限,则 BitFit 的性能可与微调整个模型相比(有时甚至更好)。 对于大型训练数据集,它的性能仅比完全微调略差。
将小型可训练网络插入到转换器
另一组参数高效的微调方法会冻结整个预训练语言模型,但会引入一小组附加参数,这些参数会针对感兴趣的任务进行训练。 适配器通过在每个变换器层中插入两个 2 层前馈网络来实现此目的。 它们直接插入遵循自注意机制的现有前馈网络之前和之后。 这两个层执行以下操作:
- 第一层将“变换器”的隐藏状态向下投影到低维向量,并应用非线性。
- 第二层将低维向量上投影回变换器隐藏状态大小。
其背后的想法是,通过在整个 Transformer 架构中插入可学习的参数(而不仅仅是训练最终的预测层),模型可以像微调一样调整其内部表示,但效率更高。 适配器调整仅比完全微调差 0.4% 左右,经过训练的参数数量仅为后者的 3.6%。
这两篇文章介绍了几种不同的高效变换器方法。 什么时候适合使用它们?
- 如果您要处理的文档特别长,我们建议使用高效的注意力机制,例如上一篇文章中介绍的机制。 这将减少预训练和推理时间。 性能甚至可能比使用全面的注意力机制更好。
- 如果您的瓶颈在于内存(例如,即使是一批短文档也会导致内存不足错误),请尝试使用精简模型(例如 TinyBERT)。 通过更少的层和更低维度的表示,这将减少模型的内存占用,同时还能加快训练速度。
- 但是,请记住,提取模型仍然需要预训练的完整模型才能学习,并且在预训练和微调期间提取时,通常效果会更好。
- 如果您在微调阶段的带注释数据有限,请使用冻结大多数/所有语言模型参数的微调方法(例如 适配器)可以降低过度拟合的风险,并且通常比微调整个模型效果更好。
- 如果您有大量受监督的下游任务,我们建议使用高效的微调方法。 这将减少为每个任务需要训练和存储的参数数量。
- 尽管高效的微调方法可能比完全微调训练得更快,但它们通常不会提高推理速度(即 从经过训练的模型获取预测)。 实际上,由于插入了额外的层,其中一些模型的推理速度可能会稍微慢一些。