LoRA / QLoRA 详解
LoRA 是目前最主流的参数高效微调(PEFT)方法,几乎是微调方向的必考题。本文从全参微调的痛点讲起,深入低秩假设、前向与初始化、超参数、QLoRA 三件套、主流变体、多 LoRA 服务、实战配方与高频追问。微调全貌见 微调范式。
一、为什么需要 LoRA?
全参数微调(Full Fine-Tuning)要更新模型所有参数,问题在于:
- 显存爆炸:除了参数本身,还要存梯度和优化器状态(Adam 约为参数量的 2 倍),7B 模型全参微调动辄上百 GB(见 分布式训练)。
- 存储与部署贵:每个任务都要存一份完整模型副本。
- 迭代慢:每次都动全部参数。
LoRA 的出发点:微调其实不需要改动那么多参数。研究发现大模型有较低的「内在维度(intrinsic dimension)」——把通用模型适配到具体任务,所需的改变集中在少数几个方向上。
二、LoRA 原理
2.1 低秩假设
LoRA(Low-Rank Adaptation)的核心假设:微调时权重的变化量 ΔW 是低秩的,可以用两个小矩阵的乘积近似。
对原始权重矩阵 W(d×d),冻结 W,在旁边加一个低秩旁路:
$$h = Wx + \Delta W x = Wx + \frac{\alpha}{r} BA, x$$
其中 A 是 r×d、B 是 d×r 的矩阵,秩 r ≪ d(如 r=8/16)。训练时只更新 A、B,可训练参数从 d² 降到 2dr,常常只有原来的千分之几。
冻结(不更新) 可训练(很小)
┌─────────┐ ┌───┐
x ──┬─▶│ W │──▶ Wx ──(+)────┤ + │──▶ h
│ │ d × d │ ▲ └───┘
│ └─────────┘ │
│ ┌───┐ ┌───┐ ×(α/r)│
└──▶│ A │──▶│ B │────────┘ 旁路:(α/r)·BAx
└───┘ └───┘
r×d d×r (r ≪ d)2.2 初始化与缩放
- 初始化:A 用随机高斯,B 初始化为 0,保证训练开始时 ΔW = BA = 0,模型等于原始基座,不被随机扰动破坏。
- 缩放:
ΔW = (α/r)·BA,α 是缩放超参,用来调节旁路的影响强度,让改变 r 时不必重调学习率。
三、LoRA 的三大优点
- 省显存省算力:只训练极少参数(且只有这部分需要优化器状态),单张消费级显卡就能微调大模型。
- 零推理延迟:训练完可把 BA 合并回原权重(
W' = W + (α/r)BA),推理时与原模型结构完全一致,无任何额外开销。这是 LoRA 相比 Adapter 的关键优势。 - 多任务热插拔:基座只存一份,每个任务只存一个几 MB 的 LoRA 权重,按需加载/卸载/融合。
四、关键超参数
| 参数 | 含义 | 经验 |
|---|---|---|
| r(秩) | 旁路矩阵的秩,决定容量 | 8/16/32/64;越大容量越强也越易过拟合、存储越大 |
| α(alpha) | 缩放系数 | 常设为 r 的 1~2 倍(如 r=16, α=32) |
| target_modules | 给哪些层加 LoRA | 至少 q_proj、v_proj;加上 k/o_proj 和 FFN(gate/up/down)效果更好 |
| dropout | LoRA 旁路 dropout | 0.05 左右防过拟合 |
| learning rate | 学习率 | 通常比全参微调大(如 1e-4~3e-4),因为只训小矩阵 |
经验:优先把 LoRA 加到更多层(含 FFN)通常比单纯增大 r 更有效;r 过大收益递减还易过拟合。
五、QLoRA:单卡微调超大模型
QLoRA = 量化(Quantization)+ LoRA,让单张 GPU 微调几十 B 的模型成为可能。三个关键技术:
- 4-bit NF4 量化:把冻结的基座权重量化到 4-bit(NormalFloat4,针对正态分布权重做了优化的数据类型),大幅降显存。
- 双重量化(Double Quantization):连量化所需的「量化常数」本身也再量化,进一步省显存。
- 分页优化器(Paged Optimizers):借 NVIDIA 统一内存,在显存峰值时把优化器状态临时挪到内存,防止 OOM。
工作机制:基座以 4-bit 存储,前向时按需反量化为 BF16 计算;梯度只流经 16-bit 的 LoRA 旁路(基座不更新)。从而在接近全参微调效果的同时,把 65B 模型微调显存压到单张 48GB 卡可承受。
代价:4-bit 反量化带来少量计算开销,训练速度比纯 LoRA 略慢;精度损失很小。
六、主流变体
| 变体 | 改进点 |
|---|---|
| QLoRA | 4-bit 量化基座,单卡微调超大模型 |
| DoRA | 把权重分解为「大小(magnitude)+ 方向(direction)」,只用 LoRA 调方向,效果更接近全参微调 |
| rsLoRA | 用 α/√r 替代 α/r 作缩放,让大 r 时训练更稳定、能用上更大的秩 |
| LoRA+ | 给 A、B 设不同学习率(B 的更大),收敛更快更好 |
| AdaLoRA | 按重要性动态分配各层的秩预算(重要层多给秩) |
| PiSSA | 用原权重的主奇异分量初始化 A、B,收敛更快、效果更好 |
| VeRA | 共享冻结随机矩阵、只训极少缩放向量,参数量更小 |
面试主线记牢:LoRA 是基础,QLoRA 解决显存,DoRA/rsLoRA/LoRA+/PiSSA 在效果和稳定性上改进。
七、多 LoRA 服务
LoRA 的「基座共享 + 小适配器」特性非常适合服务化:
- 热插拔:一个基座 + 多个 LoRA,按请求动态加载对应任务的适配器。
- 批量多 LoRA:vLLM 等支持在同一 batch 内为不同请求应用不同 LoRA(Multi-LoRA serving),极大提升多任务部署的资源利用率。
- 融合:把多个 LoRA 加权合并(如「翻译」+「正式语气」),但融合可能相互干扰,需测试。
八、实战配方(速记)
- 资源有限、需快速迭代或维护多任务 → 用 LoRA/QLoRA。
- 显存够、追求极致效果且数据多 → 考虑全参微调。
- 起步参数:r=16、α=32、target 覆盖 attention + FFN、dropout=0.05、lr≈2e-4、BF16。
- 显存不够 → 上 QLoRA(4-bit)。
- 用 LLaMA-Factory / PEFT / Unsloth 等工具一键配置。
九、高频追问
Q:LoRA 的核心假设是什么?为什么成立? 假设微调的权重变化 ΔW 是低秩的。直觉是微调只是把通用模型适配到具体任务,改变集中在少数方向(内在维度低);实验证明很小的秩就能达到接近全参微调的效果。
Q:LoRA 为什么不增加推理延迟,而 Adapter 会? LoRA 旁路可在推理前数学上合并进原权重(W+(α/r)BA),结构不变、零额外开销;Adapter 是串行插入的新模块,推理时必须额外前向,增加延迟。
Q:为什么 B 初始化为 0,A 用随机? 要保证训练开始时 BA=0、模型等于原始基座,不被随机扰动破坏。只需 A、B 之一为 0;但若两个都为 0 则梯度也为 0、无法学习,所以 A 随机初始化以提供梯度信号。
Q:r 和 α 怎么设? r 看任务复杂度和数据量(简单任务 r=8 够,复杂可加大),过大易过拟合且存储增加;α 常设为 r 的 1~2 倍,用于缩放旁路影响。把 LoRA 加到更多层往往比盲目增大 r 更有效。
Q:QLoRA 量化的是哪部分?会掉精度吗? 量化的是冻结的基座权重(4-bit NF4),LoRA 旁路保持高精度(BF16),前向时基座反量化为 BF16 计算。精度损失很小,效果接近 16-bit LoRA。
Q:QLoRA 的三件套是什么? 4-bit NF4 量化(降基座显存)、双重量化(量化常数再量化)、分页优化器(防显存峰值 OOM)。
Q:LoRA 能注入新知识吗? 能力有限。LoRA 更擅长调风格、格式、任务适配;要可靠注入大量新事实,继续预训练或 RAG 更合适。
Q:全参微调和 LoRA 怎么选? 数据多、追求极致效果、资源充足 → 全参;资源有限、需快速迭代或维护多任务版本 → LoRA/QLoRA。多数业务场景 LoRA 性价比最高。
Q:多个 LoRA 能同时用吗? 可以。可按需加载/卸载、批量多 LoRA 服务(同 batch 不同请求用不同 LoRA),也可加权融合多个 LoRA(但可能相互干扰,需测试)。
Q:DoRA 相比 LoRA 好在哪? DoRA 把权重分解为大小和方向两部分,用 LoRA 只调方向、单独学大小,更贴近全参微调的更新模式,在多数任务上效果优于原始 LoRA。