[特殊字符] PEFT 完全指南:用 Parameter-Efficient Fine-Tuning 以极低成本微调大模型
2026/9/20 13:40:03 网站建设 项目流程

🤗 PEFT 完全指南:用 Parameter-Efficient Fine-Tuning 以极低成本微调大模型

【免费下载链接】peft🤗 PEFT: State-of-the-art Parameter-Efficient Fine-Tuning.项目地址: https://gitcode.com/gh_mirrors/pe/peft

本文以仓库根目录的 README.md 为核心骨架,结合src/peft下的源码实现与examples/中的实战示例,系统讲解 🤗 PEFT 的核心原理、快速上手、内存收益、生态集成与模型支持。读者学完后将掌握:如何用 LoRA 等 PEFT 方法在消费级硬件上微调大模型、如何保存与加载适配器、如何与 Transformers / Diffusers / Accelerate / TRL 协同工作,以及如何为自定义模型手动配置 PEFT 支持。

为什么需要 PEFT:全量微调的成本困境

大型预训练模型(如 Qwen2.5-3B、Llama-2-7b、bigscience/mt0-xxl)动辄数亿到数百亿参数。全量微调(Full Fine-tuning)需要为每一层保存并更新梯度,计算与存储开销随模型规模急剧膨胀:单个 checkpoint 可达数 GB 甚至数十 GB,显存需求常常超出消费级硬件的承受范围。

Parameter-Efficient Fine-Tuning(PEFT,参数高效微调)方法正是针对这一困境提出的解决方案:只微调一小部分(额外)模型参数,而不是全部参数,从而显著降低计算与存储成本。近年来最前沿的 PEFT 技术在效果上已能达到与全量微调相当的水平。

PEFT 在生态中的定位非常清晰:它与 Transformers 深度集成以简化训练与推理,与 Diffusers 集成以便捷管理不同的适配器,与 Accelerate 集成以支持超大规模模型的分布式训练与推理。仓库根目录 README.md 开篇即点明了这一"微调任意规模模型的通用工具层"的定位。

从源码结构看(src/peft/init.py),PEFT 的核心导出 API 包括:

  • 配置体系PeftConfigPromptLearningConfig以及各类方法的配置类(如LoraConfigIA3Config);
  • 模型包装PeftModel及其任务专用子类(PeftModelForCausalLM等)、AutoPeftModel系列自动加载类;
  • 方法注册表PEFT_TYPE_TO_CONFIG_MAPPINGPEFT_TYPE_TO_TUNER_MAPPINGPEFT_TYPE_TO_MIXED_MODEL_MAPPING,由register_peft_method函数在 src/peft/utils/peft_types.py 中统一注册。

这种"注册表 + 配置类 + 模型类"的架构,使得新增一种 PEFT 方法只需注册即可被get_peft_modelPeftModel.from_pretrained等统一入口识别。

快速上手:三行代码把大模型变成 PEFT 模型

安装

PEFT 是一个纯 pip 包,安装非常轻量:

pip install peft

仓库内还提供了 Docker 镜像构建文件,方便在隔离环境中使用:docker/peft-cpu/Dockerfile(CPU 版)与 docker/peft-gpu/Dockerfile(GPU 版)。

get_peft_model包装基础模型

以 LoRA 为例,准备一个模型用于训练的核心 API 是get_peft_model:把基础模型和 PEFT 配置传入,返回一个已注入适配器的 PEFT 模型。以 Qwen2.5-3B-Instruct 为例,只需要训练全量参数的 0.12%

