什么是 P-tuning v1

P-tuning v1(也称为 P-tuning,由 Liu et al. 在 2021 年提出)是一种参数高效微调(Parameter-Efficient Fine-Tuning, PEFT) 方法,旨在通过优化连续提示(continuous prompts)来适配预训练语言模型到特定任务,同时保持模型原始参数不变。P-tuning v1 结合了离散提示(discrete prompts,如手动设计的文本提示)和软提示(soft prompts,如 Prompt Tuning 中的连续向量)的优点,通过引入一个小型神经网络(称为提示生成器,prompt encoder)生成任务特定的提示嵌入,从而增强提示的表达能力和任务适配性。

P-tuning v1 可以看作 Prompt Tuning 的增强版,解决了软提示初始化和表达能力不足的问题,尤其在自然语言理解(NLU)任务(如文本分类、关系抽取)中表现出色。以下是对 P-tuning v1 的详细解释:


1. P-tuning v1 的定义与原理

P-tuning v1 的核心思想是在输入序列中插入一组可训练的提示 token(prompt tokens),但这些提示的嵌入不是直接优化的连续向量,而是由一个小型神经网络(提示生成器)动态生成。这种方法结合了离散提示的语义先验和连续提示的灵活性,使模型能够更好地适配特定任务,同时保持参数效率。

工作原理

  • 插入提示 token
    • 在输入序列中插入一组虚拟的提示 token(通常 5-20 个),位置可以是输入的开头、中间或特定位置(如模板中的占位符)。
    • 这些提示 token 的嵌入由提示生成器生成,而不是直接作为可训练参数。
  • 提示生成器(Prompt Encoder)
    • 提示生成器是一个轻量级的神经网络,通常是一个双层 MLP(多层感知机)或 LSTM,输入是提示 token 的索引或初始嵌入,输出是优化后的提示嵌入。
    • 例如,对于一个长度为 k k k 的提示序列,提示生成器将生成 k k k 个嵌入向量,每个向量维度与模型的词嵌入相同。
    • 提示生成器的参数是可训练的,负责捕捉任务特定的语义信息。
  • 初始化与离散提示
    • P-tuning v1 通常使用离散提示(discrete prompts,如“positive”或“negative”)的词嵌入作为提示生成器的初始输入,以提供语义先验。
    • 例如,在情感分类任务中,可以用“positive”和“negative”词的嵌入初始化提示 token。
  • 训练
    • 冻结预训练模型的所有参数,仅优化提示生成器的参数。
    • 提示生成器生成的任务特定提示嵌入与输入文本的词嵌入拼接,送入模型进行计算。
  • 推理
    • 提示生成器生成提示嵌入,与输入文本一起送入模型,参与计算,推理开销极小。

数学表示
假设输入序列为 [ x 1 , x 2 , … , x n ] [x_1, x_2, \dots, x_n] [x1,x2,,xn],P-tuning v1 在序列中插入 k k k 个提示 token [ p 1 , p 2 , … , p k ] [p_1, p_2, \dots, p_k] [p1,p2,,pk]。提示嵌入由提示生成器 f θ f_\theta fθ 生成:
[ p 1 , p 2 , … , p k ] = f θ ( [ i 1 , i 2 , … , i k ] ) [p_1, p_2, \dots, p_k] = f_\theta([i_1, i_2, \dots, i_k]) [p1,p2,,pk]=fθ([i1,i2,,ik])
其中, [ i 1 , i 2 , … , i k ] [i_1, i_2, \dots, i_k] [i1,i2,,ik] 是初始输入(如离散提示的嵌入或索引), θ \theta θ 是提示生成器的可训练参数。最终输入序列为:
[ Embed ( p 1 ) , Embed ( p 2 ) , … , Embed ( p k ) , Embed ( x 1 ) , Embed ( x 2 ) , …   ] [\text{Embed}(p_1), \text{Embed}(p_2), \dots, \text{Embed}(p_k), \text{Embed}(x_1), \text{Embed}(x_2), \dots] [Embed(p1),Embed(p2),,Embed(pk),Embed(x1),Embed(x2),]


