TRL documentation

PEFT 集成

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v1.17.1).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

PEFT 集成

TRL 支持 PEFT(参数高效微调)方法,以实现内存高效的模型训练。PEFT 通过仅训练少量额外参数并保持基础模型冻结,从而实现对大型语言模型的微调,显著降低了计算成本和内存需求。

本指南介绍了如何将 PEFT 与不同的 TRL 训练器配合使用,包括 LoRA、QLoRA 和提示调优技术。

完整的可运行示例,请参阅 SFT with LoRA/QLoRA notebook。

安装

要在 TRL 中使用 PEFT,请安装所需的依赖项:

pip install trl[peft]

如需支持 QLoRA(4 位和 8 位量化),请同时安装:

pip install bitsandbytes

快速入门

所有 TRL 训练器都通过 peft_config 参数支持 PEFT。启用 PEFT 最简单的方法是使用命令行界面并加上 --use_peft 标志:

python trl/scripts/sft.py \
    --model_name_or_path Qwen/Qwen2-0.5B \
    --dataset_name trl-lib/Capybara \
    --use_peft \
    --lora_r 32 \
    --lora_alpha 16 \
    --output_dir Qwen2-0.5B-SFT-LoRA

或者,您可以在 Python 代码中直接传入 PEFT 配置:

from peft import LoraConfig
from trl import SFTTrainer

# Configure LoRA
peft_config = LoraConfig(
    r=32,
    lora_alpha=16,
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
)

# Configure training - note the higher learning rate for LoRA (10x base rate)
training_args = SFTConfig(
    learning_rate=2.0e-4,  # 10x the base rate (2.0e-5) for LoRA
    ...
)

# Create trainer with PEFT
trainer = SFTTrainer(
    model=model,
    train_dataset=dataset,
    peft_config=peft_config,
)

配置 PEFT 的三种方式

TRL 提供了三种不同的方法来配置 PEFT,每种方法都适用于不同的使用场景:

1. 使用 CLI 标志(最简单)

启用 PEFT 最简单的方法是在命令行界面中使用 --use_peft 标志。此方法非常适合快速实验和标准配置:

python trl/scripts/sft.py \
    --model_name_or_path Qwen/Qwen2-0.5B \
    --dataset_name trl-lib/Capybara \
    --use_peft \
    --lora_r 32 \
    --lora_alpha 16 \
    --lora_dropout 0.05 \
    --output_dir Qwen2-0.5B-SFT-LoRA

优点:快速设置,无需编写代码

缺点:仅限于 LoRA,自定义选项较少

2. 将 peft_config 传递给 Trainer(推荐)

如需更多控制,请将 PEFT 配置直接传递给 trainer。这是大多数使用场景下的推荐方法:

from peft import LoraConfig
from trl import SFTConfig, SFTTrainer

peft_config = LoraConfig(
    r=32,
    lora_alpha=16,
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
    target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],
)

trainer = SFTTrainer(
    model=model,
    args=training_args,
    train_dataset=dataset,
    peft_config=peft_config,  # Pass config here
)

优点:完全可控,支持所有 PEFT 方法(LoRA、Prompt Tuning 等)

缺点:需要 Python 代码

3. 将 PEFT 直接应用于模型(高级)

为了获得最大的灵活性,您可以在将模型传递给训练器之前,先对模型应用 PEFT:

from peft import LoraConfig, get_peft_model
from transformers import AutoModelForCausalLM
from trl import SFTConfig, SFTTrainer

# Load base model
model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2-0.5B")

# Apply PEFT configuration
peft_config = LoraConfig(
    r=32,
    lora_alpha=16,
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
)
model = get_peft_model(model, peft_config)

# Pass PEFT-wrapped model to trainer
trainer = SFTTrainer(
    model=model,  # Already has PEFT applied
    args=training_args,
    train_dataset=dataset,
    # Note: no peft_config needed here
)

优点:控制力最强,适用于自定义模型架构或复杂配置

缺点:代码更冗长,需要理解 PEFT 的内部机制

学习率考量

在使用 LoRA 或其他 PEFT 方法时,与全量微调相比,你通常需要使用更高的学习率(大约 10 倍)。这是因为 PEFT 方法仅训练一小部分参数,需要更大的学习率才能实现类似的参数更新。

推荐的学习率:

Trainer全量微调使用 LoRA(10 倍)
SFT2.0e-52.0e-4
DPO5.0e-75.0e-6
GRPO1.0e-61.0e-5
提示词调整N/A1.0e-2 到 3.0e-2