import torch from transformers import AutoModelForCausalLM from peft import LoraConfig, TaskType, get_peft_model device = torch.accelerator.current_accelerator().type if hasattr(torch, "accelerator") else "cuda" model_id = "Qwen/Qwen2.5-3B-Instruct" model = AutoModelForCausalLM.from_pretrained(model_id, device_map=device) peft_config = LoraConfig( r=16, lora_alpha=32, task_type=TaskType.CAUSAL_LM, # target_modules=["q_proj", "v_proj", ...] # 可选:显式指定目标模块 ) model = get_peft_model(model, peft_config) model.print_trainable_parameters() # 输出: trainable params: 3,686,400 || all params: 3,089,625,088 || trainable%: 0.1193 # 用 transformers Trainer 在你的数据集上训练,然后保存模型 model.save_pretrained("qwen2.5-3b-lora")

从 src/peft/mapping_func.py 的实现可以看到,get_peft_model做了几件关键的事:

  1. 回填基础模型信息:把peft_config.base_model_name_or_path更新为实际加载模型的name_or_path,确保保存的适配器 checkpoint 携带正确的基座模型标识;
  2. 重复注入检测:若模型中已存在BaseTunerLayer实例,会警告用户需先调用.unload()再使用不同配置重新包装;
  3. 路由分发:根据task_typeMODEL_TYPE_TO_PEFT_MODEL_MAPPING中选择对应的任务专用PeftModel子类(如PeftModelForCausalLM);若task_type未知且不是 prompt learning,则退化为通用PeftModelmixed=True时则返回PeftMixedModel,支持在一个模型上混合多种兼容的适配器类型。

PeftModel.from_pretrained加载适配器做推理

训练完成后,加载 PEFT 模型做推理同样简单:

import torch from transformers import AutoModelForCausalLM, AutoTokenizer from peft import PeftModel device = torch.accelerator.current_accelerator().type if hasattr(torch, "accelerator") else "cuda" model_id = "Qwen/Qwen2.5-3B-Instruct" tokenizer = AutoTokenizer.from_pretrained(model_id) model = AutoModelForCausalLM.from_pretrained(model_id, device_map=device) model = PeftModel.from_pretrained(model, "qwen2.5-3b-lora") inputs = tokenizer("Preheat the oven to 350 degrees and place the cookie dough", return_tensors="pt") outputs = model.generate(**inputs.to(device), max_new_tokens=50) print(tokenizer.decode(outputs[0], skip_special_tokens=True)) # 输出类似: Preheat the oven to 350 degrees and place the cookie dough in a baking dish [...]

注意这里只加载了"适配器 + 配置",基座模型仍需单独加载,这正是 PEFT 存储开销极小的原因所在。

从 src/peft/peft_model.py 的签名可以看到,PeftModel.from_pretrainedmodel_id支持两种形态:Hugging Face Hub 上的模型仓库 ID,或本地目录(由save_pretrained生成的包含adapter_config.json与适配器权重的目录)。其余参数还包括:adapter_name(加载多适配器时命名)、is_trainable(默认False,即冻结适配器仅做推理)、config(跳过自动加载、直接传入已构造的配置对象)、autocast_adapter_dtype(默认True,把 float16/bfloat16 的适配器权重转为 float32 以稳定训练)、low_cpu_mem_usage(在 meta device 上创建空适配器权重以加速加载,但训练前会被真实权重替换,因此官方建议训练场景保持False)。

快速上手的完整示例

除了 README 的代码片段,仓库还提供了大量可复跑的完整脚本,例如:

  • examples/causal_language_modeling/peft_lora_clm_accelerate_ds_zero3_offload.py:LoRA + DeepSpeed ZeRO-3 + CPU offload 的因果语言建模训练;
  • examples/sequence_classification/peft_no_lora_accelerate.py:LoRA 序列分类的 baseline 对比脚本;
  • examples/conditional_generation/peft_lora_seq2seq_accelerate_ds_zero3_offload.py 与 examples/conditional_generation/peft_lora_seq2seq_accelerate_fsdp.py:LoRA 在 seq2seq 任务上的 ZeRO-3 / FSDP 分布式训练脚本。

LoRA 配置参数深度解读

README 中仅展示了rlora_alphatask_type三个参数,但 src/peft/tuners/lora/config.py 中LoraConfig还提供了大量关键配置项,理解它们对训练效果至关重要:

参数类型说明
rintLoRA 注意力维度,即秩(rank),核心超参数之一
target_moduleslist[str] \| str指定要注入适配器的模块名。传字符串时做正则匹配;传列表时做精确匹配或以任一字符串结尾匹配;传"all-linear"则选择全部 Linear/Conv1D 层(PreTrainedModel 会排除输出层);不传则按已知模型架构自动选择,架构未知会报错,需手动指定;传[]表示不注入任何模块(配合target_parameters使用)
exclude_moduleslist[str] \| str显式排除的模块名,匹配规则同target_modules
lora_alphaintLoRA 缩放参数(scaling factor 的分母是r,或use_rslora=True时的sqrt(r)
lora_dropoutfloatLoRA 层的 dropout 概率
fan_in_fan_outbool目标层权重以(fan_in, fan_out)存储时设为True,例如 GPT-2 的Conv1D
biasstr'none''all''lora_only',控制哪些 bias 参与训练
use_rslorabool启用 Rank-Stabilized LoRA,缩放因子改为lora_alpha/sqrt(r),实验证明效果更好
modules_to_savelist[str]除适配器层外需要设为可训练并保存进 checkpoint 的模块
init_lora_weightsbool \| str适配器权重初始化方式,见下文详解
layers_to_transformlist[int] \| int只对指定层索引注入适配器
layers_patternstr配合layers_to_transform,指定nn.ModuleList的层名(常为'layers''h'
rank_pattern/alpha_patterndict按层名或正则指定与默认不同的 rank / alpha
megatron_config/megatron_coredict/str在 Megatron 的ColumnParallelLinear/RowParallelLinear上应用 LoRA 所需的配置
use_dorabool启用 DoRA(权重分解低秩适配),把权重更新分解为幅度与方向两部分,低秩下效果更好;目前仅支持 Linear 与 Conv2D,且推理时建议 merge 权重以减小开销
velora_configVeloraConfig启用 VeLoRA,为 LoRA A 投影替换自定义反向传播,以压缩激活值替代完整输入激活值
kasa_configKasaConfig启用 KaSA(知识感知奇异值适配),对冻结基座权重做一次性 SVD,截断r个最小奇异分量,在 LoRA A/B 之间插入可学习的对角奇异值;目前仅支持 Linear 层
alora_invocation_tokenslist[int]启用 Activated LoRA(aLoRA),按 token 激活不同的 LoRA 路径

init_lora_weights的多种初始化策略(这是 README 未展开、但源码中信息量极大的部分):

  • True(默认):微软参考实现的默认初始化,LoRA B 权重置零,训练前适配器是无操作(no-op);
  • False:A、B 均随机初始化,训练前即非 no-op,仅用于调试;
  • 'gaussian':按秩缩放的高斯初始化;
  • 'loftq':LoftQ 初始化,同时量化骨干权重并初始化 LoRA 层(需配合loftq_config);
  • 'eva':基于层输入激活的 SVD 的数据驱动初始化(Explained Variance Adaptation,需配合eva_config,至少传入训练数据集);
  • 'olora':OLoRA 初始化;
  • 'pissa':PiSSA(主奇异值与奇异向量适配)初始化,收敛更快、效果更好,且相比 QLoRA 能降低量化误差;'pissa_niter_[次数]'为基于 FSVD 的快速版本,niter=16时可在数秒内完成 7B 模型的初始化且效果与 SVD 相当;
  • 'corda':CorDA(面向上下文的分解适配),在指令预览模式下收敛比 PiSSA 更快(需配合corda_config);
  • 'orthogonal':A、B 正交初始化(要求r为偶数,目前仅支持 Linear 层),类似 OLoRA 但不改动基座权重;
  • 'mica':MiCA(小分量适配),用基座权重最小奇异值对应的左奇异向量初始化 B,A 置零,训练时冻结 B、只更新 A;目前支持 Linear 与 Embedding 层。

仓库中对应每种初始化方法都有独立实现与示例,例如 examples/pissa_finetuning/pissa_finetuning.py、examples/corda_finetuning/corda_finetuning.py、examples/loftq_finetuning/quantize_save_load.py。

为什么你应该使用 PEFT

PEFT 带来的好处众多,其中最核心的是计算与存储的巨额节省,这使它适用于大量实际场景。

在消费级硬件上达到高性能

以 A100 80GB GPU(>64GB CPU 内存)训练 ought/raft/twitter_complaints 数据集为例,README 给出了三组模型的全量微调 vs PEFT-LoRA 显存/内存对比:

模型全量微调PEFT-LoRA PyTorchPEFT-LoRA DeepSpeed + CPU Offload
bigscience/T0_3B(3B 参数)47.14GB GPU / 2.96GB CPU14.4GB GPU / 2.96GB CPU9.8GB GPU / 17.8GB CPU
bigscience/mt0-xxl(12B 参数)OOM GPU56GB GPU / 3GB CPU22GB GPU / 52GB CPU
bigscience/bloomz-7b1(7B 参数)OOM GPU32GB GPU / 3.8GB CPU18.1GB GPU / 35GB CPU

结论很直观:用 LoRA,可以在 80GB 显存上完整微调一个原本会直接 OOM 的 12B 模型,也可以轻松容纳并训练 3B 模型,而且 3B 模型的性能与全量微调相当,GPU 显存消耗却只是零头:

提交名称准确率
Human baseline(众包)0.897
Flan-T50.892
lora-t0-3b0.863

README 还特别提示:上表中 bigscience/T0_3B 的表现尚未调优,通过调整输入指令模板、LoRA 超参与其他训练超参还能进一步榨取性能。最终该模型的 checkpoint 只有19MB,而全量 bigscience/T0_3B 模型约 11GB。

这类"以极少可训练参数逼近全量微调效果"的现象,根源在于适配器只引入了低秩增量。仓库的 method_comparison/ 目录提供了对数十种 PEFT 方法在 MetaMathQA 与图像生成(flux2-klein)两个基准上的系统对比脚本与结果,读者可以查看各方法在相同实验条件下的可训练参数占比与效果差异。

量化:进一步压缩显存

量化是另一种通过更低精度表示数据来降低模型内存需求的方法,可以与 PEFT 方法组合,让 LLM 的训练与推理加载更加轻松。README 给出的两个学习路径:

  • 在 16GB GPU 上用 QLoRA + TRL 微调 meta-llama/Llama-2-7b-hf;
  • 用 LoRA + 8-bit 量化微调 openai/whisper-large-v2 做多语言语音识别。

仓库对此有直接配套代码:examples/int8_training/peft_bnb_whisper_large_v2_training.ipynb、examples/int8_training/peft_adalora_whisper_large_training.py、examples/int8_training/Fine-tune-opt-bnb-peft.ipynb、examples/int8_training/fine_tune_blip2_int8.py;examples/fp4_finetuning/finetune_fp4_opt_bnb_peft.py 则展示了 FP4 精度下的 QLoRA 训练。

节省计算与存储

PEFT 通过避免在每个下游任务或数据集上都全量微调来节省存储:大多数情况下你只微调模型参数中极小的一部分,每个 checkpoint 只有几 MB(而不是几 GB)。这些小巧的 PEFT 适配器在性能上与全量微调模型相当。如果你有多个数据集,PEFT 模型还能帮你大幅节省存储,同时不必担心灾难性遗忘(catastrophic forgetting)或对骨干/基座模型的过拟合——因为基座模型始终是冻结的。

这一特性在仓库中同样有具体印证:以 Stable Diffusion 的 LoRA 微调为例,examples/lora_dreambooth/train_dreambooth.py 生成的最终 checkpoint 仅有8.8MB;examples/boft_dreambooth 与 examples/hra_dreambooth 则是 BOFT、HRA 方法的 Dreambooth 对照实现。

PEFT 生态集成

PEFT 之所以在 Hugging Face 生态中被广泛采用,正是因为它为训练与推理带来了巨大的效率提升。README 列出了四个核心集成方向。

Diffusers:低显存训练 Stable Diffusion

迭代式扩散过程非常消耗显存,PEFT 可以降低内存需求并缩小最终 checkpoint 的存储体积。在 A100 80GB GPU(>64GB CPU 内存)上以 LoRA 训练 Stable Diffusion 的对比:

模型全量微调PEFT-LoRAPEFT-LoRA + 梯度检查点
CompVis/stable-diffusion-v1-427.5GB GPU / 3.97GB CPU15.5GB GPU / 3.84GB CPU8.12GB GPU / 3.77GB CPU

配合梯度检查点(Gradient Checkpointing),训练显存可从 27.5GB 一路降到 8.12GB,最终 checkpoint 仅 8.8MB。想亲手尝试,可以直接运行 examples/lora_dreambooth/train_dreambooth.py 训练脚本;仓库还提供了 examples/stable_diffusion/convert_sd_adapter_to_peft.py 用于把已有的 SD 适配器转换为 PEFT 格式。

Transformers:add_adapter/load_adapter/set_adapter

PEFT 已直接集成进 Transformers。加载模型后调用add_adapter即可添加新的 PEFT 适配器:

from peft import LoraConfig model = ... # transformers 模型 peft_config = LoraConfig(...) model.add_adapter(peft_config, adapter_name="lora_1")

加载已训练好的适配器用load_adapter

model = ... # transformers 模型 model.load_adapter(<adapter-路径>, adapter_name="lora_1")

在不同适配器之间切换用set_adapter

model.set_adapter("lora_2")

README 明确指出:Transformers 内置集成并不包含 PEFT 提供的全部功能,例如把适配器合并回基座模型的方法(merge_adapter/unmerge_adapter)就只存在于 PEFT 库本身。仓库中的 examples/multi_adapter_examples/ 目录展示了多适配器的合并与加权推理实践。

Accelerate:分布式训练与推理开箱即用

Accelerate 是一个面向多种训练配置与硬件(GPU、TPU、Apple Silicon 等)的分布式训练与推理库。PEFT 模型与 Accelerate 开箱即用,这让在消费级硬件上训练超大模型或进行推理变得非常便捷。仓库的 examples/causal_language_modeling/ 与 examples/conditional_generation/ 中提供了配好 ZeRO-3 CPU offload(accelerate_ds_zero3_cpu_offload_config.yaml)与 FSDP 的完整训练脚本,README 中那张"PEFT-LoRA DeepSpeed with CPU Offloading"的显存数据即来源于此类配置。

TRL:RLHF 训练

PEFT 同样可以用于 LLM 的 RLHF(人类反馈强化学习)训练,覆盖 ranker 与 policy 等组件。README 给出的三个学习路径分别涉及:

  • DPO(Direct Preference Optimization):用 PEFT + TRL 对 Mistral-7b 做 DPO 偏好优化;
  • RLHF on 消费级 GPU:在 24GB 消费级 GPU 上用 PEFT + TRL 微调 20B LLM;
  • StackLLaMA 全流程:用 PEFT + TRL 完成监督微调、奖励建模与 RL 微调的完整管线。

模型支持与自定义配置

官方支持矩阵

想确认某个模型对某 PEFT 方法是否开箱即用,README 建议使用对应的 Space 或查阅官方文档;即使模型未在列表中,也可以手动配置模型 config 来为模型启用 PEFT

从源码看,模型-方法支持关系由两层映射驱动:

  1. 任务类型映射(src/peft/utils/peft_types.py):TaskType定义了SEQ_CLS(文本分类)、SEQ_2_SEQ_LM(序列到序列语言建模)、CAUSAL_LM(因果语言建模)、TOKEN_CLS(token 分类)、QUESTION_ANS(问答)、FEATURE_EXTRACTION(特征提取)六种任务;
  2. 方法注册表(src/peft/mapping.py):PEFT_TYPE_TO_CONFIG_MAPPINGPEFT_TYPE_TO_TUNER_MAPPING等字典保存了PeftType到配置类 / 模型类的映射,由register_peft_method填充。

仓库当前(__version__ = "0.21.1.dev0",见 src/peft/init.py)注册的方法非常丰富,从 src/peft/utils/peft_types.py 的枚举与 src/peft/init.py 的导出列表可以看出,除了 LoRA 及其变体(DoRA、PiSSA、OLoRA、LoftQ、EVA、CorDA、MiCA、LoRA-GA、aLoRA、rsLoRA、VeLoRA、KaSA、QDoRA 等),还包括:AdaLORA、IA3、BOFT、LoHa、LoKr、OFT、XLORA、FourierFT、HRA、BONE、MISS、RandLoRA、SHIRA、C3A、ROAD、Poly、LN_Tuning、VeRA、FROD、BEFT、CPT、DeFT、GLoRA、GraLoRA、Hira、Lily、OSF、Peanut、PSOFT、PVera、Shadow、Supertuning、TinyLoRA、TrainableTokens、UniLoRA、VBLoRA、WaveFT、MultiTaskPromptTuning、AdaptionPrompt、PromptTuning、PrefixTuning、P-Tuning、LoRA+、Riemannian LoRA 等数十种。

为自定义/新架构启用 PEFT

当某个模型不在官方支持列表中时,LoraConfig文档串(src/peft/tuners/lora/config.py)给出了明确的兜底方案:手动指定target_modules。未指定且架构未知时会直接抛错,此时应通过target_modules(注入哪些模块)、exclude_modules(排除哪些模块)显式声明,或传入'all-linear'自动选择全部 Linear/Conv1D 层。仓库文档 docs/source/developer_guides/custom_models.md 对自定义模型与新 Transformers 架构的适配做了系统讲解。

自动加载:AutoPeftModel 系列

除了PeftModel.from_pretrained,PEFT 还提供AutoPeftModel系列自动类(src/peft/auto.py):AutoPeftModelAutoPeftModelForCausalLMAutoPeftModelForSeq2SeqLMAutoPeftModelForSequenceClassificationAutoPeftModelForTokenClassificationAutoPeftModelForQuestionAnsweringAutoPeftModelForFeatureExtraction。它们会读取 checkpoint 中保存的auto_mapping信息,自动推断并加载正确的基座模型类与 PEFT 包装类,省去手动指定基座模型类名的步骤。

生态配套:方法对比与文档

仓库为深度使用 PEFT 的用户提供了两套配套资源:

  • 方法对比基准:method_comparison/ 下包含MetaMathQA(数学推理)与image-gen(flux2-klein 图像生成)两套实验框架,每个方法目录下都有对应的实验配置与结果 JSON(如method_comparison/MetaMathQA/results/lora--llama-3.2-3B-rank32.json),可用于横向对比不同 PEFT 方法在同一任务、同一基座模型下的表现;
  • 完整文档站:docs/source/index.md 及其 docs/source/_toctree.yml 组织了从 Quicktour、方法概览(docs/source/methods/overview.md)、包参考(docs/source/package_reference/peft_model.md、docs/source/package_reference/lora.md 等)到开发者指南(checkpoint、自定义模型、低层 API、混合模型、模型合并、量化等,见 docs/source/developer_guides/)的完整知识体系。

贡献与引用

PEFT 是开源项目,欢迎通过 CONTRIBUTING.md 与 docs/source/developer_guides/contributing.md 了解贡献流程;scripts/目录下还提供了check_doc_coverage.pytriage_prs.py等维护工具。如果你的论文或工作使用了 PEFT,请按如下 BibTeX 引用:

@Misc{peft, title = {{PEFT}: State-of-the-art Parameter-Efficient Fine-Tuning methods}, author = {Sourab Mangrulkar and Sylvain Gugger and Lysandre Debut and Younes Belkada and Sayak Paul and Benjamin Bossan and Marian Tietz}, howpublished = {\url{https://github.com/huggingface/peft}}, year = {2022} }

小结

围绕 README 的完整脉络,本文系统梳理了 PEFT 的五大核心要点:核心思想(只微调少量额外参数)、快速上手get_peft_model包装训练 +PeftModel.from_pretrained加载推理)、收益量化(消费级硬件训练 12B 模型、19MB checkpoint、配合量化更进一步)、生态集成(Transformers / Diffusers / Accelerate / TRL 四个方向的具体 API 与示例脚本),以及模型支持与自定义配置(注册表架构、TaskType六类任务、target_modules兜底方案)。结合src/peft的源码实现与examples/method_comparison/的配套代码,你可以以此为起点,在自己的数据集与模型上快速落地 LoRA 乃至数十种 PEFT 方法。

【免费下载链接】peft🤗 PEFT: State-of-the-art Parameter-Efficient Fine-Tuning.项目地址: https://gitcode.com/gh_mirrors/pe/peft

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询