【Hugging Face】PEFT 库中的 get_peft_model() 函数:将基础模型转换为支持参数高效微调(PEFT)的模型

在 Hugging Face 的 PEFT(Parameter-Efficient Fine-Tuning)库中,get_peft_model() 函数是用于将基础模型(通常是 Hugging Face Transformers 模型)转换为支持参数高效微调(PEFT)的模型的关键函数。它通过应用指定的 PEFT 配置(如 LoraConfigPromptTuningConfig 等)为模型添加适配器(adapters),从而实现高效微调。以下是对 get_peft_model() 函数的详细讲解,包括其功能、参数、用法、代码示例和注意事项。


1. get_peft_model() 功能概述

get_peft_model() 函数的主要作用是将一个预训练模型(base model)与 PEFT 配置结合,生成一个新的 PeftModel 实例。这个实例包含了基础模型和附加的 PEFT 适配器(如 LoRA 矩阵、Prompt Tuning 提示、IA3 缩放向量等)。适配器只包含少量可训练参数,而基础模型的权重通常保持冻结,从而实现高效微调。

核心功能

  • 根据指定的 PEFT 配置(如 LoraConfigVeraConfig 等)为模型添加适配器。
  • 自动冻结基础模型的权重,仅允许适配器参数可训练(除非配置中指定了 modules_to_save)。
  • 支持多任务适配器(通过 adapter_name 参数)。
  • 返回一个 PeftModel 实例,兼容 Hugging Face 的 Trainer 和推理流程。

2. get_peft_model() 函数签名

以下是 get_peft_model() 函数的签名(基于 PEFT 最新版本):