2. P-tuning v1 的优点

  1. 参数效率高

    • 提示生成器的参数量极少,通常占模型总参数的 0.01%-0.1%。例如,对于一个 110M 参数的 BERT 模型,提示生成器可能只有几万到几十万参数。
    • 存储需求低,适合多任务部署。
  2. 增强表达能力

    • 通过提示生成器(MLP 或 LSTM)生成提示嵌入,相比直接优化的软提示(Prompt Tuning),P-tuning v1 的提示更具动态性和语义表达能力。
  3. 结合离散提示的先验

    • 使用离散提示的嵌入初始化(如“positive”或“negative”),提供任务相关的语义信息,加速收敛并提升性能。
  4. 适合小数据集

    • 优化少量参数降低过拟合风险,特别适合数据量有限的场景。
  5. 推理开销低

    • 提示生成器仅在输入端添加少量计算,推理时延迟几乎不变。

3. P-tuning v1 的缺点

  1. 性能依赖任务

    • P-tuning v1 在自然语言理解任务(如分类、关系抽取)上表现优异,但在生成任务(如文本生成)上可能不如 Prefix Tuning 或 Adapter Tuning。
  2. 超参数敏感

    • 提示生成器的结构(MLP 或 LSTM)、提示长度、初始化方式等需要仔细调优,可能增加实验复杂性。
  3. 实现复杂度稍高

    • 相比 Prompt Tuning 的简单嵌入优化,P-tuning v1 需要设计和训练提示生成器,代码实现稍复杂。
  4. 对模型规模敏感

    • 类似 Prompt Tuning,P-tuning v1 在大模型(如 GPT-3)上效果更显著,在中小型模型(如 BERT)上可能性能略逊于 Adapter 或 LoRA。

4. P-tuning v1 的代表性实现

  1. P-tuning(Liu et al., 2021):

    • 最早提出 P-tuning 的方法,针对自然语言理解任务(如 SuperGLUE 基准)设计。
    • 使用双层 MLP 作为提示生成器,结合离散提示初始化,在 BERT 和 GPT-2 等模型上展示了优于手动提示的性能。
  2. P-tuning v2

    • 改进版本,进一步优化提示生成器的设计和初始化策略,扩展到更多任务(包括生成任务)。
    • 在性能上更接近 Adapter Tuning 或 LoRA,尤其在大模型上。

5. P-tuning v1 的应用场景

P-tuning v1 特别适合以下场景:

  • 自然语言理解任务:如文本分类、关系抽取、意图检测等,尤其在 SuperGLUE 等基准任务中表现优异。
  • 小数据集场景:数据量有限时,通过优化提示生成器避免过拟合。
  • 多任务学习:为不同任务训练独立的提示生成器,共享同一预训练模型。
  • 提示工程优化:结合离散提示的先验,增强手动提示的效果。
  • 资源受限环境:低存储和计算需求,适合快速部署。

6. P-tuning v1 的代码示例

以下是一个使用 Python 和 Hugging Face 的 transformers 库实现 P-tuning v1 的示例,基于 BERT 模型为 GLUE 的 SST-2(情感分类)任务进行微调。由于 Hugging Face 的 peft 库直接支持 P-tuning,我们将使用其实现。

from transformers import AutoModelForSequenceClassification, AutoTokenizer, TrainingArguments, Trainer
from peft import get_peft_model, PromptEncoderConfig
from datasets import load_dataset
import numpy as np

# 1. 加载预训练模型和分词器
model_name = "bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSequenceClassification.from_pretrained(model_name, num_labels=2)

# 2. P-tuning配置
p_tuning_config = PromptEncoderConfig(
    task_type="SEQ_CLS",
    num_virtual_tokens=20,
    encoder_hidden_size=128,  # MLP的隐藏层维度
    encoder_dropout=0.1,
    encoder_num_layers=2,      # MLP层数
)
model = get_peft_model(model, p_tuning_config)

