【Hugging Face】PEFT 库中的 P-tuningConfig 常用参数和说明

在 Hugging Face 的 PEFT(Parameter-Efficient Fine-Tuning)库中,P-tuningConfig 是用于配置 P-Tuning 方法的类。P-Tuning 是一种参数高效的微调技术,通过在输入序列中添加可训练的连续提示(continuous prompts)来调整预训练模型的行为,而不修改模型的原始权重。P-Tuning 是 Prompt Tuning 的改进版本,结合了更灵活的提示设计和优化的提示嵌入,特别适合生成任务和复杂任务。以下是对 P-tuningConfig 的详细讲解,包括其参数、用法、代码示例和注意事项。


1. P-tuningConfig 概述

P-Tuning 的核心思想是通过学习一组连续的提示嵌入(soft prompts),将其插入到输入序列中,作为任务特定的上下文。与 Prompt Tuning 相比,P-Tuning 通常使用更复杂的提示设计(例如通过 LSTM 或 MLP 建模提示嵌入),并且在生成任务(如语言模型)中表现更好。P-Tuning 的参数量极少,仅涉及提示嵌入的参数,非常适合资源受限的场景。

P-Tuning 的优势

  • 高效性:只训练少量提示参数,参数量远少于全参数微调。
  • 灵活性:通过复杂的提示建模(如 LSTM 或 MLP),提高任务适配能力。
  • 适用于生成任务:在因果语言模型(如 GPT)或序列到序列模型(如 T5)中效果显著。
  • 兼容性:与 Hugging Face 的 Transformers 模型无缝集成。

2. P-tuningConfig 的主要参数