为什么是 10 倍? LoRA 适配器的可训练参数远少于完整模型。更高的学习率可以弥补这种参数数量的减少,从而确保有效的训练。有关详细说明,请参阅这篇博客文章。

有关有效使用 LoRA 的更多最佳实践,请参阅 LoRA Without Regret 文档。

使用不同训练器的 PEFT

TRL 的训练器支持各种训练范式的 PEFT 配置。以下是每个主要训练器的详细示例。

sft
dpo
grpo

监督微调(SFT)

SFTTrainer 用于在指令数据集上进行监督微调。

使用 LoRA

python trl/scripts/sft.py \
    --model_name_or_path Qwen/Qwen2-0.5B \
    --dataset_name trl-lib/Capybara \
    --learning_rate 2.0e-4 \
    --num_train_epochs 1 \
    --per_device_train_batch_size 2 \
    --gradient_accumulation_steps 8 \
    --use_peft \
    --lora_r 32 \
    --lora_alpha 16 \
    --output_dir Qwen2-0.5B-SFT-LoRA

Python 示例

from peft import LoraConfig
from trl import SFTConfig, SFTTrainer

# Configure LoRA
peft_config = LoraConfig(
    r=32,
    lora_alpha=16,
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
    target_modules=["q_proj", "v_proj"],  # optional: specify target modules
)

# Configure training with higher learning rate for LoRA
training_args = SFTConfig(
    learning_rate=2.0e-4,  # 10x the base rate for LoRA
    ...
)

# Create trainer with PEFT config
trainer = SFTTrainer(
    model="Qwen/Qwen2-0.5B",  # can pass model name or loaded model
    args=training_args,
    train_dataset=dataset,
    peft_config=peft_config,  # pass PEFT config here
)
trainer.train()

QLoRA:量化低秩适应

QLoRA 将 4 位量化与 LoRA 相结合,使得在消费级硬件上微调超大模型成为可能。与标准 LoRA 相比,该技术可将内存需求降低多达 4 倍。

QLoRA 的工作原理

  1. 4 位量化:使用 bitsandbytes 以 4 位精度加载基础模型
  2. 冻结权重:量化模型的权重在训练过程中保持冻结
  3. LoRA 适配器:仅以更高精度训练 LoRA 适配器参数
  4. 内存效率:支持在单个消费级 GPU 上微调 Llama-70B 等模型

使用 QLoRA 与 TRL

只需将 load_in_4bit=True 与 PEFT 配置结合使用即可:

命令行

python trl/scripts/sft.py \
    --model_name_or_path meta-llama/Llama-2-7b-hf \
    --dataset_name trl-lib/Capybara \
    --load_in_4bit \
    --use_peft \
    --lora_r 32 \
    --lora_alpha 16 \
    --per_device_train_batch_size 1 \
    --gradient_accumulation_steps 16 \
    --output_dir Llama-2-7b-QLoRA

Python 示例

将 quantization_config 与 peft_config 一起直接传递给 trainer——trainer 会为您加载并量化模型。SFTTrainer、DPOTrainer、GRPOTrainer 和 RLOOTrainer 也提供相同的 quantization_config 参数。

import torch

from peft import LoraConfig
from transformers import BitsAndBytesConfig
from trl import SFTConfig, SFTTrainer

# Configure 4-bit quantization
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16,
    bnb_4bit_use_double_quant=True,
)

# Configure LoRA
peft_config = LoraConfig(
    r=32,
    lora_alpha=16,
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
)

# Configure training with higher learning rate for LoRA
training_args = SFTConfig(
    learning_rate=2.0e-4,  # 10x the base rate for QLoRA
    ...
)

# Create trainer with quantization and PEFT config
trainer = SFTTrainer(
    model="meta-llama/Llama-2-7b-hf",
    args=training_args,
    train_dataset=dataset,
    quantization_config=bnb_config,
    peft_config=peft_config,
)

trainer.train()

QLoRA 配置选项

BitsAndBytesConfig 提供了多个选项以优化内存和性能:

import torch

from transformers import BitsAndBytesConfig

bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",  # or "fp4"
    bnb_4bit_compute_dtype=torch.bfloat16,  # Compute dtype for 4-bit base models
    bnb_4bit_use_double_quant=True,  # Nested quantization for additional memory savings
)

配置参数:

  • bnb_4bit_quant_type:量化数据类型("nf4" 或 "fp4")。建议使用 NF4。
  • bnb_4bit_compute_dtype:用于计算的 dtype。使用 bfloat16 以获得更好的训练稳定性。
  • bnb_4bit_use_double_quant:启用嵌套量化,以额外节省每个参数约 0.4 位。

8 位量化

