PEFT 详解
参数高效微调方法详解
PEFT 详解
一、概览
PEFT(Parameter-Efficient Fine-Tuning)是一个用于高效地将预训练模型适配到各种下游应用的方法族,无需对模型的所有参数进行微调。PEFT 方法仅微调少量(额外的)模型参数——显著降低了计算和存储成本——同时取得了与完全微调模型相当的性能。这使得在消费级硬件上训练和存储大型语言模型(LLM)更加容易。
PEFT 方法家族包括:
- LoRA 系列:通过低秩分解实现参数高效微调
- QLoRA:结合 4-bit 量化和 LoRA
- 提示方法:Prefix Tuning、Prompt Tuning 等
二、LoRA 系列
2.1 LoRA:低秩适配
问题背景与动机
核心问题:
- 随着模型规模增大(GPT-3 175B+),全量微调变得不可行:存储成本高、训练资源消耗大
- 传统适配器(Adapter)引入额外推理延迟
- 提示微调(Prompt Tuning)优化困难,性能随可训练参数非单调变化
LoRA 的解决方案:核心假设是模型适应过程中的权重变化 ΔW 具有低"内在秩"(intrinsic rank)。
理论基础:Li et al. (2018) 和 Aghajanyan et al. (2020) 研究表明,尽管预训练模型是过参数化的,但针对特定任务适应时,权重矩阵的实际变化存在于较低的内在维度上。
核心机制
冻结预训练权重 W₀ ∈ ℝ^(d×k),引入低秩分解矩阵:
其中:
- A ∈ ℝ^(r×k),B ∈ ℝ^(d×r),r ≪ min(d,k)
- α 为缩放因子,控制 LoRA 对原始权重的影响强度
- 实际缩放比例:α/r(通常设置 α = 2r)
关键超参数
| 参数 | 作用 | 常用设置 |
|---|---|---|
r (rank) |
低秩维度,控制参数量和表达能力 | 4, 8, 16, 32, 64 |
lora_alpha |
缩放因子,调节 LoRA 影响强度 | 通常设为 2*r |
target_modules |
注入 LoRA 的目标模块 | 根据架构选择 |
lora_dropout |
LoRA 层的 dropout 率 | 0.0 - 0.1 |
bias |
是否训练偏置项 | "none", "all", "lora_only" |
初始化策略(关键!)
self.lora_A = nn.Linear(in_features, r)
nn.init.kaiming_uniform_(self.lora_A.weight, a=math.sqrt(5))
# lora_B: 零初始化(确保训练初期不改变原始模型行为)
self.lora_B = nn.Linear(r, out_features)
nn.init.zeros_(self.lora_B.weight)
为什么 B 要零初始化?
- 训练开始时:ΔW = B · A = 0,模型输出等价于原始预训练模型
- 保证训练稳定性,从基线模型开始渐进学习
目标模块选择策略
| 配置 | 适用场景 | 说明 |
|---|---|---|
| Wq + Wv (经典) | 通用任务,资源受限 | 论文推荐,性价比最优 |
| 仅 Wq | 极低资源场景 | 参数量最小,性能尚可 |
| Wq + Wk + Wv | 复杂注意力任务 | 需要更精细控制时 |
| 全部四个 (Q,K,V,O) | 追求极致性能 | 参数量翻倍,收益递减 |
| 加入 Wo | 特定架构(如 LLaMA) | 视模型架构而定 |
注意:原论文发现 Wq+Wv 组合在参数效率和性能间达到最佳平衡。这不意味着 Wk "与预训练分布耦合紧密",而是实验观察到的收益递减现象。
核心优势:权重合并
训练阶段:h = W₀x + (α/r)BAx(并行计算)
推理阶段:可将 LoRA 权重合并回原矩阵:
合并后的优势:
- 零额外推理延迟(与原始模型完全等价)
- 零额外显存开销
- 这是 LoRA 相比 Adapter 的关键优势
代码实践
# 1. 定义配置
lora_config = LoraConfig(
r=8, # 低秩维度
lora_alpha=32, # 缩放因子(通常 = 2*r)
target_modules=["q_proj", "v_proj"], # 目标模块(LLaMA系列)
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM"
)
# 2. 包装模型
model = get_peft_model(base_model, lora_config)
# 3. 训练后合并权重(部署优化)
merged_model = model.merge_and_unload() # 合并LoRA权重到基模型
LoRA 总结
| 维度 | LoRA 特点 |
|---|---|
| 参数效率 | 可训练参数减少 10,000 倍(GPT-3 175B) |
| 显存效率 | GPU 显存需求降低 3 倍(vs 全量微调) |
| 训练吞吐 | 高于 Adapter,接近全量微调 |
| 推理延迟 | 零额外延迟(权重合并后) |
| 模型质量 | 与全量微调持平甚至更好 |
| 部署便利 | 支持动态切换、权重合并、量化兼容 |
2.2 QLoRA:量化 + LoRA
QLoRA 是一种参数高效微调方法,通过将预训练模型量化为 4-bit(NF4 格式)并结合低秩适配器,使得在单张消费级显卡上就能微调数百亿参数的大模型,且性能接近全量微调。
核心特性:
- 预训练模型的 4-bit 版本在训练全程持久保存在显存中
- 计算时反量化为 16-bit 参与梯度计算
- 梯度只更新 LoRA 适配器
- 预训练模型始终保持 4-bit 冻结状态
4-bit NormalFloat (NF4)
核心思想:神经网络权重通常呈正态分布,NF4 利用这一特性,设计了一种信息论最优的量化格式。
实现步骤:
- 分块量化:将权重张量分成小块(每块 64 或 256 个权重)
- 计算块统计量:计算每块的均值 μ 和标准差 σ
- 归一化:将权重映射到标准正态空间 N(0,1):x_norm = (x - μ) / σ
- 分位数量化:使用预计算的 N(0,1) 的 16 个等概率分位点进行查表量化
- 存储:存储 4-bit 索引,以及 μ 和 σ(后者再被二次量化)
名称含义:
- Normal:针对正态分布优化
- Float:每个 4-bit 编码对应一个浮点数值(而非整数)
三、提示方法
3.1 Prefix Tuning
痛点与目标
痛点:对大型预训练语言模型(如 GPT-2、BART)进行全参数微调时,每个下游任务都需要存储一份完整的模型副本(例如 GPT-2 有 7.74 亿参数)。当任务数量增多时,存储开销极大。
目标:提出一种轻量级的替代方案,冻结大部分预训练参数,只引入少量可训练参数,同时保证在生成任务上的性能接近甚至超越全参数微调。
直觉来源
- 受 Prompting(提示) 启发——通过给模型添加合适的上下文(如"TL;DR"表示摘要),可以引导模型完成特定任务,而无需修改模型参数
- 离散的、由自然语言构成的提示(如"请总结以下内容")对预训练模型效果有限,且离散优化困难
方法
在输入序列前添加一系列可学习的任务特定向量,同时保持预训练模型冻结。前缀参数被插入到模型的所有层中。
- 在输入序列的最前面添加一组连续的、可训练的虚拟向量,称为 Prefix(前缀)
- 前缀会参与到每一层 Transformer 的注意力计算中,被放在每个 multi-head attention 的 key 矩阵和 value 矩阵之前
- 特征向量长度未变,相当于增加了原始的 token 和这些 soft prompt token 计算相似度,然后聚合
- 训练时,冻结原始语言模型参数,仅优化前缀参数
实验证实
离散提示 < Embedding-only 软提示 < Prefix-Tuning(每层)
3.2 Prompt Tuning
Prompt Tuning 给每个任务定义了自己的 Prompt,拼接到数据上作为输入,同时 freeze 预训练模型进行训练。在没有加额外层的情况下,可以看到随着模型体积增大效果越来越好,最终追上了精调的效果。
Prompt Tuning 还提出了 Prompt Ensembling,也就是在一个 batch 里同时训练同一个任务的不同 prompt,这样相当于训练了不同"模型",比模型集成的成本小多了。
Prompt Tuning vs Prefix Tuning
| 维度 | Prompt Tuning | Prefix Tuning |
|---|---|---|
| 提出时间 | 2021 年(Google) | 2021 年(斯坦福/清华) |
| 训练位置 | 仅输入嵌入层 | 每一层的 Key/Value |
| 参数量 | 更少(通常 20-100 个 token) | 稍多(每层都有前缀) |
| 模型侵入性 | 无侵入,完全冻结模型 | 需修改注意力机制 |
| 实现复杂度 | 更简单 | 较复杂 |
| 重参数化 | 不需要 | 需要 MLP 生成前缀 |
| 小模型表现 | 需要较大模型(>10B)才有效 | 中小模型也能工作 |
| 大模型表现 | 随着模型增大,差距缩小 | 始终稳定 |
四、总结
PEFT 方法族为大模型的高效微调提供了多种选择:
- LoRA:最通用、最实用,支持权重合并,零推理延迟
- QLoRA:在 LoRA 基础上加入 4-bit 量化,进一步降低显存需求
- Prefix Tuning:适合生成任务,每层都有可学习前缀
- Prompt Tuning:最简洁的方法,仅在输入层添加可学习向量
选择哪种方法取决于具体的任务需求、硬件约束和性能要求。在实践中,LoRA 因其简单高效而成为最流行的选择。
← 返回 3. Post-training