想象一家没有档期换主角的戏剧团:那位主角已经身经百战,演技炉火纯青,公司绝不愿意为他重新排练一遍。现在要演一出新戏,导演能做的只有一件事——写提示卡片。P-Tuning 的做法,是在演员上场前把一张写满情绪密码的提词板放在入口处;卡片上的内容不是真实台词,而是模型自己学习的一套“暗号”。Prefix Tuning 则更进一步:演员每进入一个表演环节,导演就递上一张新的耳语卡片。这样既不动主角,又能通过调整这些卡片改变整场戏的走向。这就是 Prefix Tuning 与 P-Tuning 的核心差异:一个在入口提词,一个在每一层幕后递纸条。本文就用这套“递卡片”的比喻,把二者的原理、参数设计、效果对比与工程选型讲清楚。
当你需要低成本地把大模型改造成特定任务专家,理解这两种“递卡片”的思路,能帮你用最少显存拿到最好效果,也是大模型 PEFT 面试与实战的基本功。
目录
可视化演示
对比Prefix Tuning(每层插入前缀)与P-Tuning(仅输入层插入)在插入位置、参数效率和任务效果上的差异。
本节配有交互动效(进入视口后自动加载,约 3KB)。
前缀插入位置对比:Prefix Tuning vs P-Tuning PFX: 每层KV前插入可学习前缀向量 PT: 仅输入Embedding层插入soft prompt PFX参数量 = 2\u00d7L\u00d7len\u00d7d,PT = len\u00d7d PFX: Attn = softmax(Q[K_pre;K]^T[V_pre;V])
核心思想:一张小卡片,主角不动
把大模型想象成一位不能临场换人的名角。全量微调就像让名角从头重学一出新戏,成本极高。Prefix Tuning 与 P-Tuning 的共同点,是让名角继续演,但把导演想加入的小调整写在一叠卡片上。这些卡片不是自然语言,而是模型可训练的连续向量,也就是“虚拟 token”。它们没有字典含义,却像演员之间的暗号:看到暗号,名角就知道该往哪个方向表演。
这些虚拟 token 可以被梯度训练,却不必改动主角任何一层演技。这种思路属于参数高效微调 PEFT:主模型参数冻结,只学习极少量额外参数,就能让模型快速适应新任务。P-Tuning 与 Prefix Tuning 虽然落点不同,但第一步都像是在原始输入前面挂上一段可学习的前缀:
所以,Prefix Tuning 与 P-Tuning 并不是两个互不相干的方向,而是“给冻结模型加连续提示”这个思想在不同深度上的两种落点:一个偏深层,一个偏输入层。
- 新输入
\tilde{X}表示加入提示卡片后,真正送入 Transformer 的新序列。 - 拼接操作
[A; B]表示沿着序列长度方向把 A 和 B 拼接起来。 - 虚拟前缀
\mathbf{p}_{\text{prefix}}是一组可训练的连续向量,不绑定任何具体单词。 - 原始输入
X是原始词 token 经过 embedding 后得到的向量序列。
插入位置:入口提词还是每层递纸条
只在场外提词一次,演员能记住的内容有限;每换一幕都递一张新纸条,影响力就会更直接。P-Tuning v1 的做法的确更接近“入口提词”:在 embedding 之后、第一层 Transformer 之前,把虚拟 token 拼接到输入序列上。Prefix Tuning 则不同,它把前缀放到每一层自注意力模块的 Key 和 Value 上,让每一层都能看到这张卡片。
Transformer 的每一层里,输入会先生成 Q、K、V 三组向量。Prefix Tuning 为每一层额外准备一组可学习的“K 前缀”和“V 前缀”,把原有 K、V 和前缀拼在一起再做注意力计算。这样,原始 token 在计算每个位置的注意力权重时,都会考虑前缀信息:
位置决定能力边界:浅层提示更适合分类、抽取等“理解型”任务;深层提示更容易影响逐字生成的每一步,所以 Prefix Tuning 在生成任务上表现更稳定。
l 层输出是由 Query、拼接后的 Key、拼接后的 Value 一起计算得到的。前缀并不改写原始词向量,而是在注意力层面“加塞”信息。- 层数标记上标
(l)表示这是 Transformer 的第l层。 - 注意力计算
Attn是自注意力运算,负责让序列中的每个位置互相“看”一眼。 - 查询向量
Q^{(l)}由当前层输入变换而来,代表“我在找什么”。 - 键值拼接
[K^{(l)}_{\text{p}}; K^{(l)}]表示在第 l 层原有的 Key 前面再拼一段可学习前缀 Key。 - 值拼接
[V^{(l)}_{\text{p}}; V^{(l)}]同理,前缀 Value 也参与注意力加权。
参数设计:薄卡片与厚卡片
同样是递卡片,P-Tuning 与 Prefix Tuning 的卡片厚度不同。P-Tuning 不只放几个裸向量,它会先用一个提示编码器(常用 LSTM 或 MLP)加工这些虚拟 token,让它们互相有配合,像一个团队。Prefix Tuning 则用一个小的投影网络,把初始参数映射成每一层需要的 K/V 前缀;训练稳定之后,真正使用时只需要保留这张“最终前缀卡”。
如果把参数量写成一个选择结构,最常见的形式是:
例如 12 层、隐藏维度 768、前缀长度 10 的配置下,Prefix Tuning 大约要学习 18 万参数;P-Tuning 的前缀矩阵只有 7680 个参数,加上编码器后仍然远小于全量微调,所以 P-Tuning 的“卡片”通常更轻。
- 总可学习参数
N_{\text{tune}}表示这个方案实际要训练的参数总数。 - 层数
L是 Transformer 的层数,Prefix Tuning 每一层都要放一份前缀。 - 两份副本数字
2表示 Key 和 Value 各一份,这是 Prefix Tuning 特有的开销。 - 前缀长度与隐藏维
P是前缀长度,d是隐藏向量维度,两者相乘得到单份前缀矩阵大小。 - 提示编码器参数
|\theta_{\text{enc}}|是 P-Tuning 中 LSTM/MLP 编码器的参数数量。
训练策略:让卡片在实战中改写法
训练过程就像导演反复看彩排:剧情表现不好,就改写卡片;表现好了,卡片就固定下来。两种方法的主模型都被冻结,真正变化的是那叠提示参数。它们共享同一个目标函数——语言模型原本的预测损失,只不过在预测时多看了这段前缀。
用 \Phi 表示冻结的主模型参数,\theta 表示可学习的前缀或编码器参数,训练目标可以写成:
实际工程里,Prefix 的投影网络和 P-Tuning 的提示编码器都主要为了让训练更稳定,训练完成后真正需要保存的是最终前缀矩阵。两种方法都可以用 Adam 优化,通常只需要关心可学习参数的学习率,而不是全量微调那样调整整个大模型。
- 总损失
\mathcal{L}是整个训练过程中需要最小化的损失值。 - 求和范围
\sum_{t=1}^{T}表示对序列中的 T 个位置逐一计算并累加。 - 条件概率
p_{\Phi}(y_t \mid y_{<t})表示在给定前面词的情况下,模型预测第 t 个词为y_t的概率。 - 冻结主模型
\Phi表示全程冻结的大模型参数。 - 可学习提示
\theta表示我们真正更新的前缀参数或提示编码器参数。
效果对比:谁更适合哪台戏
如果把两种方案放进真实剧场彩排,Prefix Tuning 在 table-to-text、摘要、翻译这类生成任务上表现稳定,常常能用不到 0.1% 的可训练参数接近甚至超过全量微调。P-Tuning v1 则在 SuperGLUE 这类少样本分类任务上非常亮眼,参数更少,更适合标注数据不多的情况。P-Tuning v2 后来补齐了深层提示,也明显缩小了在生成任务上的差距。
一个常被引用的参数效率指标是:
效果上可以这样记:P-Tuning 更像一张薄卡片,非常适合分类和少样本场景;Prefix Tuning 更像一叠厚卡片,每层都有提示,生成长文时更稳。但如果你只有很少的显存,P-Tuning 的激活值占用通常更小;如果要高质量长文本生成,Prefix 或 P-Tuning v2 的收益更明显。
- 效率指标
\eta表示“可训练参数占全模型参数的比例”。 - 可训练参数
|\theta_{\text{trainable}}|是前缀、编码器等真正参与更新的参数量。 - 全量参数
|\theta_{\text{full}}|是大模型全部参数的数量。 - 千分之一上限
\le 0.001意味着最多只训练约 0.1% 的参数。
适用场景:按戏份选卡片
选型很像导演根据戏种选道具:独幕戏放一张入口提词板就够了;长剧则需要每幕都安排提示。放在任务上,如果任务是文本生成、摘要、对话这类需要逐字推理的场景,Prefix Tuning 往往更合适;如果任务是情感分类、意图识别这类理解型任务,特别是在少样本条件下,P-Tuning 更轻更快。
一个经验法则可以写成:
工程上还有一个很实用的场景:多任务共用底座。一个 7B 模型服务多个业务线,不需要每个业务线都保存一份完整模型,只需要为每个业务线保存一张前缀卡片。新业务上线时,也只增加一张新卡片,不动底座,这大大降低部署和存储成本。
- 选择动作
\text{choice}表示我们正在做的方案选择。 - 映射关系
\mapsto表示“根据条件映射到对应方案”。 - 生成任务
\text{long generation}指摘要、写作、对话等长输出任务。 - 少样本分类
\text{few-shot classification}指只有几十到几百条标注数据的分类任务。
与Prompt关系:从入口卡片到深层卡片
要理解 Prefix Tuning 与 P-Tuning 的位置,还需要认识 Prompt Tuning。Prompt Tuning 是最简单的“入口提词板”:只在大模型输入层学习一段连续 soft prompt,没有额外的提示编码器,也没有深层注入。P-Tuning 可以看作 Prompt Tuning 的升级版:仍然在输入层工作,但额外加了一个提示编码器来建模虚拟 token 之间的关系。
P-Tuning v2 则借鉴了 Prefix Tuning 的“深层”思想,在每一层都加入可学习的提示,而不是只在输入层放提示。它的核心形式可以写成:
从演进路径看是:Prompt Tuning 在入口,P-Tuning 在入口加编码器,Prefix Tuning 在每层插 K/V,P-Tuning v2 又回到每层插提示。今天的 PEFT 工具库里,它们往往只是不同配置的前缀模块,选型时不必纠结名字,而要看任务、显存和实测效果。
l 层有一个形状为 P × d 的可学习提示矩阵。P 是前缀长度,d 是隐藏维度。- 可学习提示
\mathbf{p}^{(l)}_{\theta}表示第l层专属的提示参数。 - 层号上标
(l)表示这是第l层,而不是共享同一个提示。 - 矩阵维度
\mathbb{R}^{P \times d}说明它是一个形状为P × d的实数矩阵。
AI 应用场景
电商客服意图识别
阶段:少样本分类与模型部署
解决的问题:传统方式需要标注几万条客服语料,再全量微调一个大模型,成本高且容易过拟合。P-Tuning 只训练输入层提示和提示编码器,冻结底座模型,能用几十到几百条标注样本完成意图识别。
具体案例:某电商平台需要区分“退款”“物流”“投诉”三类客服问题。使用 P-Tuning 在 7B 底座模型上加一个虚拟前缀,只训练 0.1% 左右参数即可上线;新品类出现时,再新增一张前缀卡即可。
金融新闻摘要生成
阶段:内容生成与摘要
解决的问题:金融新闻时效性强,全量微调生成模型代价高、周期长。Prefix Tuning 在每一层注入前缀,对长文本生成更敏感,可以用少量训练数据快速得到可控摘要。
具体案例:券商对每日公告做摘要,用 Prefix Tuning 训练一个任务前缀,共享同一个冻结的 BART 或 GPT 底座。每天新公告只需一次前向推理,可读性好且不改变原有模型能力。
多业务线共用底座
阶段:多任务推理与模型服务
解决的问题:多个业务线如果各自部署一套全量微调模型,显存和运维成本成倍增长。Prefix Tuning 允许每个业务只保存自己的前缀卡片,共享同一个底座。
具体案例:一家公司同时做法律问答、客服摘要、简历解析三个产品。底座模型只有一个,每个产品线上挂不同 Prefix 卡片,切任务时只要切换前缀,不用部署多份大模型。
Python 演示
import torchimport torch.nn as nnimport torch.nn.functional as F class FrozenTinyLM(nn.Module): def __init__(self, vocab_size=16, dim=8, layers=2): super().__init__() self.embed = nn.Embedding(vocab_size, dim) self.blocks = nn.ModuleList([nn.Linear(dim, dim) for _ in range(layers)]) self.head = nn.Linear(dim, vocab_size) for p in self.parameters(): p.requires_grad = False def forward(self, text_ids, input_pvec=None, layer_pvecs=None): B = text_ids.size(0) h = self.embed(text_ids) if input_pvec is not None: h = torch.cat([input_pvec.repeat(B, 1, 1), h], dim=1) for i, block in enumerate(self.blocks): if layer_pvecs is not None: p = layer_pvecs[i].unsqueeze(0).repeat(B, 1, 1) h = torch.cat([p, h], dim=1) h = torch.tanh(block(h)) if layer_pvecs is not None: h = h[:, -text_ids.size(1):] logits = self.head(h) return F.log_softmax(logits[:, -1], dim=-1) class PrefixTuning(nn.Module): def __init__(self, lm, dim=8, layers=2, plen=4): super().__init__() self.lm = lm self.layer_pvecs = nn.ParameterList( [nn.Parameter(torch.randn(plen, dim) * 0.1) for _ in range(layers)] ) def forward(self, x): return self.lm(x, layer_pvecs=self.layer_pvecs) class PTuning(nn.Module): def __init__(self, lm, dim=8, plen=4): super().__init__() self.lm = lm self.input_pvec = nn.Parameter(torch.randn(1, plen, dim) * 0.1) def forward(self, x): return self.lm(x, input_pvec=self.input_pvec) def make_batch(length=3, vocab=16): x = torch.randint(0, vocab, (1, length)) y = torch.randint(0, vocab, (1,)) return x, y def train_tuner(model, steps=80): opt = torch.optim.Adam(model.parameters(), lr=0.05) loss = None for _ in range(steps): x, y = make_batch() opt.zero_grad() loss = F.nll_loss(model(x), y) loss.backward() opt.step() return loss.item() if __name__ == "__main__": torch.manual_seed(0) lm = FrozenTinyLM() prefix_model = PrefixTuning(lm) ptuning_model = PTuning(lm) prefix_loss = train_tuner(prefix_model) ptune_loss = train_tuner(ptuning_model) prefix_params = sum(p.numel() for p in prefix_model.parameters() if p.requires_grad) ptune_params = sum(p.numel() for p in ptuning_model.parameters() if p.requires_grad) print("prefix_loss:", round(prefix_loss, 3)) print("ptuning_loss:", round(ptune_loss, 3)) print("prefix_trainable_params:", prefix_params) print("ptuning_trainable_params:", ptune_params)
p.requires_grad = False冻结主模型全部参数,确保只训练提示部分。self.layer_pvecs = nn.ParameterList(...)为每一层创建一份可学习前缀参数。self.input_pvec = nn.Parameter(...)在输入层保存一份可学习前缀向量。h = torch.cat([p, h], dim=1)把前缀拼到当前序列前面,模拟向前传递“暗号”。h = h[:, -text_ids.size(1):]保持序列长度不变,模拟 Prefix 的深层注入。loss = F.nll_loss(model(x), y)用语言模型交叉熵损失更新提示参数。
常见误区
误区Prefix Tuning 和 P-Tuning 都是加前缀,名字不同而已,随便选一个就行。
正解它们只是共享“连续提示”的大思路,插入位置完全不同。P-Tuning v1 在输入层加提示并配编码器;Prefix Tuning 在每一层注意力 K/V 上加前缀。就像“入口提词板”和“每幕递纸条”,影响路径不一样。
为何常见:两者都叫“前缀”,又都属于 PEFT,初学者容易只看名字不看结构。
误区提示必须是“你好”“总结一下”这种真实句子,虚拟 token 也要能翻译成某个词。
正解虚拟 token 是连续向量,不一定有词典含义。它更像演员之间的暗号,可以直接用梯度训练,比自然语言硬提示更灵活。
为何常见:大家习惯于给模型写提示词,以为所有提示都必须人类可读。
误区P-Tuning 参数更少,所以更先进、效果更好。
正解参数少只代表“卡片薄”。在生成任务上,Prefix Tuning 的每层提示往往更稳定;P-Tuning v1 在生成任务上未必占优。选型要看任务类型,不能只看参数数量。
为何常见:很多人把“参数量少”等同于“效果优”,忽略了浅层提示与深层提示的表达能力差异。
误区主模型完全不动,只加几个向量,效果肯定比不上全量微调。
正解在不少任务上,Prefix Tuning 和 P-Tuning 都能逼近甚至超过全量微调,尤其适合低资源场景。冻结的是旧能力,新任务通过提示卡获得适配能力。
为何常见:直觉上以为“改得越少越没用”,但大模型本身已有丰富知识,缺的只是入口。
误区Prompt Tuning 和 P-Tuning 只是两个叫法,底层完全一样。
正解Prompt Tuning 是最简单的输入层 soft prompt,没有提示编码器;P-Tuning 在输入层之外增加了 LSTM/MLP 编码器;Prefix Tuning 则把提示放到每层 K/V。
为何常见:都包含“Prompt”字样,资料又常混在一起讲,导致概念边界模糊。
面试题
Q1. Prefix Tuning 主要在哪里插入可学习前缀?
- A.在输入嵌入层之后
- B.在每一层注意力 KV 上← 正确答案
- C.在输出 Softmax 之前
- D.仅在第一层之前输入
答案:B。Prefix Tuning 的核心特征是把可学习前缀注入每一层自注意力的 Key/Value 上,而不只是输入层。P-Tuning v1 更像输入层提示,因此 B 正确。
Q2. P-Tuning v1 最典型的做法是?
- A.在输入层加编码器提示← 正确答案
- B.在每层加可学习前缀
- C.全量更新模型全部参数
- D.用强化学习寻找提示词
答案:A。P-Tuning v1 在输入 embedding 处加入虚拟 token,并用 LSTM/MLP 提示编码器建模 token 间依赖;它不更新主模型。B 是 Prefix Tuning 的做法。
Q3. 设 L 为层数、P 为前缀长度、d 为隐藏维度,Prefix Tuning 的 K/V 前缀参数量约为?
- A.L × P × d 个参数
- B.L × 2 × P × d 个参数← 正确答案
- C.P × d 个参数
- D.2 × P × d 个参数
答案:B。每个 layer 需要 Key 前缀和 Value 前缀各一份,所以有系数 2。若只算输入层则没有 L 和 2,因此选 B。
Q4. P-Tuning 使用提示编码器的主要目的是?
- A.增加整体模型参数规模
- B.建模虚拟 Token 之间依赖← 正确答案
- C.把自然语言词转成向量
- D.完全替代 Transformer
答案:B。提示编码器(LSTM/MLP)让多个虚拟 token 之间产生结构化依赖,提高提示表达力。它不是为了简单增加参数,也不能替代主模型。
Q5. 在长文本生成类任务中,通常哪种方案更稳定?
- A.Prefix Tuning 更稳定← 正确答案
- B.P-Tuning v1 更稳定
- C.Prompt Tuning 更稳定
- D.随机初始化更稳定
答案:A。Prefix Tuning 在每一层注入前缀,对逐字生成的影响更直接,因此在生成任务上更稳定;P-Tuning v1 偏向少样本分类场景。
Q6. 关于 P-Tuning v2,下列说法正确的是?
- A.只在输出层加一个向量
- B.只在输入层加提示编码器
- C.在深层每层加可学习提示← 正确答案
- D.冻结后完全不使用提示
答案:C。P-Tuning v2 借鉴 Prefix Tuning 的深层思想,在每一层都加入可学习 prompt,既保留编码器方法,又改善生成任务表现。
Q7. 高效微调中“冻结”大模型的含义是什么?
- A.模型完全不参与计算
- B.主模型不更新只学提示← 正确答案
- C.把模型电源直接关掉
- D.只冻结词嵌入层
答案:B。冻结意味着主模型仍参与前向和反向计算,但梯度不会更新主模型参数,只有额外前缀或编码器被优化。
Q8. 下列哪些属于 Prefix Tuning 的特点?
- A.主模型参数保持冻结← 正确答案
- B.每层 KV 插入前缀← 正确答案
- C.前缀向量需要训练← 正确答案
- D.所有权重全部更新
答案:ABC。Prefix Tuning 是 PEFT 方法,主模型冻结,只训练每层 K/V 前缀。D 是全量微调的行为,与 Prefix Tuning 相反。
Q9. P-Tuning v1 的特点包括?
- A.冻结主模型不更新← 正确答案
- B.使用提示编码器建模← 正确答案
- C.在输入层插入连续提示← 正确答案
- D.全量更新每层权重
答案:ABC。P-Tuning v1 是冻结主模型、输入层加连续提示、并用提示编码器建模依赖的浅层方案。D 属于全量微调。
Q10. 实际选择 Prefix Tuning 或 P-Tuning 时,应考虑?
- A.任务生成还是分类← 正确答案
- B.显存与训练预算← 正确答案
- C.少样本资源是否紧张← 正确答案
- D.模型名称长度
答案:ABC。任务类型直接决定浅层还是深层提示更有效,显存和标注数量决定能否负担更厚的前缀。模型名称长度与效果无约束关系。