若需以牺牲部分内存节省为代价换取略高的精度,您可以使用 8 位量化:

from transformers import BitsAndBytesConfig, AutoModelForCausalLM

bnb_config = BitsAndBytesConfig(load_in_8bit=True)

model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-2-7b-hf",
    quantization_config=bnb_config,
    device_map="auto",
)

或通过命令行:

python trl/scripts/sft.py \
    --model_name_or_path meta-llama/Llama-2-7b-hf \
    --load_in_8bit \
    --use_peft \
    --lora_r 32 \
    --lora_alpha 16

预量化检查点

部分检查点以量化形式发布,例如 gpt-oss 采用 MXFP4,或 Mistral Medium 3.5 采用 FP8。这些权重无法就地训练,因此当通过名称传入此类检查点时,训练器会以反量化形式加载它,无论是否提供 peft_config。随后,模型将占用其反量化权重所需的内存,例如 gpt-oss-20b 在 bfloat16 下约为 42 GB,而其 MXFP4 检查点仅为 13 GB。要在 bfloat16 下加载它,与其他模型一样:

from trl import SFTConfig

training_args = SFTConfig(model_init_kwargs={"dtype": "bfloat16"})

FP8 检查点需要 transformers 5.0.0 或更高版本。

提示词调整

Prompt tuning 是另一种 PEFT 技术,它学习附加在输入前面的软提示(连续嵌入),同时保持整个模型冻结。这对于大型模型尤其有效。

Prompt Tuning 的工作原理

  1. 虚拟令牌:向输入添加可学习的连续嵌入(虚拟令牌)
  2. 冻结模型:整个基础模型保持冻结
  3. 特定任务提示:每个任务学习自己的提示嵌入
  4. 极致高效:仅训练提示嵌入(通常为 8-20 个 token)

使用 TRL 进行 Prompt Tuning

from peft import PromptTuningConfig, PromptTuningInit, TaskType
from trl import SFTConfig, SFTTrainer

# Configure Prompt Tuning
peft_config = PromptTuningConfig(
    task_type=TaskType.CAUSAL_LM,
    prompt_tuning_init=PromptTuningInit.TEXT,
    num_virtual_tokens=8,
    prompt_tuning_init_text="Classify if the tweet is a complaint or not:",
    tokenizer_name_or_path="Qwen/Qwen2-0.5B",
)

# Configure training with higher learning rate for Prompt Tuning
training_args = SFTConfig(
    learning_rate=2.0e-2,  # Prompt Tuning typically uses 1e-2 to 3e-2
    ...
)

# Create trainer with PEFT config
trainer = SFTTrainer(
    model=model,
    args=training_args,
    train_dataset=dataset,
    peft_config=peft_config,  # pass PEFT config here
)

trainer.train()

Prompt Tuning 配置

from peft import PromptTuningConfig, PromptTuningInit, TaskType

peft_config = PromptTuningConfig(
    task_type=TaskType.CAUSAL_LM,  # Task type
    prompt_tuning_init=PromptTuningInit.TEXT,  # Initialize from text
    num_virtual_tokens=8,  # Number of virtual tokens
    prompt_tuning_init_text="Your initialization text here",
    tokenizer_name_or_path="model_name",
)

配置参数:

  • task_type:任务类型(语言建模为 TaskType.CAUSAL_LM)
  • prompt_tuning_init:初始化方法(TEXT、RANDOM)
  • num_virtual_tokens:要前置的虚拟 token 数量(通常为 8-20)
  • prompt_tuning_init_text:用于初始化虚拟令牌的文本(当使用 TEXT 初始化时)
  • tokenizer_name_or_path:用于从文本初始化的分词器

Prompt Tuning 与 LoRA

功能提示词调整LoRA
已训练参数~0.001%~0.1-1%
内存使用情况最小低
训练速度最快快速
模型修改无Adapter 层
适用场景大型模型,多种任务通用微调
学习率更高(1e-2 到 3e-2)标准(1e-4 到 3e-4)

高级 PEFT 配置

LoRA 配置参数

from peft import LoraConfig

peft_config = LoraConfig(
    r=16,  # LoRA rank
    lora_alpha=32,  # LoRA scaling factor
    lora_dropout=0.05,  # Dropout probability
    bias="none",  # Bias training strategy
    task_type="CAUSAL_LM",  # Task type
    target_modules=["q_proj", "v_proj"],  # Modules to apply LoRA
    modules_to_save=None,  # Additional modules to train
)