def get_peft_model(
    model: torch.nn.Module,
    peft_config: PeftConfig,
    adapter_name: str = "default",
    mixed: bool = False
) -> PeftModel
参数说明
  • modeltorch.nn.Module,必填)

    • 基础模型,通常是 Hugging Face Transformers 模型(如 AutoModelForCausalLMAutoModelForSequenceClassification 等)。
    • 示例:model = AutoModelForCausalLM.from_pretrained("gpt2")
  • peft_configPeftConfig,必填)

    • PEFT 配置对象,指定使用的微调方法及其参数。
    • 支持的配置类包括:
      • LoraConfig(低秩适配)
      • PromptTuningConfig(提示微调)
      • PrefixTuningConfig(前缀微调)
      • P-tuningConfig(P-Tuning)
      • IA3Config(缩放向量微调)
      • LoftQConfig(量化低秩适配)
      • VeraConfig(向量基随机矩阵适配)
      • AdaLoraConfig(自适应低秩适配)
    • 示例:peft_config = LoraConfig(task_type="CAUSAL_LM", r=8, target_modules=["c_attn"])
  • adapter_name(字符串,默认:"default"

    • 指定适配器的名称,用于支持多任务或多适配器场景。
    • 示例:adapter_name="task1"
    • 如果需要添加多个适配器,可以后续通过 peft_model.add_adapter() 使用不同的 adapter_name
  • mixed(布尔值,默认:False

    • 是否启用混合精度(mixed precision)支持。
    • 如果为 True,适配器将支持混合精度训练(需要 PyTorch 和适当的硬件支持)。
    • 通常保持默认值 False,除非需要优化内存或性能。
返回值
  • PeftModel
    • 一个 PeftModel 实例,包含基础模型和 PEFT 适配器。
    • 该实例支持 Hugging Face 的 Trainergenerate()(生成任务)以及标准 PyTorch 训练流程。
    • 提供方法如 print_trainable_parameters() 查看可训练参数。

3. 使用 get_peft_model() 的基本流程

以下是一个使用 get_peft_model() 微调 GPT-2 模型(用于因果语言建模任务)的完整示例,展示如何结合 LoraConfig

步骤 1:安装和导入库
pip install peft transformers torch datasets
from transformers import AutoModelForCausalLM, AutoTokenizer, Trainer, TrainingArguments
from peft import LoraConfig, get_peft_model
from datasets import load_dataset
步骤 2:加载模型和数据集
# 加载预训练模型和分词器
model_name = "gpt2"
model = AutoModelForCausalLM.from_pretrained(model_name, device_map="auto")
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:配置 PEFT(以 LoraConfig 为例)
# 配置 LoRA
lora_config = LoraConfig(
    task_type="CAUSAL_LM",           # 因果语言模型任务
    r=8,                             # 低秩矩阵的秩
    lora_alpha=16,                   # 缩放因子
    lora_dropout=0.1,                # Dropout 概率
    target_modules=["c_attn"],       # 应用 LoRA 的模块(GPT-2 的注意力层)
    modules_to_save=["lm_head"]      # 全量微调语言模型头
)

# 使用 get_peft_model() 创建 PEFT 模型
peft_model = get_peft_model(model, lora_config, adapter_name="default")

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

输出示例:

trainable params: 294,912 || all params: 124,747,008 || trainable%: 0.236

这表明只有约 0.24% 的参数需要训练(LoRA 权重 + 语言模型头参数)。

步骤 4:训练模型
# 配置训练参数
training_args = TrainingArguments(
    output_dir="./results",
    evaluation_strategy="epoch",
    learning_rate=2e-5,
    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:保存和加载 PEFT 模型
# 保存 PEFT 适配器
peft_model.save_pretrained("./lora_model")

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

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

4. 支持的 PEFT 配置

get_peft_model() 支持以下 PEFT 配置类,每种配置对应一种微调方法:

  • LoraConfig:低秩适配(LoRA),通过低秩矩阵更新权重。
  • AdaLoraConfig:自适应 LoRA,动态调整秩。
  • PromptTuningConfig:提示微调,添加可训练的虚拟 token。
  • PrefixTuningConfig:前缀微调,为每层添加前缀向量。
  • P-tuningConfig:P-Tuning,使用 LSTM 或 MLP 建模提示。
  • IA3Config:(IA)^3,通过缩放向量调整激活。
  • LoftQConfig:量化 LoRA,结合量化初始化。
  • VeraConfig:VeRA,使用共享低秩矩阵和缩放向量。

选择配置的建议

  • 生成任务LoraConfig, VeraConfig, PrefixTuningConfig, P-tuningConfigIA3Config 更适合(如 GPT、LLaMA)。
  • 分类任务LoraConfigPromptTuningConfig 更通用(如 BERT)。
  • 量化场景LoftQConfigLoraConfig 结合 4-bit 量化。
  • 存储受限VeraConfig(可不保存共享矩阵)或 IA3Config(参数量极少)。

5. 进阶用法

以下是一些 get_peft_model() 的高级用法,展示其灵活性:

多任务适配器

支持为不同任务创建多个适配器,并动态切换:

# 配置两个 LoRA 适配器
lora_config_task1 = LoraConfig(
    task_type="CAUSAL_LM",
    r=8,
    target_modules=["c_attn"],
    lora_alpha=16
)
lora_config_task2 = LoraConfig(
    task_type="CAUSAL_LM",
    r=16,
    target_modules=["c_attn"],
    lora_alpha=32
)

# 创建第一个适配器
peft_model = get_peft_model(model, lora_config_task1, adapter_name="task1")

# 添加第二个适配器
peft_model.add_adapter("task2", lora_config_task2)

# 切换适配器
peft_model.set_adapter("task1")  # 使用 task1 适配器
peft_model.set_adapter("task2")  # 切换到 task2 适配器
结合量化

结合 bitsandbytes 进行 4-bit 量化以节省内存:

from transformers import BitsAndBytesConfig

# 加载量化模型
quantization_config = BitsAndBytesConfig(load_in_4bit=True)
model = AutoModelForCausalLM.from_pretrained(model_name, quantization_config=quantization_config)

# 配置 LoRA
lora_config = LoraConfig(
    task_type="CAUSAL_LM",
    r=8,
    target_modules=["c_attn"],
    lora_alpha=16
)

# 创建 PEFT 模型
peft_model = get_peft_model(model, lora_config)
检查可训练参数

使用 print_trainable_parameters() 查看参数分布:

peft_model.print_trainable_parameters()

输出示例:

trainable params: 294,912 || all params: 124,747,008 || trainable%: 0.236
合并适配器权重

将适配器权重合并到基础模型以消除推理延迟:

merged_model = peft_model.merge_and_unload()
merged_model.save_pretrained("./merged_model")
保存到 Hugging Face Hub

将适配器上传到 Hugging Face Hub:

peft_model.push_to_hub("your-username/peft-model")

6. 常见问题与解答

  • Q1:如何选择合适的 peft_config

    • 根据任务和资源选择:
      • 生成任务LoraConfig, VeraConfig, PrefixTuningConfig
      • 分类任务LoraConfig, PromptTuningConfig
      • 量化微调LoftQConfigLoraConfig 结合 4-bit 量化。
      • 存储受限VeraConfig(最小检查点)或 IA3Config(最少参数)。
    • 参考 PEFT 文档中的基准测试或实验不同配置。
  • Q2:为什么 get_peft_model() 报错?

    • 原因 1:target_modules 配置错误
      • 检查 target_modules 是否与模型结构匹配(使用 model.named_modules() 查看)。
      • 示例:LLaMA 使用 ["q_proj", "v_proj"],GPT-2 使用 ["c_attn"]
    • 原因 2:模型不兼容
      • 确保 model 是 Hugging Face Transformers 模型,且支持 PEFT。
    • 原因 3:内存不足
      • 启用量化(4-bit 或 8-bit)或减少 r(LoRA 秩)。
  • Q3:如何添加多个适配器?

    • 使用 get_peft_model() 创建第一个适配器,然后通过 peft_model.add_adapter(adapter_name, peft_config) 添加更多适配器。
    • 示例见“多任务适配器”部分。
  • Q4:mixed=True 有什么作用?

    • 启用混合精度训练(FP16/BF16),减少内存占用并加速训练。
    • 需要 GPU 支持和 PyTorch 的 torch.cuda.amp
  • Q5:如何调试性能不佳?

    • 检查 peft_config 参数(例如,增加 r 或扩展 target_modules)。
    • 调整学习率(LoRA 推荐 2e-5,Prompt Tuning 推荐 1e-3)。
    • 确保数据集质量和预处理正确。
    • 尝试其他 PEFT 方法(例如,从 PromptTuningConfig 切换到 LoraConfig)。

7. 注意事项

  • 模型兼容性

    • get_peft_model() 要求输入模型是 torch.nn.Module 的子类,且通常是 Hugging Face Transformers 模型。
    • 非 Transformer 模型可能需要自定义适配器配置。
  • 冻结权重

    • 默认情况下,基础模型的权重被冻结,仅适配器参数可训练。
    • 如果需要微调特定模块(如分类头),在 peft_config 中设置 modules_to_save
  • 内存管理

    • 对于大型模型,建议结合 bitsandbytes 的 4-bit 或 8-bit 量化。
    • 使用梯度检查点(model.gradient_checkpointing_enable())以进一步节省内存。
  • 适配器切换

    • 多任务场景下,确保通过 set_adapter() 切换到正确的 adapter_name
    • 每次推理或训练前检查当前激活的适配器(peft_model.active_adapter)。

8. 进一步资源

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

彬彬侠

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

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

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

打赏作者

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

抵扣说明:

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

余额充值