TRL documentation
PEFT 集成
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 倍) |
|---|---|---|
| SFT | 2.0e-5 | 2.0e-4 |
| DPO | 5.0e-7 | 5.0e-6 |
| GRPO | 1.0e-6 | 1.0e-5 |
| 提示词调整 | N/A | 1.0e-2 到 3.0e-2 |
为什么是 10 倍? LoRA 适配器的可训练参数远少于完整模型。更高的学习率可以弥补这种参数数量的减少,从而确保有效的训练。有关详细说明,请参阅这篇博客文章。
有关有效使用 LoRA 的更多最佳实践,请参阅 LoRA Without Regret 文档。
使用不同训练器的 PEFT
TRL 的训练器支持各种训练范式的 PEFT 配置。以下是每个主要训练器的详细示例。
监督微调(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-LoRAPython 示例
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()直接偏好优化(DPO)
DPOTrainer 实现了基于人类反馈的偏好学习。
使用 LoRA
python trl/scripts/dpo.py \
--model_name_or_path Qwen/Qwen2-0.5B-Instruct \
--dataset_name trl-lib/ultrafeedback_binarized \
--learning_rate 5.0e-6 \
--per_device_train_batch_size 2 \
--gradient_accumulation_steps 8 \
--use_peft \
--lora_r 32 \
--lora_alpha 16 \
--output_dir Qwen2-0.5B-DPO-LoRAPython 示例
from peft import LoraConfig
from trl import DPOConfig, DPOTrainer
# 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 = DPOConfig(
learning_rate=5.0e-6, # 10x the base rate for DPO with LoRA
...
)
# Create trainer with PEFT config
trainer = DPOTrainer(
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()注意:在使用 PEFT 与 DPO 时,无需提供单独的参考模型(ref_model)。训练器会自动将冻结的基础模型作为参考模型。
组相对策略优化(GRPO)
GRPOTrainer 使用基于组的奖励来优化策略。
使用 LoRA
python trl/scripts/grpo.py \
--model_name_or_path Qwen/Qwen2-0.5B \
--dataset_name trl-lib/math-reasoning \
--learning_rate 1.0e-5 \
--per_device_train_batch_size 2 \
--use_peft \
--lora_r 32 \
--lora_alpha 16 \
--output_dir Qwen2-0.5B-GRPO-LoRAPython 示例
from peft import LoraConfig
from trl import GRPOConfig, GRPOTrainer
# 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 = GRPOConfig(
learning_rate=1.0e-5, # 10x the base rate for GRPO with LoRA
...
)
# Create trainer with PEFT config
trainer = GRPOTrainer(
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 的工作原理
- 4 位量化:使用
bitsandbytes以 4 位精度加载基础模型 - 冻结权重:量化模型的权重在训练过程中保持冻结
- LoRA 适配器:仅以更高精度训练 LoRA 适配器参数
- 内存效率:支持在单个消费级 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-QLoRAPython 示例
将 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 的工作原理
- 虚拟令牌:向输入添加可学习的连续嵌入(虚拟令牌)
- 冻结模型:整个基础模型保持冻结
- 特定任务提示:每个任务学习自己的提示嵌入
- 极致高效:仅训练提示嵌入(通常为 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
使用自定义的 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 示例和笔记本
- 使用 LoRA/QLoRA 进行 SFT 的 Notebook - 展示 LoRA 和 QLoRA 两种实现的完整可运行示例
- TRL 示例目录 - 展示使用不同训练器进行 PEFT 的训练脚本集合
- TRL Cookbook 食谱 - 常见 PEFT 训练场景的分步指南
文档
研究论文
- LoRA 论文 - 原始 LoRA 方法论和结果
- QLoRA 论文 - 使用 4 位量化进行高效微调
- Prompt Tuning 论文 - 参数高效 Prompt Tuning 的规模之力