微调工具类的文章站里已经有几篇:GPT-2 微调是流程演示,LlamaFactory 上手是不改代码的实操。这一篇补原理——LoRA 到底凭什么把微调成本打下来,以及它的边界在哪。
它解决什么问题
先算一笔账。全量微调一个 7B 模型,显存去了哪里?混合精度训练(FP16 权重 + Adam 优化器)下,每个参数的模型状态开销是 16 字节——这是 ZeRO 论文(Rajbhandari et al., 2020)给出的经典账本:
- 权重(FP16):2 字节
- 梯度(FP16):2 字节
- 优化器状态(FP32 主权重 4 字节 + 动量 m 4 字节 + 方差 v 4 字节):12 字节
三项乘以参数量:7B × 16 字节 ≈ 112GB,其中优化器状态一项就占 84GB——这还没算激活值。也就是说,全量微调的大头根本不是「权重本身」,而是为每个可训练参数配备的优化器状态与梯度副本。
这笔账直接指出了破局方向:如果可训练参数只占极小的比例,梯度和优化器状态的大头就自动消失了。剩下的问题是:只训练一小部分参数,模型还学得动吗?
它怎么工作
低秩假设的来历
答案来自一条研究脉络。Li et al.(2018)与 Aghajanyan et al.(2020)发现,预训练模型的「内在维度」(intrinsic dimension)极低:把微调参数随机投影到低得多的子空间,模型依然能学得很好,而且预训练越充分,这个维度越低。LoRA 论文(Hu et al., 2021)把这一观察推进了一步,提出了自己的核心假设:微调过程中权重的变化量 ΔW 同样具有很低的秩。既然 ΔW 是低秩的,就没必要用 d×k 个自由参数去表达它——直接按低秩分解来参数化它即可。
数学:W' = W0 + BA
对一个预训练权重矩阵 W0(d×k),LoRA 冻结它,把更新量分解为两个小矩阵的乘积:
W' = W0 + ΔW = W0 + BA
其中 B 是 d×r,A 是 r×k,秩 r ≪ min(d, k)。训练时只有 A、B 参与反向传播,W0 完全不动。
参数量能省多少?拿 Llama-2-7B(隐藏维度 4096,32 层,总参数约 6.7B)算一笔:
# Llama-2-7B:d=4096,32 层,LoRA 只挂在 q_proj 与 v_proj,r=8
d, layers, r = 4096, 32, 8
lora_per_layer = 2 * r * (d + d) # 每层 q、v 两处,A 与 B 各 r*d / d*r
total = layers * lora_per_layer # 4,194,304 ≈ 4.2M
print(f"可训练参数 {total:,},占总参数 {total / 6.7e9:.2%}")
# 可训练参数 4,194,304,占总参数 0.06%
r=8 时可训练参数约 420 万,只占总参数的 0.06%——梯度和优化器状态随之缩到 MB 量级。论文里 GPT-3 175B 的数字更夸张:可训练参数降到原模型的 0.01%(约 10,000 分之一),训练期显存从 1.2TB 降到 350GB,只挂 q/v 投影(r=4)时 checkpoint 从 350GB 缩到 35MB。
flowchart LR
x(("x")) --> W0["W0:冻结权重 d×k"]
x --> A["A:r×k,随机初始化"]
A --> B["B:d×r,初始全零"]
B --> SC["乘以缩放 α/r"]
W0 --> ADD(("+"))
SC --> ADD
ADD --> h(("h"))
工程细节里的四个讲究
挂哪些层。 论文主实验只把 LoRA 挂在注意力的 Wq、Wv 上,MLP 冻结。一个反直觉的消融结论是:固定可训练参数预算时,「多挂层 + 低秩」优于「少挂层 + 高秩」——r=2 打满四个注意力矩阵(q/k/v/o),比 r=8 只挂 Wq 效果更好(WikiSQL 73.7 对 70.4)。QLoRA 论文进一步补上结论:要追平全量微调,LoRA 需要挂在所有线性层(含 MLP),此时秩的大小反而不敏感。
初始化。 A 用随机高斯初始化,B 初始化为全零,保证训练起点 ΔW = BA = 0——微调从原始模型平滑出发,而不是从一个随机的扰动开始。(PEFT 参考实现中 A 用 Kaiming-uniform 初始化,细节截至 2026-10-07 以其文档为准。)
缩放因子 α/r。 ΔW 乘以 α/r 再加回主干。α 通常取第一次尝试的 r 值且不再精调——论文的说法是,调 α 的作用约等于调学习率,固定 α 可以让换 r 时不必重调超参数。
推理零延迟。 训练完成后直接计算并保存 W = W0 + BA,推理图与全量微调的模型完全一致,零额外延迟。这是 LoRA 对 Adapter 类方法的决定性优势:串行插入的 Adapter 在 GPT-2 medium 实测延迟最高 +30.3%(batch=1、seq=128)。切换任务也只需减去 BA、加上新的 B'A'。
QLoRA:把底座也压到 4-bit
LoRA 解决了「训练多少参数」的问题,但冻结的底座权重仍是 FP16。QLoRA(Dettmers et al., 2023)把底座量化成 4-bit 再挂 LoRA,靠三项技术做到「不牺牲精度」:
- NF4(4-bit NormalFloat):预训练权重呈零均值正态分布,用 N(0,1) 的分位点构造 4-bit 数据类型,对正态权重信息论最优;块大小 64,反量化后以 BF16 计算。
- 双重量化(Double Quantization):把第一层量化的 FP32 缩放常数再量化成 FP8(块 256),量化开销从 0.5 bits/参数降到 0.127 bits/参数,净省 0.373 bits/参数——65B 模型约省 3GB。
- 分页优化器(Paged Optimizers):借 NVIDIA 统一内存,把梯度检查点引起的显存尖峰挪到主存。
显存账因此改写:16-bit 微调 65B 模型需要超过 780GB,QLoRA 把它压到 48GB 以内的单卡。7B 模型的账更好算:4-bit 底座约 3.4GB,LoRA 参数、梯度与 Adam 状态合计几十 MB,剩下主要是激活值——一张 8GB 消费级显卡就能跑起微调。效果上,QLoRA 论文在 MMLU 上测得 NF4+双重量化 53.1 对 BF16 LoRA 53.0,基本无损;其微调出的 Guanaco 65B 在 Vicuna 评测中达到 ChatGPT 水平的 99.3%,用了 24 小时单卡。
边界在哪
学得少,忘得也少。 Biderman et al.(TMLR 2024)在 Llama-2-7B/13B 上对比了 LoRA(r=8/16)与全量微调:在代码与数学这类大域偏移的目标域上,LoRA 系统性落后于全量微调——它「学得少」;但换来的好处是源域能力保留得更好——它「忘得也少」,且全量微调加正则也追不平这个差距。所以分野很清楚:学新技能、大偏移任务,全量微调仍不可替代;风格对齐、指令跟随、领域适配这类「在既有能力上做微调」的场景,LoRA/QLoRA 是性价比起点。
r 的选择不是玄学但也不是关键。 GPT-3 实验里 r=1 都够用,r=64 也没有更好;QLoRA 侧的结论是覆盖面(挂满所有线性层)比秩更重要。域偏移大时可以加大 r,但要清楚它的收益有上限——瓶颈往往不在秩,而在低秩假设本身是否成立。
服役形态已经长出来了。 因为适配器小到可以大量囤积,服务端出现了 S-LoRA(Sheng et al., 2023):适配器驻留主存、按请求换入 GPU,用统一分页管理适配器权重与 KV Cache,单机服务数千个并发 LoRA 适配器,吞吐最高提升 4 倍。这是「零延迟合并」在服务端的翻版——底座共享,每个任务只换一对 BA。
回头看,LoRA 的本质是把「微调」从改写全部知识,降格为在冻结知识上叠加一层低秩修正:它省钱的前提是「要学的增量本来就小」。这个前提成立时,微调从一套集群经济学变成一张消费级显卡的账;不成立时,别硬省——该全量就全量。
参考资料
- LoRA: Low-Rank Adaptation of Large Language Models — Hu et al., ICLR 2022
- QLoRA: Efficient Finetuning of Quantized LLMs — Dettmers et al., NeurIPS 2023
- Intrinsic Dimensionality Explains the Effectiveness of Language Model Fine-Tuning — Aghajanyan et al., ACL 2021
- ZeRO: Memory Optimizations Toward Training Trillion Parameter Models — Rajbhandari et al., SC 2020
- LoRA Learns Less and Forgets Less — Biderman et al., TMLR 2024
- S-LoRA: Serving Thousands of Concurrent LoRA Adapters — Sheng et al., 2023
- Hugging Face PEFT 文档:LoRA
读者留言
COMMENTS 暂无还没有留言,来说第一句?