# 3. 数据预处理
def preprocess_function(examples):
    encoding = tokenizer(
        examples["sentence"],
        padding="max_length",
        truncation=True,
        max_length=128,
        return_tensors="pt"
    )
    encoding["labels"] = examples["label"]  # 添加标签字段
    return encoding

dataset = load_dataset("glue", "sst2")
encoded_dataset = dataset.map(preprocess_function, batched=True)
train_dataset = encoded_dataset["train"].select(range(1000))
eval_dataset = encoded_dataset["validation"]

# 4. 调整训练参数
training_args = TrainingArguments(
    output_dir="./p_tuning_output",
    num_train_epochs=3,
    per_device_train_batch_size=16,
    per_device_eval_batch_size=16,
    eval_strategy="epoch",
    save_strategy="epoch",
    load_best_model_at_end=True, 
    metric_for_best_model="accuracy",  # 定义最佳模型标准
    greater_is_better=True,
)

# 5. 初始化训练器(优化评估指标计算)
def compute_metrics(eval_pred):
    predictions = np.argmax(eval_pred.predictions, axis=1)
    return {"accuracy": (predictions == eval_pred.label_ids).mean()}

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=train_dataset,
    eval_dataset=eval_dataset,
    compute_metrics=compute_metrics,
)

# 6. 训练P-tuning
trainer.train()

# 7. 保存最终模型
model.save_pretrained("./p_tuning_model")

# 8. 推理示例
text = "This movie is fantastic!"
inputs = tokenizer(text, return_tensors="pt", padding=True, truncation=True, max_length=128).to(model.device)
outputs = model(**inputs)
prediction = outputs.logits.argmax(-1).item()
print(f"Prediction: {'Positive' if prediction == 1 else 'Negative'}")

代码说明

  • 模型和 P-tuning:使用 bert-base-uncased 模型,添加 20 个提示 token,由 MLP 提示生成器生成。
  • 数据集:使用 GLUE 的 SST-2 数据集(二分类情感分析),仅用部分数据以加快训练。
  • 训练:仅优化提示生成器的参数,冻结 BERT 的原始参数。
  • 保存和推理:训练后的提示生成器参数保存为小文件(几十 KB),可用于情感分类推理。
  • 依赖:需要安装 transformers, peft, 和 datasets 库(pip install transformers peft datasets)。

运行结果

  • P-tuning v1 通常只需 1-2 GB 的 GPU 内存,远低于全参数微调。
  • 训练后,模型在 SST-2 数据集上可达到 ~88%-92% 的准确率,接近 Adapter Tuning 的性能。

7. 与其他 PEFT 方法的对比

方法参数效率推理延迟性能(相对全参数微调)适用场景
P-tuning v1极高无增加接近NLU 任务、小数据集
Prompt Tuning极高无增加稍逊小数据集、API 模型
Prefix Tuning极高无增加稍逊生成任务、低资源场景
Adapter Tuning轻微增加接近多任务、跨语言迁移
LoRA极高无增加接近大模型适配、个性化
  • 与 Prompt Tuning 相比:P-tuning v1 通过提示生成器增强表达能力,性能更稳定,尤其在 NLU 任务上。
  • 与 Prefix Tuning 相比:P-tuning v1 更适合理解任务(如分类),而 Prefix Tuning 更适合生成任务。
  • 与 Adapter Tuning 相比:P-tuning v1 参数量更少,推理速度更快,但 Adapter Tuning 在复杂任务上可能更稳定。
  • 与 LoRA 相比:P-tuning v1 实现稍复杂,但在结合离散提示的场景中更具优势。

8. 总结

P-tuning v1 是一种高效的微调方法,通过使用提示生成器优化连续提示,结合离散提示的先验,实现任务适配。它在参数效率、推理速度和自然语言理解任务中表现优异,特别适合小数据集和提示工程优化的场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

彬彬侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值