以下是 P-tuningConfig 中常用的参数及其说明(基于 PEFT 库的最新版本):

  • peft_type(默认:"P_TUNING"

    • 指定 PEFT 方法类型,固定为 "P_TUNING"
    • 通常无需手动设置,由类自动处理。
  • task_type(可选,字符串)

    • 指定任务类型,帮助 PEFT 确定模型结构和用途。常见选项包括:
      • "SEQ_CLS":序列分类(如情感分析)。
      • "TOKEN_CLS":token 分类(如 NER)。
      • "CAUSAL_LM":因果语言模型(如 GPT)。
      • "SEQ_2_SEQ_LM":序列到序列模型(如 T5)。
    • 推荐明确指定,尤其是生成任务使用 "CAUSAL_LM""SEQ_2_SEQ_LM"
  • num_virtual_tokens(整数,默认:20)

    • 指定添加到输入序列中的虚拟提示 token 数量。
    • 典型值:10 到 100。更多的 token 增加表达能力,但也增加参数量。
    • 参数量计算:依赖于提示建模方式(例如,num_virtual_tokens * embedding_dim 或更多,如果使用 LSTM/MLL)。
  • prompt_encoder_type(字符串,默认:"LSTM"

    • 指定提示嵌入的编码器类型,用于生成连续提示。选项包括:
      • "LSTM":使用 LSTM 建模提示嵌入(P-Tuning v2 的默认方式)。
      • "MLP":使用多层感知机(MLP)建模提示嵌入。
      • "INNER":直接优化嵌入(类似 Prompt Tuning)。
    • LSTM 通常更适合复杂任务,但参数量稍多;MLP 更简单,参数量较少。
  • encoder_hidden_size(整数,可选)

    • 指定提示编码器(LSTM 或 MLP)的隐藏层大小。
    • 典型值:与模型的 embedding_dim 匹配(如 BERT 的 768,GPT 的 1024)。
    • 如果不指定,默认使用模型的隐藏层大小。
  • encoder_num_layers(整数,默认:2)

    • 指定提示编码器(LSTM 或 MLP)的层数。
    • 典型值:1 到 4。更多层增加表达能力,但也增加参数量。
  • encoder_dropout(浮点数,默认:0.1)

    • 提示编码器中的 Dropout 概率,用于正则化。
    • 典型值:0.0 到 0.5。
  • modules_to_save(列表,可选)

    • 指定需要全量微调的模块(不使用 P-Tuning)。例如,分类头或语言模型头可以放入此列表。
    • 示例:["classifier"]["lm_head"]

3. 使用 P-tuningConfig 的基本流程

以下是一个使用 P-tuningConfig 微调 GPT-2 模型(用于因果语言建模任务)的完整示例:

步骤 1:安装和导入库
pip install peft transformers torch datasets
from transformers import AutoModelForCausalLM, AutoTokenizer, Trainer, TrainingArguments
from peft import P-tuningConfig, get_peft_model
from datasets import load_dataset
步骤 2:加载模型和数据集
# 加载预训练模型和分词器
model_name = "gpt2"
model = AutoModelForCausalLM.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token  # 为 GPT-2 设置 pad token

# 加载数据集(以 wikitext 为例)
dataset = load_dataset("wikitext", "wikitext-2-raw-v1")

# 数据预处理
def tokenize_function(examples):
    return tokenizer(examples["text"], truncation=True, padding="max_length", max_length=128)

tokenized_dataset = dataset.map(tokenize_function, batched=True)
步骤 3:配置 P-tuningConfig
# 配置 P-Tuning
ptuning_config = P-tuningConfig(
    task_type="CAUSAL_LM",           # 因果语言模型任务
    num_virtual_tokens=20,           # 虚拟提示 token 数量
    prompt_encoder_type="LSTM",      # 使用 LSTM 编码器
    encoder_hidden_size=1024,        # 编码器隐藏层大小(匹配 GPT-2)
    encoder_num_layers=2,            # 编码器层数
    encoder_dropout=0.1,             # Dropout 概率
    modules_to_save=["lm_head"]      # 全量微调语言模型头
)

# 将 P-Tuning 应用到模型
peft_model = get_peft_model(model, ptuning_config)

# 查看可训练参数
peft_model.print_trainable_parameters()

输出示例:

trainable params: 2,048,000 || all params: 126,688,608 || trainable%: 1.617

这表明只有约 1.62% 的参数需要训练(LSTM 编码器参数 + 语言模型头参数)。

步骤 4:训练模型
# 配置训练参数
training_args = TrainingArguments(
    output_dir="./results",
    evaluation_strategy="epoch",
    learning_rate=1e-3,                     # P-Tuning 通常需要较高学习率
    per_device_train_batch_size=8,
    per_device_eval_batch_size=8,
    num_train_epochs=3,
    weight_decay=0.01,
)

# 初始化 Trainer
trainer = Trainer(
    model=peft_model,
    args=training_args,
    train_dataset=tokenized_dataset["train"].select(range(1000)),  # 选取子集以加速示例
    eval_dataset=tokenized_dataset["validation"].select(range(200)),
)

# 开始训练
trainer.train()
步骤 5:保存和加载 P-Tuning 模型
# 保存 P-Tuning 参数
peft_model.save_pretrained("./ptuning_model")

# 加载 P-Tuning 模型
from peft import PeftModel
base_model = AutoModelForCausalLM.from_pretrained(model_name)
loaded_model = PeftModel.from_pretrained(base_model, "./ptuning_model")
步骤 6:推理
# 准备输入
inputs = tokenizer("Once upon a time", return_tensors="pt")

# 推理
loaded_model.eval()
outputs = loaded_model.generate(**inputs, max_length=50)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))

4. P-tuningConfig 的优化建议

  • 调整 num_virtual_tokens

    • 较小的值(如 10-20)适合简单任务或快速实验。
    • 较大的值(如 50-100)适合复杂生成任务,但会增加参数量。
    • 参数量与 num_virtual_tokens 和编码器复杂度(LSTM/MLL)相关。
  • 选择 prompt_encoder_type

    • LSTM:适合复杂任务,提供更强的提示建模能力,但参数量较多。
    • MLP:适合简单任务或资源受限场景,参数量较少。
    • INNER:类似 Prompt Tuning,适合快速实验。
  • 配置 encoder_hidden_size

    • 通常设置为模型的 embedding_dim(如 GPT-2 的 1024,BERT 的 768)。
    • 较小的值可以减少参数量,但可能降低性能。
  • 调整 encoder_num_layers

    • 默认 2 层通常足够。增加到 3 或 4 层可增强表达能力,但参数量增加。
    • 较小的值(1 层)适合快速实验。
  • 学习率

    • P-Tuning 通常需要较高的学习率(如 1e-3 或 5e-4),因为只优化少量参数。
    • 使用学习率调度器(如线性衰减)以提高稳定性。
  • 任务类型

    • 确保 task_type 匹配模型类型,例如 GPT 使用 "CAUSAL_LM",T5 使用 "SEQ_2_SEQ_LM"
  • 内存优化

    • P-Tuning 参数量较小,但对于大模型,可以结合 4-bit 量化:
      from transformers import BitsAndBytesConfig
      quantization_config = BitsAndBytesConfig(load_in_4bit=True)
      model = AutoModelForCausalLM.from_pretrained(model_name, quantization_config=quantization_config)
      

