项目背景与定位
1.1 一句话定位
PEFT(Parameter-Efficient Fine-Tuning)是 HuggingFace 官方维护的、参数高效微调算法库。它把 LoRA、QLoRA、AdaLoRA、IA³、LoHa、LoKr、DoRA、Prefix Tuning、Prompt Tuning、P-Tuning v2 等 20+ 种"只更新少量参数即可达到全参微调效果"的方法,封装成统一的 PeftConfig + PeftModel API。
如果你用 LLaMA-Factory / Axolotl / TRL / NeMo 训过 LoRA,它们底层调的都是 PEFT。可以说 PEFT 是当下 LLM 微调生态里最底层、最广泛被使用的库之一。
1.2 为什么会有 PEFT
故事要从 2021 年说起。当时 GPT-3 等大模型出现,人们想做微调但碰到现实障碍:
- 175B 模型全参微调一次显存要 1 TB+,工业上根本玩不起;
- 每出一个新任务就要训一份新模型,部署和存储灾难;
- 但应用层往往只需要"在原模型上加一点行业知识 / 风格",不需要动整个模型。
各种"只动一小撮参数"的方案百花齐放,HuggingFace 团队 2022 年决定做一个统一封装,让用户只需要:
from peft import LoraConfig, get_peft_model
config = LoraConfig(r=8, target_modules=["q_proj", "v_proj"])
model = get_peft_model(model, config)
剩下的事 PEFT 自动搞定——找到指定模块、替换 Linear、训练时只更新 LoRA、保存时只保存 LoRA。
LoRA 的核心公式(也是大量 PEFT 算法的共同骨架):
$$y = W x + \tfrac{\alpha}{r}\, B A\, x,\qquad B\in\mathbb{R}^{d\times r},\;A\in\mathbb{R}^{r\times d},\;r\ll d$$
训练参数量从 $d^2$ 降到 $2dr$,当 $r=8,\,d=4096$ 时缩减比为 $2dr / d^2 = 16/d \approx 0.4\%$。
1.3 它在 HF 生态里的位置
| 层 | 库 | 作用 |
|---|---|---|
| 模型 | transformers | 提供 Llama/Qwen/Mistral 等模型实现 |
| 算法 | peft | 提供 LoRA/QLoRA/AdaLoRA/IA³ 等 |
| 训练 | TRL / Trainer | 训练循环(SFT/DPO/PPO) |
| 加速 | accelerate / deepspeed | 多卡 / ZeRO |
| 量化 | bitsandbytes | 4bit/8bit 加载 |
PEFT 是夹在 transformers 和 training 之间的算法层。它只关心一件事:怎么修改模型 forward 流程,让训练时只更新一小撮参数。
1.4 设计哲学:算法工厂 + 统一接口
- 统一抽象:所有算法都继承自
PeftConfig,所有"加 adapter 后的模型"都是PeftModel。 - 目标模块通过字符串匹配:用户写
target_modules=["q_proj", "v_proj"],PEFT 通过re.match找到模型里所有名字符合的 Linear。 get_peft_model是入口:所有转换都过这里。- 多 adapter 是一等公民:可以在同一个 base model 上加多个 LoRA adapter,运行时切换或合并。
- 跟随论文:每出一个新 PEFT 论文,社区通常很快会贡献到 PEFT。
1.5 算法选择速查
| 你的目标 | 推荐方法 |
|---|---|
| 显存够、想又快又好 | LoRA(基础首选) |
| 显存吃紧、想训 70B | QLoRA(4bit 加载 + LoRA) |
| 想自动决定每层 rank | AdaLoRA |
| 想要比 LoRA 略好但训练量类似 | DoRA |
| 显存极度吃紧、能接受效果略差 | IA³(参数量最小) |
| 只想加 prompt,不动模型权重 | Prompt Tuning / P-Tuning v2 |
1.6 本书将怎么带你走完这趟旅程
- 第 2-3 章装好环境,跑一个最小 LoRA 例子;
- 第 4 章讲清楚
PeftConfig/PeftModel/TUNERS三大抽象; - 第 5-9 章逐个算法剖析:LoRA / QLoRA / AdaLoRA / IA³ / Prompt 系,每个算法都会贴源码 + 论文公式对照;
- 第 10 章多 adapter 高级用法;
- 第 11 章踩坑合集;
- 第 12 章让你自己写一个新的 PEFT 方法 PoC(继承 BaseTuner);
- 第 13 章给一张
src/peft/tuners/目录的走读路线图。
1.7 PEFT 2024–2026 关键节点
PEFT 自 2022 末开源以来一直在跟论文。下表按时间倒序整理本书基线 commit a106ff4c7061 当时已合入 main 的关键节点,每条都关联本书具体小节:
| 时间 | 特性 | 说明 | 本书章节 |
|---|---|---|---|
| 2025-Q2 | 40+ tuner / vLLM serving 适配 | PEFT 正式跨越 30 个方法门槛 | ch08 / ch13.7 |
| 2025-Q1 | TorchAO 量化兼容 + EVA 初始化 | lora/torchao.py + tuners/lora/eva.py | ch05.10 / ch06.7 |
| 2024-12 | FourierFT / rsLoRA / Trainable Tokens | 频域 / scaling 调整 / 选择性 token 训练 | ch08.5 / ch08.9 |
| 2024-09 | add_weighted_adapter 支持 TIES / DARE | 7 种 combination_type | ch10.7 |
| 2024-06 | OFT / BOFT / HRA 集成 | 正交 adapter 家族 | ch08.4 |
| 2024-04 | PiSSA / OLoRA 初始化 | SVD-based init,2-4× 收敛 | ch05.5 |
| 2024-03 | VeRA | shared random matrix,0.05% 参数 | ch08.3 |
| 2024-02 | DoRA | weight decomposition;LoRA 增强 2-3% | ch05.4 / ch07.5 |
| 2023-12 | AdaLoRA 重构 + IA³ / LoHa / LoKr | 正交家族 + adaptive rank | ch07.2 / ch08 |
| 2023-09 | LoftQ 初始化 | 量化感知 SVD init | ch06.6 |
| 2023-07 | 多 adapter 一等公民 | add_adapter / set_adapter | ch10 |
| 2023-04 | QLoRA 集成 | bnb 4bit + LoRA | ch03 / ch06 |
| 2022-12 | PEFT v0.1 首次开源 | LoRA / Prefix / Prompt / P-Tuning 四件套 | — |
1.8 PeftType 全枚举(30+ 方法)
翻 src/peft/utils/peft_types.py 的 PeftType,会发现 PEFT 已经远不止 1.5 那个表。按"出现的场景"重新归类:
| 类别 | PeftType | 典型用 |
|---|---|---|
| LoRA 家族 | LORA / ADALORA | 基础低秩适配 + 自适应秩 |
| LoRA 增强 | 同 LORA 但 use_dora / use_rslora 等 flag | DoRA / rsLoRA |
| 正交家族 | OFT / BOFT / HRA | 保模长的旋转更新 |
| 因子化家族 | LOHA / LOKR | Hadamard / Kronecker 积 |
| 共享随机基 | VERA / RANDLORA / PVERA | 极小参数(<0.1%) |
| 频域 | FOURIERFT / WAVEFT | DFT / 小波域适配 |
| 稀疏 / 块 | SHIRA / BONE / C3A | 结构化稀疏 |
| Prompt 系 | PROMPT_TUNING / PREFIX_TUNING / P_TUNING / MULTITASK_PROMPT_TUNING / ADAPTION_PROMPT | 虚拟 token / 前缀 |
| activation 缩放 | IA3 | 最小参数 scale 向量 |
| 多技能 / 路由 | POLY | Polytropon multi-head routing |
| 选择性 | TRAINABLE_TOKENS | 只训部分 token embedding(扩词表) |
| 实验性 | DELORA / GRALORA / VBLORA / TINYLORA / LILY / MISS / ROAD / OSF / CPT / ADAMSS / BEFT / CARTRIDGE | 每个对应一篇近期论文,按本书 ch13.7 索引 |
"我该选哪个?"决策树:
- 显存够 + 想稳产 → LoRA(首选);
- 显存吃紧 + 70B → QLoRA(LoRA + 4bit bnb);
- 有数据想做更精细 → DoRA(LoRA + weight decomp,
use_dora=True); - 需要自动决定每层 rank → AdaLoRA;
- 极端参数预算(< 0.1%) → VeRA / IA³;
- 只想加新 token 不动权重 → Trainable Tokens;
- 所有其余实验性方法都先用 LoRA 跑通 baseline 再尝试。