Prefix-tuning是一种针对预训练语言模型的参数高效微调方法,由Li和Liang在2021年提出。它的核心做法是:在输入序列前面添加一串可训练的连续向量(称为prefix),微调时只更新这些prefix参数,预训练模型本身保持冻结。
与全参数微调的区别:
| 维度 | 全参数微调 | Prefix-tuning |
|---|---|---|
| 可训练参数量 | 100%(全部参数) | 通常不到1% |
| 每个任务存储 | 完整模型副本 | 仅存储一组prefix向量 |
| 计算开销 | 高(需要完整反向传播) | 低 |
| 效果 | 上限最高 | 接近全参数微调,部分生成任务可超越 |
| 灾难性遗忘风险 | 较高 | 极低(原模型不动) |
核心思想: 通过在每一层Transformer的注意力计算中注入可训练的前缀向量,相当于为模型提供了一个连续的、任务特定的"软提示",引导预训练模型激活与当前任务最相关的内部知识,从而适配下游任务。
为什么用很少参数就能有效:
具体机制:
对于Transformer的每一层,设原始输入的隐藏状态为 $h$,经过线性投影得到Key和Value矩阵 $K, V$。Prefix-tuning在每一层的Key和Value前面拼接可训练的prefix向量:
加在哪些位置: 加在每一层的Key和Value上,而非只加在输入层。这意味着prefix的影响贯穿整个网络的深度。
这是一个很好的追问,能考察理解深度。原因有几点:
保持注意力权重的归一化特性不受干扰。 Query决定了"当前token在关注什么"。如果在Query上拼接prefix,会改变每个原始token的Query表示,从而改变所有token之间的注意力分布,干扰原有的语言建模能力。而在Key和Value上加prefix,相当于增加了模型"可以参考的记忆单元",原始token之间的注意力关系保持不变。
Prefix的作用是"提供额外上下文",而不是"改变每个token的查询意图"。 在Key和Value上加prefix,等价于告诉模型:"在计算注意力时,除了当前序列本身的token,你还可以参考这些额外的键值对。"这是一种更自然的任务指令注入方式。
实验验证支持。 Li和Liang的原始论文中,只在Key上添加和在Key+Value上添加都进行了实验,Key+Value效果最好。而在Query上添加通常会导致训练不稳定和效果下降。
核心区别:
| 维度 | Prompt-tuning | Prefix-tuning |
|---|---|---|
| 添加位置 | 仅在输入层的embedding前拼接可训练向量 | 在每一层的Key和Value前拼接可训练向量 |
| 影响范围 | 只影响第一层的输入表示 | 影响每一层的注意力计算 |
| 可训练参数量 | 更少 | 稍多(但仍在1%以内) |
| 对深层的影响 | 间接(通过逐层传递) | 直接(每层都有任务信号注入) |
为什么Prefix-tuning效果通常更好:
Prompt-tuning只在输入层加入任务信号,这个信号需要通过多层Transformer逐层向前传递,在传递过程中会逐渐衰减和稀释。而Prefix-tuning在每一层都直接注入了任务信号,相当于持续"提醒"模型当前任务是什么,因此对模型深层表示的影响更强、更直接。尤其在模型规模较小时(如BERT-base级别),Prompt-tuning效果会明显下降,而Prefix-tuning仍能保持较好的性能。
三种方法的机制对比:
Adapter(Houlsby et al., 2019):
- 在Transformer的每个子层(注意力层、FFN层)后插入小型瓶颈模块
- 瓶颈模块结构:下投影(d→r) → 非线性激活 → 上投影(r→d),其中 $r \ll d$
- 可训练参数约为模型的3-5%
LoRA(Hu et al., 2021): - 冻结原模型所有参数,为某些权重矩阵(通常是注意力层的 $W_Q, W_V$)添加低秩分解矩阵 - 参数更新量:$\Delta W = BA$,其中 $B \in \mathbb{R}^{d \times r}, A \in \mathbb{R}^{r \times k}$,$r$ 为秩 - 推理时 $\Delta W$ 可以合并到原权重中,不增加推理延迟 - 可训练参数通常不到1%
Prefix-tuning(Li & Liang, 2021): - 在每层Key和Value前拼接可训练向量 - 不修改模型结构,只增加额外的"注意力上下文" - 可训练参数通常不到1%
优缺点对比总结:
| 方法 | 优点 | 缺点 |
|---|---|---|
| Adapter | 效果稳定,各层独立适配 | 参数量相对较大;推理时增加延迟(串行插入模块) |
| LoRA | 推理零延迟(可合并权重);实现简单;分类和NLU任务表现好 | 修改了权重矩阵,不够"即插即用";对生成任务的效果有时不如Prefix |
| Prefix-tuning | 多任务切换方便(换一组向量即可);生成任务表现好;不修改模型结构 | 占用序列长度(prefix占用了注意力窗口);训练不稳定(需要重参数化技巧);推理时增加少量计算 |
这是一个技术选型问题。选择Prefix-tuning的场景:
多任务/多租户部署场景: 需要频繁在不同任务之间切换。Prefix-tuning只需换一组prefix向量,模型本体完全共享,切换成本极低。LoRA虽然也可以换,但通常需要重新加载权重或管理多个合并版本。
文本生成任务(NLG): 如摘要、翻译、对话生成等。大量实验表明Prefix-tuning在生成任务上通常优于LoRA,因为prefix直接影响每一层的注意力计算,对生成过程中每一步的"上下文感知"有更强的引导作用。
模型需要保持完全不变: 有些场景要求基础模型绝对不可修改(如合规、安全审查),Prefix-tuning不改动模型任何权重,天然满足需求。
极端低资源场景: 参数量比LoRA更少(相同prefix长度下),在数据极少时可能更不容易过拟合。
选择LoRA的场景:分类/NLU任务、需要推理零开销、需要合并权重后部署等。
选择原则:
过短的影响:
过长的影响:
经验法则: 简单分类任务用较短prefix(10-20),复杂生成任务用较长prefix(50-100),但具体需要实验验证。
不稳定的原因:
优化空间不同: Prefix向量直接初始化是随机的高维连续向量,它们处在一个与预训练模型内部表示分布不同的空间中。模型在训练初期需要同时"找到"合适的prefix表示,优化方向不确定,容易陷入震荡。
梯度信号稀疏: 只有prefix参数更新,梯度需要经过整个冻结的模型回传到prefix上。在深层网络中,梯度可能过大或过小,导致学习率难以选择。
初始化敏感: 随机初始化的prefix向量可能落在激活函数的饱和区或表示空间的"空洞"中,导致训练初期loss不下降。
改进方法:
重参数化(Reparameterization): 这是原始论文中最重要的技巧。不直接优化prefix向量 $P$,而是用一个小的MLP网络生成prefix:$P = \text{MLP}(z)$,其中 $z$ 是一个较小的可训练向量。训练时优化MLP和 $z$,推理时只用生成的 $P$,丢弃MLP。这样做的好处是:MLP提供了一个平滑的映射,将 $z$ 映射到一个更合理的表示空间,使优化更稳定。
用任务相关的离散token初始化: 不随机初始化,而是用一些与任务相关的词(如"总结:"、"分类:")的embedding来初始化prefix。这给prefix一个更合理的起点。
适当降低学习率并增加warmup: 由于只有prefix参数在更新,梯度动态与传统微调不同。更小的学习率和更长的warmup步数有助于稳定训练。
梯度裁剪: 防止prefix梯度爆炸。
使用AdamW等自适应优化器: 根据梯度的一阶和二阶矩自动调整每个参数的学习率,对prefix优化空间的不均匀性有更好的适应能力。
回答思路:
方案一:每任务独立Prefix(最常用)
方案二:共享Prefix + 任务特定Prefix
方案三:Prefix生成的层次化设计
实际落地考虑:
这个现象在论文和后续研究中被观察到,可能原因:
灾难性遗忘的避免: 全参数微调会改变预训练模型的所有权重,在数据量不够大时可能破坏预训练学到的通用语言能力。Prefix-tuning保持模型不变,只"引导"而不"改变",因此保留了更强的语言生成流畅性。
正则化效果: Prefix-tuning的可训练参数极少,天然是一种强正则化,在数据有限时能防止过拟合训练集分布。
任务信号逐层注入: prefix在每一层都参与了注意力计算,对生成过程的每一步(自回归解码的每个token)都提供一致的任务引导,而全参数微调对生成过程中的不同位置影响可能不均匀。
以长度为 $l$ 的prefix,序列长度为 $n$,层数 $L$,维度 $d$ 计算:
评论专区
评论加载中...登录后即可发表评论