Skip to content

LoRA / PEFT

不修改原始模型的 99.9% 参数,只训练极少量新增参数,却能让一个通用 LLM 变成专业领域专家。LoRA 是 LLM 微调领域最重要的工程突破——它让普通开发者也能在消费级 GPU 上定制大模型。

Overview

PEFT(Parameter-Efficient Fine-Tuning,参数高效微调)是一类技术的统称,目标是在保持预训练模型大部分参数固定的前提下,通过训练少量额外参数来适配模型到特定任务。LoRA(Low-Rank Adaptation,低秉适配)是 PEFT 中最流行、最实用的方法。

传统全量微调(Full Fine-tuning)需要更新模型的所有参数(如 Llama 3 70B 有 700 亿参数),需要多张 A100/H100 和大量内存。LoRA 只需训练数百万到数十亿级别的参数,即可在单张消费级 GPU 上完成。

How LoRA Works

核心思想

假设模型某层的权重矩阵为 W ∈ ℝ^(d×k),全量微调学习的是一个更新量 ΔW。LoRA 假设这个更新量是低秉的(即可以分解为两个小矩阵的乘积):

W' = W + ΔW = W + BA

其中:
  B ∈ ℝ^(d×r),A ∈ ℝ^(r×k)
  r << min(d, k)  →  低秉约束

关键观察:原始模型参数 W 被冻结,只训练 B 和 A 两个小矩阵。当 r=8 时,参数量仅为原始的 0.1% 不到。

训练与推理

训练阶段

python
# 只计算 BA 的梯度
loss = criterion(model(x), target)
loss.backward()
optimizer.step()  # 只更新 A 和 B

推理阶段

python
# 将 BA 合并回原始权重
W_merged = W + BA
# 然后用 W_merged 进行正常推理

合并的好处:推理时没有额外开销,与原始模型速度相同。

Key Hyperparameters

参数含义常见设置影响
rank (r)低秉维度4, 8, 16, 32, 64越大容量越高,过大可能过拟合
alpha (α)缩放系数通常 = r 或 r/2控制 LoRA 适配强度,α/r 是实际缩放比
target_modules应用 LoRA 的层q_proj, v_proj 或 所有 linear更多层 → 更强表达力,但参数更多
dropoutLoRA 层的 dropout0.0 – 0.1防止过拟合
learning rate学习率1e-4 – 1e-3通常比全量微调高 10倍

Variants of PEFT

方法原理参数量适用场景
LoRA低秉矩阵分解极少通用,最广泛使用
QLoRALoRA + 4-bit 量化极少 + 低精度单张消费级 GPU 训练百亿级模型
DoRA权重分解为方向和大小分别适配比 LoRA 更稳定,性能稍好
AdaLoRA动态分配 rank 到不同层自适应重要性分配
IA³学习元素级缩放向量很少与 LoRA 结合使用效果最好
Prefix Tuning训练前缀嵌入向量生成任务
Prompt Tuning训练软提示嵌入极少超大模型上效果与全量微调接近

QLoRA: 消费级 GPU 上训练百亿模型

QLoRA 是 LoRA 的重要扩展,通过 4-bit NormalFloat 量化 + 双量化 + 分页优化,实现了:

  • Llama 2 65B 在 48GB GPU 上训练(原本需要 >780GB 显存)
  • 量化模型的性能损失极小(<1% 准确度下降)
  • 支持完整的 16-bit 梯度计算(通过双量化 buffer)

Practical Workflow

python
from peft import LoraConfig, get_peft_model, TaskType
from transformers import AutoModelForCausalLM

# 1. 加载预训练模型
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b")

# 2. 配置 LoRA
lora_config = LoraConfig(
    r=16,
    lora_alpha=32,
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj"],
    lora_dropout=0.05,
    bias="none",
    task_type=TaskType.CAUSAL_LM,
)

# 3. 包装模型
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# 输出: trainable params: 33M || all params: 6.7B || trainable%: 0.49%

# 4. 训练(只更新 LoRA 参数)
trainer = Trainer(model=model, ...)
trainer.train()

# 5. 保存适配器(只有几十 MB)
model.save_pretrained("./lora-adapter")

# 6. 推理时合并或动态加载

When to Use What

场景推荐方案理由
快速实验/原型验证LoRA (r=8)最快速度看效果
生产级部署QLoRA 或 LoRA + 量化最低硬件要求
极端性能追求DoRA 或 AdaLoRA比标准 LoRA 稳定性更好
多任务适配LoRA + IA³更强的表达能力
超大模型(>100B)Prompt Tuning参数效率最高

Why It Matters

  • 民主化模型定制:让个人开发者和小团队能在消费级硬件上定制大模型
  • 多租户架构:一个基座模型 + 多个小适配器 = 多个专用模型,极大降低部署成本
  • 迅速迭代:适配器训练只需分钟到小时,而非天/周
  • 避免灾难性遗忘:全量微调可能覆盖预训练知识,LoRA 保留基座能力

Relationships

  • 比较分析:Full FT vs LoRA vs QLoRA — 三种微调方法的全面对比
  • 基础概念:Fine-tuning — 微调的基本原理与实践
  • 量化关联:Model Quantization — QLoRA 依赖于 4-bit 量化技术
  • 工具生态:Hugging Face PEFT 库是 LoRA 的事实标准实现
  • 训练方法:Synthetic Data — LoRA 训练数据的质量决定适配效果

Open Questions

  • LoRA 的 rank 上限在哪?当某些任务需要 r=256 甚至更高时,是否还比全量微调更有优势?
  • 多适配器组合(如 Mixture of Adapters)能否达到模型合并的效果?
  • LoRA 在多模态模型(图文混合)上的表现如何?是否需要为视觉编码器单独设计适配策略?
  • 当基座模型更新时,旧适配器是否仍然有效?适配器版本管理的最佳实践是什么?

Sources

AI Knowledge Base — 持续积累