PEFT 参数高效微调 — HuggingFace 官方出品的 LoRA/Adapter 工具库
一句话说明
PEFT(Parameter-Efficient Fine-Tuning,v0.14+)是 HuggingFace 出品的官方微调库,提供 LoRA、QLoRA、Adapter、Prompt Tuning、IA3 等多种参数高效方法,只需几行代码就能给任意 Transformer 模型加上微调能力。
安装与配置
# 安装 PEFT(通常随 transformers 一起用)
pip install peft # 安装最新版(v0.14+)
pip install peft transformers accelerate # 推荐:同时安装常用依赖
# 可选:量化支持(QLoRA 需要)
pip install bitsandbytes # 4bit/8bit 量化库
# 验证安装
python -c "import peft; print(peft.__version__)"
核心用法
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import LoraConfig, get_peft_model, TaskType # PEFT 核心类
# 第一步:加载基座模型
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-3.2-8B",
torch_dtype="auto", # 自动选择数据类型
device_map="auto" # 自动分配到 GPU
)
# 第二步:定义 LoRA 配置
lora_config = LoraConfig(
task_type=TaskType.CAUSAL_LM, # 任务类型:因果语言模型(生成类任务)
r=16, # LoRA 秩(低秩矩阵的维度)
lora_alpha=32, # 缩放系数(控制 LoRA 的影响强度)
lora_dropout=0.1, # Dropout 比例
target_modules=["q_proj", "v_proj"], # 对哪些层加 LoRA(默认 q 和 v 注意力层)
bias="none", # 是否训练 bias(none/all/lora_only)
)
# 第三步:把 LoRA 加到模型上
model = get_peft_model(model, lora_config)
# 查看可训练参数比例(通常只有 0.1%-1%)
model.print_trainable_parameters()
# 输出示例:trainable params: 4,194,304 || all params: 8,030,261,248 || trainable%: 0.0522
参数详解
from peft import LoraConfig, AdaLoraConfig, PromptTuningConfig
# 1. LoRA 完整参数
lora_config = LoraConfig(
r=16, # 秩,推荐范围:4-64
lora_alpha=32, # 缩放系数,通常是 r 的 2 倍
lora_dropout=0.05, # Dropout,防止过拟合
target_modules=["q_proj", "k_proj", # 目标模块列表(None=自动选)
"v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj"],
bias="none", # bias 处理方式
use_rslora=True, # 使用 RS-LoRA(更稳定的 rank-stabilized 版本)
modules_to_save=["lm_head"], # 这些层保存全量权重(不用 LoRA)
)
# 2. QLoRA(4bit 量化 + LoRA)
from transformers import BitsAndBytesConfig
import torch
bnb_config = BitsAndBytesConfig(
load_in_4bit=True, # 用 4bit 加载基座模型
bnb_4bit_quant_type="nf4", # 量化类型(nf4 效果最好)
bnb_4bit_compute_dtype=torch.bfloat16, # 计算时用 bf16(内存少但速度快)
bnb_4bit_use_double_quant=True, # 二次量化(进一步省内存)
)
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-3.2-8B",
quantization_config=bnb_config,
device_map="auto"
)
# 然后再用 get_peft_model() 加 LoRA
# 3. AdaLoRA(自适应 LoRA,自动分配秩给重要层)
adalora_config = AdaLoraConfig(
init_r=12, # 初始秩
target_r=8, # 最终目标秩
tinit=200, # 开始调整前的预热步数
tfinal=1000, # 调整结束步数
deltaT=10, # 调整间隔步数
lora_alpha=32,
)
实战案例
# 完整 QLoRA 微调流程
import torch
from transformers import (AutoModelForCausalLM, AutoTokenizer,
BitsAndBytesConfig, TrainingArguments, Trainer)
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
model_name = "meta-llama/Llama-3.2-8B-Instruct"
# 4bit 量化配置
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16,
)
# 加载量化模型
model = AutoModelForCausalLM.from_pretrained(
model_name, quantization_config=bnb_config, device_map="auto")
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token # Llama 没有 pad token,用 eos 代替
# 准备模型进行量化训练(必须调用这个函数!)
model = prepare_model_for_kbit_training(model)
# 加 LoRA
lora_config = LoraConfig(r=8, lora_alpha=16, target_modules="all-linear")
model = get_peft_model(model, lora_config)
# 保存和加载 LoRA 权重
model.save_pretrained("./my_lora_model") # 只保存 LoRA 权重(几十 MB)
# 加载 LoRA 并推理
from peft import PeftModel
base_model = AutoModelForCausalLM.from_pretrained(model_name, device_map="auto")
model = PeftModel.from_pretrained(base_model, "./my_lora_model")
model = model.merge_and_unload() # 合并 LoRA 到基座模型
常见报错与解决
| 报错信息 | 原因 | 解决方法 |
|---|
Expected all tensors to be on same device | 模型分布在不同设备 | 设置 device_map="auto" |
bitsandbytes not found | 未安装量化库 | pip install bitsandbytes |
target_modules not found | 模块名写错 | 用 model.named_modules() 查看层名 |
prepare_model_for_kbit_training 报错 | 旧版 PEFT | 升级 pip install --upgrade peft |
| LoRA 权重文件很大 | 意外保存了全量模型 | 确认用 get_peft_model() 包装后再保存 |
速查表
| 功能 | 代码 |
|---|
| 基础 LoRA | LoraConfig(r=16, lora_alpha=32) |
| 自适应 LoRA | AdaLoraConfig(init_r=12, target_r=8) |
| QLoRA 量化 | BitsAndBytesConfig(load_in_4bit=True) |
| 查看可训练参数 | model.print_trainable_parameters() |
| 保存 LoRA | model.save_pretrained("path") |
| 加载 LoRA | PeftModel.from_pretrained(base, "path") |
| 合并权重 | model.merge_and_unload() |
| 官方文档 | https://huggingface.co/docs/peft |