引言
近年来,以 GPT-4、PaLM-2 等为代表的超大规模语言模型在众多 NLP 任务上刷新了性能上限。然而,将这些千亿甚至万亿参数模型完整复制并梯度更新(Full Fine-Tuning)所产生的计算与存储成本,令绝大多数团队望而却步。参数高效微调(Parameter‑Efficient Fine‑Tuning, PEFT)范式应运而生,其核心主张是:冻结预训练模型的主体权重,仅优化极少量的新增(或部分)参数,即可在多种下游任务上达到与全量微调相当的性能。
在 PEFT 的方法谱系中,Additive(加法型)微调策略通过“在模型结构上额外添加可训练组件”来注入任务知识,既保持了基础模型通用能力的完整保留,又实现了任务的快速适配与切换。本文聚焦 Additive 方法中诞生最早、影响最广泛的一支——Soft Prompt路线,并以Prompt‑Tuning为典型代表,深入解析其概念、原理、适用场景与实现方法,帮助读者仅通过少量“虚拟提示词”即可高效撬动大模型的下游任务能力。
关键字
参数高效微调,Additive PEFT,Soft Prompt,Prompt-Tuning,连续提示,大模型适配,虚拟令牌,少样本迁移
文章目录
- 1. Additive 微调:定义与分类
- 2. Soft Prompt:从离散到连续
- 3. Prompt‑Tuning 核心机制
- 4. Prompt‑Tuning 适用场景与局限性
- 5. Prompt‑Tuning 实现示例
1. Additive 微调:定义与分类
Additive 微调指的是在不修改原模型任何预训练权重的前提下,显式地在网络的输入层或中间层插入新的可训练参数,并通过下游任务的损失信号指导这些新增参数的更新。与 LoRA 等重参数化方法通过低秩矩阵间接修改权重增量不同,Additive 方法在“结构层面做加法”,具备天然的参数隔离与多任务复用优势:每个任务可以独立保存一份轻量级参数包,而骨干模型只需加载一次。
在 Additive 方法论下,主要包含三大类技术:
- Soft Prompt 方法:在输入嵌入序列或各层隐藏状态前方拼接可学习的连续向量,典型代表有 Prompt‑Tuning、Prefix‑Tuning、P‑Tuning 等。
- Adapter 方法:在 Transformer 子层之间插入小型瓶颈网络(通常由降维-非线性-升维构成),通过调整内部表示来适配任务。
- Scale & Shift 方法(如 LLaMA‑Adapter):在注意力计算和前馈层的激活值上施加可学习的缩放与平移因子,以极低成本注入任务信号。
本文重点剖析 Soft Prompt 这一支,因为它直接作用于模型的“输入端”,实现极简且效果出人意料。
2. Soft Prompt:从离散到连续
传统 Prompt Engineering 通过手工编写离散的文本前缀(Hard Prompt,如“将以下句子翻译成英文:”)来引导模型行为。这种方法存在两个固有痛点:设计依赖经验,且离散单词无法被梯度直接优化——哪怕只调换一个词,也可能引起输出质量的剧烈波动。
Soft Prompt(连续提示/软提示)的核心突破,在于将离散提示词泛化为一组连续、可微调的嵌入向量。这些向量并不对应真实词汇,但在嵌入空间中与词嵌入具有相同的维度。将它们拼接到输入序列嵌入之前,模型在反向传播过程中可以直接对这些 Soft Prompt 向量求梯度并更新,从而在连续空间中自动搜索出最优的“任务语义前缀”。
理解 Soft Prompt 的关键维度有三:
- 表示连续性:摆脱离散词表的束缚,在平滑的嵌入空间中学习,梯度优化稳定且高效。
- 参数隔离性:骨干模型完全冻结,Soft Prompt 的梯度不会影响预训练知识,杜绝灾难性遗忘。
- 可插拔与可组合性:每个下游任务只需保存一份数 KB 到数十 KB 的 Soft Prompt 文件,运行时动态加载,无需重新部署模型实例。
从信息论角度看,Soft Prompt 相当于在输入嵌入空间中开辟了少量“可学习的上下文变量”,由下游任务自行决定读入什么“虚拟上下文”最有利于完成任务,这种思路为后续一系列 Prompt 调优方法提供了理论基石。
3. Prompt‑Tuning 核心机制
Prompt‑Tuning由 Lester 等人在 2021 年的论文《The Power of Scale for Parameter‑Efficient Prompt Tuning》中提出,是 Soft Prompt 路线的奠基之作。其做法极为简洁:
对于一个由 Transformer 解码器构成的语言模型,将原始输入 token 序列X = [ x 1 , . . . , x n ] X = [x_1, ..., x_n]X=[x1,...,xn]映射为嵌入矩阵E ∈ R n × d E \in \mathbb{R}^{n \times d}E∈Rn×d,然后在E EE前方拼接m mm个可学习的嵌入向量P = [ p 1 , . . . , p m ] ∈ R m × d P = [p_1, ..., p_m] \in \mathbb{R}^{m \times d}P=[p1,...,pm]∈Rm×d,得到[ P ; E ] [P; E][P;E],送入冻结的模型前向计算。训练时,仅对P PP计算梯度并更新。
形式化地,损失函数为:
L = − log P θ ( y ∣ [ P ; E ] ) \mathcal{L} = -\log P_{\theta}\big(y \mid [P; E]\big)L=−logPθ(y∣[P;E])
其中θ \thetaθ表示模型全部预训练参数(冻结),P PP为可训练的 Soft Prompt 参数。
关键实验发现:
- 参数规模与虚拟tokens数量的关系:当模型参数达到百亿级别时,仅需 5~20 个虚拟 token 即可接近全量微调的性能;而模型较小时(如几亿参数),往往需要更多的 Soft Prompt 或更强的初始化策略才能收敛。
- 初始化策略:随机初始化虽然可行,但使用预训练模型词表中的某些 token 嵌入(如任务相关词)来初始化P PP通常能加速收敛并提升最终效果。现代实践中,还可以使用任务描述文本的嵌入来初始化。
- 与 Prefix‑Tuning 的对比:Prefix‑Tuning 在每一层 Transformer的隐藏状态前方都插入可学习向量,因此参数总量更大,表现力更强,但实现更复杂;而 Prompt‑Tuning 仅在输入层添加向量,更为轻量简洁,在多任务服务化场景中优势明显。
Prompt‑Tuning 的本质,是通过学习一组合适的“虚拟上下文向量”来代替人工设计的提示词前缀,这是一种以极低成本撬动大规模语言模型任务迁移能力的优雅方案。
4. Prompt‑Tuning 适用场景与局限性
Prompt‑Tuning 极小的参数量(通常仅几十 KB)赋予其在以下场景中的独特优势:
- 超大规模模型适配:对于 10B 参数以上的模型,Prompt‑Tuning 仅训练不到 0.01% 的参数便可在多数下游任务上媲美全量微调,且单张消费级 GPU 即可完成训练。
- 多任务快速服务化:每个下游任务只需保存一个微小的 Soft Prompt 文件,线上推理时按需加载,无需为每个任务保留完整的模型实例,大幅降低内存占用与服务成本。
- 少样本与领域特化:在医疗、法律等数据稀少且专业性强的场景中,冻结主干可防止通用知识被覆盖,仅让 Soft Prompt 去捕捉领域相关的上下文线索,适合少样本或零样本迁移。
- 隐私保护与联邦学习:传输数 KB 的 Soft Prompt 远比传输完整模型安全、高效,特别适合数据不出域的联邦学习场景,各方仅共享 Prompt 参数即可实现协作。
- 持续学习:不同任务的 Soft Prompt 相互隔离,新增任务不会干扰已部署任务的 Prompt 向量,天然缓解灾难性遗忘。
局限性:
- 模型规模依赖性强:对于参数量低于十亿的模型,Prompt‑Tuning 的表现往往不及 Prefix‑Tuning 或全量微调,甚至不敌于人工设计的硬提示。
- 复杂推理与生成任务:当任务需要深度推理、多步逻辑或长文本一致性生成时,仅靠少量 Soft Prompt 可能欠拟合,此时需借助 P‑Tuning v2 或 Adapter 等方法提升容量。
- 初始化敏感:不恰当的随机初始化可能导致收敛缓慢或陷入局部最优,需借助文本初始化或多次调参。
在工程实践中,建议先评估模型规模与任务复杂度,若为超大规模模型(如 20B+),Prompt‑Tuning 往往是最轻量且有效的一线方案。
5. Prompt‑Tuning 实现示例
借助 Hugging Face 的peft库,只需数行代码即可完成 Prompt‑Tuning 的配置与训练。以下示例使用 GPT‑2 模型在 SST‑2 情感分类数据集上进行适配,展示从模型加载到训练推理的完整流程。
5.1 环境准备与配置
importtorchfromtransformersimport(AutoModelForCausalLM,AutoTokenizer,Trainer,TrainingArguments,DataCollatorForLanguageModeling)frompeftimportPromptTuningConfig,PromptTuningInit,get_peft_model model_name="gpt2"tokenizer=AutoTokenizer.from_pretrained(model_name)tokenizer.pad_token=tokenizer.eos_token# GPT-2 无 pad tokenmodel=AutoModelForCausalLM.from_pretrained(model_name)peft_config=PromptTuningConfig(task_type="CAUSAL_LM",# 任务类型prompt_tuning_init=PromptTuningInit.TEXT,# 使用文本初始化 Soft Promptnum_virtual_tokens=20,# 虚拟令牌数量prompt_tuning_init_text="Classify if this review is positive or negative:",tokenizer_name_or_path=model_name,)peft_model=get_peft_model(model,peft_config)peft_model.print_trainable_parameters()# 输出示例: trainable params: xxxx || all params: 124439808 || trainable%: 0.00165.2 数据准备
将 SST‑2 数据集中的文本与标签组合为语言模型格式,前文拼接后接标签指示词(例如 “positive” / “negative”)进行自回归训练。
fromdatasetsimportload_dataset raw_datasets=load_dataset("glue","sst2")deftokenize_function(examples):prompts=[f"sentence:{sent}\nlabel:"forsentinexamples["sentence"]]targets=[" positive"iflabel==1else" negative"forlabelinexamples["label"]]full_texts=[p+tforp,tinzip(prompts,targets)]returntokenizer(full_texts,truncation=True,padding="max_length",max_length=128)tokenized_datasets=raw_datasets.map(tokenize_function,batched=True)tokenized_datasets=tokenized_datasets.remove_columns(["sentence","label","idx"])5.3 训练与推理
data_collator=DataCollatorForLanguageModeling(tokenizer=tokenizer,mlm=False)training_args=TrainingArguments(output_dir="./prompt_tuning_sst2",per_device_train_batch_size=4,num_train_epochs=3,logging_steps=50,save_strategy="no",learning_rate=5e-4,report_to="none",)trainer=Trainer(model=peft_model,args=training_args,train_dataset=tokenized_datasets["train"],data_collator=data_collator,)trainer.train()推理时,仅需输入待分类文本,模型将基于训练好的 Soft Prompt 生成后续内容。
peft_model.eval()test_sent="This movie is fantastic!"inputs=tokenizer(f"sentence:{test_sent}\nlabel:",return_tensors="pt")withtorch.no_grad():outputs=peft_model.generate(inputs.input_ids,max_new_tokens=5)print(tokenizer.decode(outputs[0],skip_special_tokens=True))# 预期输出部分包含 " positive"如果需要更轻量地保存和加载 Prompt 权重,可直接保存peft_model的 adapter 部分。
peft_model.save_pretrained("./prompt_tuning_weights")# 加载时frompeftimportPeftModel loaded=PeftModel.from_pretrained(model,"./prompt_tuning_weights")5.4 手动实现思路
若想深入理解 Prompt‑Tuning 底层逻辑,可手动在嵌入层拼接 Soft Prompt 参数,并通过register_forward_pre_hook或直接改写forward方法实现。核心步骤为:冻结骨干参数 → 创建nn.Parameter形状为(num_virtual_tokens, hidden_dim)→ 在输入嵌入前torch.cat→ 调整attention_mask对应前缀部分全部设为 1。该实现可帮助读者掌握 Soft Prompt 的数学本质,但在工程中建议直接使用peft以避免细节错误。
总结
Prompt‑Tuning 作为 Additive PEFT 的里程碑方法,用极简的“连续前缀”设计重新定义了高效适配的范式。它以数 KB 的参数量、完全隔离的任务携带能力和不亚于全量微调的性能,在大模型时代展现出强大的生存力。尽管在模型规模较小或任务高度复杂时存在局限,但 Prompt‑Tuning 与 Prefix‑Tuning、P‑Tuning v2 等后继方法共同构成的 Soft Prompt 技术家族,至今仍是参数高效微调领域最活跃、最实用的分支之一。可以预见,随着模型规模的进一步膨胀和轻量级服务化需求的日益增长,这种“加微而不改重”的适配思想将会在更多实际落地场景中持续发光。