Prompt Tuning
参考文章:万字长文 Prompt Tuning!
微调方法总结
- 为什么要引入 Prompt?
- Prompt 的经典方法的发展
1. 为什么要引入 prompt?
prompt 旨在解决传统预训练模型(BERT、GPT 等)在 Fine-tune 时的两个痛点:
- 降低语义差异。 预训练任务主要以 Mask Language Modeling 为主(next prediction 等效果不好,不常用),而下游任务则重新引入新的训练参数,两个阶段的训练目标具有较大差异。因此需要缩小 Pre-train 和 Fine-tune 两个阶段目标差异过大的问题。
- 避免过拟合。 由于 Fine-tune 需要引入额外的参数以适配相应的任务需要,因此在样本数量有限的情况下容易发生过拟合,模型泛化能力下降。
2. Prompt 的定义
以下游情感分类为例,prompt 希望将分类问题转换为预训练的重构 Mask 问题。给定句子[CLS] I like the Disney films very much.[SEP],传统分类方法是得到 CLS 表征后通过 MLP 进行分类。
Prompt 有一下两个重要概念,Pattern-Verbalizer-Pair(PVP),在后续的大多数研究中都采用这种 PVP 组件:
- Pattern(Template)。 prompt 的第一步就是为相关句子构建一个模版,比如 “It was [Mask]”,并拼接到原始输入中,可以得到 “[CLS] I like the Disney films very much.[SEP] It was [Mask]” 。句子喂给预训练模型,可以得到 Mask 预测的各个 token 的结果。
- Verbalizer ,记 。由于我们只对 Mask 重构得到的部分词感兴趣,因此需要选择指定的标签词 (great、terrible 等),建立一定的映射关系。比如 , 。不同的任务有不同的 label word,不同的 pattern 也对应不同的 label word。
由于每个句子都可以有不同的 pattern 和 verbalizer,对应产生了一些 ensembling 的方法。
- Patterns Ensembling
- Verbalizers Ensembling
- PVPs Ensembling:pattern 和 verbalizer 均进行集成
后续的研究将重点放到了如何生成 pattern 和 verbalizer 上。
3. Prompt 的方法发展
研究发现,不同的 Pattern 和 Verbalizer 会对效果产生差异很大的结果。
构建 Patter 的方法可以总结成:
- 人工构建
- 启发式构建。通过规则、启发式搜索等方法构建合适的模版。
- 生成。给定训练数据,生成合适的模版
- 词向量微调。在训练时加入一些词向量显式地定义离散字符的模版,参与梯度更新
- 伪标记:不显式定义,而是将模版作为可训练的参数
其中,前三种称为离散的模版构建,旨在直接与原始文本拼接显式离散的字符且在训练中始终保持不变,不引入额外参数。
后两种称为连续的模版构建,旨在让模型在训练过程中根据上下文语义和任务目标对模版参数进行连续可调,避免陷入离散不变模版的局部最优,同时增强泛化能力。
基于连续提示的 promt-tuning 的几个代表作:
Prefix-Tuning
Prompt-Tuning
P-tuning
PPT
1. Prefix-Tuning
Prefix-Tuning 在输入 token 之前构造一段与任务相关的 virtual tokens 作为 prefix(实际是随机初始化的 vector),然后 fine-tune 的时候只更新 prefix 部分参数,冻结其他参数。其中,transformer 的每一层(encoder 和 decoder)前面都会随机初始化一段 prefix(只调整 embedding 层的表现力不够)。具体通过 HuggingFace 框架内置的 past_key_value 参数控制,本质上与 Adapter 类似,是在 transformer 内部对 key 和 value 插入可训练的两个 MLP,具体见代码。
同时,为了防止直接更新 prefix 参数导致训练不稳定和性能下降,在 prefix 层前面加了 MLP 结构,随机初始化低维向量,通过 MLP 升维。
2. Prompt-Tuning
Prompt-Tuning 是第一个没有中间层前缀或特定任务输出层的方法,可以看作 Prefix-Tuning 的简化版本,它给每个任务定义了自己的 Prompt,然后拼接到数据上作为输入,但只在输入层(encoder?代码验证)加入 Prompt tokens,并且不需要 MLP 进行调整来解决难训练的问题。
prompt 初始化可以是随机初始化,也可以是用模型词表中的 embedding(更优)。对于分类任务,也可以使用输出类别的 embedding 来限制模型。
同时,Prompt-Tuning 还提出了 Prompt Ensembling,在同一个 batch 里,为同一个任务训练不同的 prompt,相当于训练了不同模型,比模型集成的成本小很多。
3. P-Tuning
P-Tuning 讲离散和连续 Prompt 相结合。图中蓝色表示输入,橙色是 prompt,使用离散的关键信息作为 prompt,同时在不同位置加入连续的 prompt
P-Tuning 在 Prompt-Tuning 的基础上主要做了三个改进(两个应该是同期工作):
- 考虑到了伪标记之间的依赖关系。因此引入 Prompt Encoder,实际采用 LSTM+MLP。相比随机
- 指定上下文词。如果模版全是伪标记,在训练时无法很好控制模版朝着与对应句子相似的语义上优化,因此选定部分与当前句子语义代表性的一些词作为伪标记的初始化(captial)
- 混合提示。将离散与连续 token 相结合。例如[x][it][][mask]
4. P-Tuning v2
现实用的比较多
Prompt Tuning 存在两个问题:
- Fail to work well on small models。当预训练语言模型参数量低于 100 亿时,Prompt Tuning 会比传统的 fine-tuning 差
- Fail to work well on hard NLU(自然语言理解)tasks。发现像序列标注等对推理和理解要求高的任务,prompt-tuning 效果会变差。
因此,P-Tuning v2 相比 v1 进一步优化:
- 取消了 reparamerization:不再使用 MLP 或者 RNN 进行表征,且不再替换 ptr-trained model word embedding,直接对 pseudo token 对应的深层模型的参数进行微调
- Multi-task learning。对于 pseudo token 的 continous prompt,采用 multi-task 方法
- 无需 Verbalizer,且完全变为生成模型。可以在[CLS] 部分输出 sentence-level class,以及每个 token 位置上输出 token-level class。
5. PPT
Prompt-Tuning 通常适用于低资源场景,但由于连续的模版是随机初始化的,存在新的参数,少量样本可能仍然很难确保这些模版很好地被优化。因此简单的方法就是对这些连续的模版进行预训练。
PPT 分别对三种分类任务设计预训练时使用的 PVP(Pattern-Verbalizer Pairs),具体设计可见解说
4. Prompt 的本质
最初的 Prompt Tuning 旨在设计 pattern 和 verbalizer 来解决基于预训练模型的小样本文本分类,然而事实上,NLP 领域涉及到很多除了分类以外大量复杂的任务,例如抽取、问答、生成、翻译等等。因此,我们寻药提炼出 Prompt Tuning 的本质,将 Prompt Tuning 升华到一种更加通用的范式上。
据王嘉宁大佬两年多 Prompt-Tuning 的研究经验,总结了三个关于 Prompt 的本质:
- Prompt 的本质是一种对任务的指令
- Prompt 的本质是一种对预训练任务的复用
- Prompt 的本质是一种参数有效性学习
具体见 原文,面试必背!!!