关键参数:

  • r:LoRA 秩(典型值:8、16、32、64)。秩越高,参数越多,但性能可能更好。
  • lora_alpha:缩放因子(通常为秩的 2 倍)。控制 LoRA 更新的幅度。
  • lora_dropout:LoRA 层的 Dropout 概率(典型值:0.05-0.1)。
  • target_modules: 要应用 LoRA 的模块。常见选择:
    • ["q_proj", "v_proj"]:注意力查询和值(内存高效)
    • ["q_proj", "k_proj", "v_proj", "o_proj"]:所有注意力投影
    • ["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"]:所有线性层
  • modules_to_save:需要完全训练的其他模块(例如 ["embed_tokens", "lm_head"])

目标模块选择

您可以指定要将 LoRA 应用于哪些模块。常见模式:

# Minimal (most memory efficient)
target_modules=["q_proj", "v_proj"]

# Attention only
target_modules=["q_proj", "k_proj", "v_proj", "o_proj"]

# All linear layers (best performance, more memory)
target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"]

使用命令行参数

TRL 脚本通过命令行接受 PEFT 参数:

python trl/scripts/sft.py \
    --model_name_or_path Qwen/Qwen2-0.5B \
    --dataset_name trl-lib/Capybara \
    --use_peft \
    --lora_r 32 \
    --lora_alpha 16 \
    --lora_dropout 0.05 \
    --lora_target_modules q_proj v_proj \
    --output_dir output

可用标志:

  • --use_peft:启用 PEFT
  • --lora_r:LoRA 秩(默认值:16)
  • --lora_alpha:LoRA alpha(默认值:32)
  • --lora_dropout:LoRA dropout(默认值:0.05)
  • --lora_target_modules:目标模块(以空格分隔)
  • --lora_modules_to_save:需要额外训练的模块
  • --use_rslora:启用秩稳定 LoRA
  • --use_dora:启用 Weight-Decomposed LoRA (DoRA)
  • --load_in_4bit:启用 4 位量化(QLoRA)
  • --load_in_8bit:启用 8 位量化

保存和加载 PEFT 模型

保存

训练完成后,保存您的 PEFT 适配器:

# Save the adapters
trainer.save_model("path/to/adapters")

# Or manually
model.save_pretrained("path/to/adapters")

这仅保存适配器权重(约几 MB),而非完整模型(约几 GB)。

加载

加载 PEFT 模型以进行推理:

from transformers import AutoModelForCausalLM
from peft import PeftModel

# Load base model
base_model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2-0.5B")

# Load PEFT adapters
model = PeftModel.from_pretrained(base_model, "path/to/adapters")

# Optionally merge adapters into base model for faster inference
model = model.merge_and_unload()

推送到 Hub

您可以轻松地在 Hugging Face Hub 上共享您的 PEFT 适配器:

# Push adapters to Hub
model.push_to_hub("username/model-name-lora")

# Load from Hub
from peft import PeftModel
model = PeftModel.from_pretrained(base_model, "username/model-name-lora")

多 GPU 训练

PEFT 与 TRL 的多 GPU 支持无缝配合:

torchrun --nproc_per_node 8 trl/scripts/sft.py \
    --model_name_or_path Qwen/Qwen2-0.5B \
    --dataset_name trl-lib/Capybara \
    --use_peft \
    --lora_r 32 \
    --lora_alpha 16

对于使用多 GPU 的 QLoRA,基础模型会自动进行分片:

torchrun --nproc_per_node 8 trl/scripts/sft.py \
    --model_name_or_path meta-llama/Llama-2-70b-hf \
    --load_in_4bit \
    --use_peft \
    --lora_r 32

用于大模型的朴素流水线并行(NPP)

对于非常大的模型(>60B 参数),TRL 支持 Naive Pipeline Parallelism (NPP),可将模型和适配器分布在多个 GPU 上。激活值和梯度会在 GPU 之间进行通信,支持 int8 及其他数据类型。

NPP

如何使用 NPP

使用自定义的 device_map 加载模型,将其拆分到多个设备上:

from transformers import AutoModelForCausalLM
from peft import LoraConfig

# Create custom device map (see accelerate documentation)
device_map = {
    "model.embed_tokens": 0,
    "model.layers.0": 0,
    # ... distribute layers across GPUs
    "lm_head": 0,  # Must be on GPU 0
}

model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-2-70b-hf",
    device_map=device_map,
    peft_config=lora_config,
)
  • 将 lm_head 模块保留在第一块 GPU(设备 0)上,以避免错误
  • 请参阅此设备映射教程以进行正确配置
  • 直接运行训练脚本(不使用 torchrun):python script.py
  • NPP 尚不支持数据并行

资源

TRL 示例和笔记本

文档

研究论文

Update on GitHub