5. P-Tuning vs. 其他 PEFT 方法

  • P-Tuning vs. Prompt Tuning

    • 结构:P-Tuning 使用复杂的编码器(LSTM/MLL)建模提示,Prompt Tuning 直接优化嵌入。
    • 参数量:P-Tuning 参数量稍多,但表达能力更强。
    • 适用场景:P-Tuning 更适合生成任务,Prompt Tuning 更通用。
  • P-Tuning vs. Prefix Tuning

    • 结构:P-Tuning 在输入序列添加提示,Prefix Tuning 在每层添加前缀向量。
    • 参数量:P-Tuning 参数量通常少于 Prefix Tuning(取决于编码器)。
    • 适用场景:两者都适合生成任务,P-Tuning 更灵活。
  • P-Tuning vs. LoRA

    • 参数量:P-Tuning 参数量通常少于 LoRA。
    • 灵活性:LoRA 应用于权重矩阵,适合多种任务;P-Tuning 更专注生成任务。
    • 性能:LoRA 在分类任务中可能更优,P-Tuning 在生成任务中表现更好。

6. 常见问题与解答

  • Q1:如何选择 num_virtual_tokens

    • 从 10-20 开始实验。如果生成质量不足,增加到 50 或 100。
    • 注意参数量随 num_virtual_tokens 和编码器复杂度增长。
  • Q2:prompt_encoder_type 如何选择?

    • LSTM:推荐用于复杂任务或大模型。
    • MLP:适合简单任务或快速实验。
    • INNER:类似 Prompt Tuning,适合资源极度受限的场景。
  • Q3:P-Tuning 是否支持所有模型?

    • 支持所有 Hugging Face Transformers 模型,但最适合生成模型(如 GPT、LLaMA、T5)。
    • 对于分类模型(如 BERT),效果可能不如 LoRA。
  • Q4:性能不佳如何优化?

    • 增加 num_virtual_tokensencoder_num_layers
    • 切换 prompt_encoder_type(如从 MLP 到 LSTM)。
    • 调整学习率(尝试 5e-4 到 2e-3)。
    • 检查数据集质量或增加训练轮次。

7. 进阶用法

  • 多任务 P-Tuning

    • 为不同任务创建多个提示:
    ptuning_config_task1 = P-tuningConfig(
        task_type="CAUSAL_LM",
        num_virtual_tokens=20,
        prompt_encoder_type="LSTM"
    )
    ptuning_config_task2 = P-tuningConfig(
        task_type="CAUSAL_LM",
        num_virtual_tokens=20,
        prompt_encoder_type="MLP"
    )
    
    peft_model = get_peft_model(model, ptuning_config_task1, adapter_name="task1")
    peft_model.add_adapter("task2", ptuning_config_task2)
    peft_model.set_adapter("task1")  # 切换提示
    
  • 保存到 Hugging Face Hub

    peft_model.push_to_hub("your-username/ptuning-model")
    
  • 结合量化

    from transformers import AutoModelForCausalLM, BitsAndBytesConfig
    quantization_config = BitsAndBytesConfig(load_in_4bit=True)
    model = AutoModelForCausalLM.from_pretrained(model_name, quantization_config=quantization_config)
    peft_model = get_peft_model(model, ptuning_config)
    

8. 进一步资源

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

彬彬侠

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

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

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

打赏作者

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

抵扣说明:

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

余额充值