迁移学习(九):参数高效微调
从低秩适配的数学原理出发,系统讲解 LoRA、Adapter、Prefix-Tuning、Prompt-Tuning、BitFit、QLoRA 等参数高效微调方法,附 LoRA 从零实现与方法选型指南。
GPT-3 有 1750 亿参数,全量微调一次要占 700 GB 显存,再加上梯度和优化器状态,单卡根本放不下;要为 100 个客户分别定制一份模型,光存储就 70 TB 起步。**参数高效微调(Parameter-Efficient Fine-Tuning,PEFT)**给出的答案是:把预训练权重冻住,只训练一份不到 1% 的"增量",单张消费级显卡就能微调几十亿乃至几百亿参数的模型,性能几乎不掉。
本文从低秩假设的数学动因讲起,依次推导 LoRA、Adapter、Prefix-Tuning、Prompt-Tuning、P-Tuning v2、BitFit、QLoRA 的设计逻辑,给出 LoRA 的从零实现,最后用 GLUE 上的实测数据告诉你"什么场景该选什么方法"。
你将学到
- 为什么"权重更新是低秩的"这个假设站得住脚
- LoRA 的数学推导、初始化、缩放因子与权重合并
- Adapter 瓶颈结构的设计与插入位置
- Prefix-Tuning、Prompt-Tuning、P-Tuning v2 的区别
- QLoRA 如何把 65B 模型塞进单张 48 GB 显卡
- 各方法在 GLUE 上的性能对比与选型建议
预备知识
- Transformer 结构(Attention、FFN、残差与 LayerNorm)
- 矩阵分解基础(秩、SVD)
- 迁移学习基础(本系列第 1-6 篇)
全量微调的困境
形式化地,全量微调对所有参数 $\boldsymbol{\theta}$ 做优化:
$$\boldsymbol{\theta}^* = \arg\min_{\boldsymbol{\theta}} \mathcal{L}(\boldsymbol{\theta}).$$代价是真实的:
- 显存爆炸:175B 模型 FP32 权重 ~700 GB,加上梯度与 Adam 的两份动量,全量微调需要数 TB 显存。
- 存储成本:每个任务一份完整 checkpoint,100 个任务就是 70 TB。
- 灾难性遗忘:所有参数都在动,预训练知识容易被破坏。
- 服务复杂度:上线时无法用单一基座 + 路由的方式同时服务多个任务。
PEFT 把问题改写成加性分解:
$$\boldsymbol{\theta}^* = \boldsymbol{\theta}_0 + \Delta\boldsymbol{\theta}, \qquad |\Delta\boldsymbol{\theta}| \ll |\boldsymbol{\theta}_0|.$$预训练权重 $\boldsymbol{\theta}_0$ 冻结、共享,每个任务只训练并存储一份很小的 $\Delta\boldsymbol{\theta}$。“基座 + 增量"的范式让模型部署从奢侈品变成了日用品。
| 方法 | 可训练参数占比 | 存储节省 |
|---|---|---|
| 全量微调 | 100% | 0% |
| LoRA | 0.1% - 1% | 99% - 99.9% |
| Adapter | 0.5% - 2% | 98% - 99.5% |
| Prefix-Tuning | ~0.1% | ~99.9% |
| Prompt-Tuning | <0.01% | >99.99% |
| BitFit | ~0.1% | ~99.9% |
LoRA:低秩适配

一句话讲清楚
LoRA 假设 权重更新 $\Delta\mathbf{W}$ 本身是低秩的,于是用两个"瘦长矩阵"的乘积来参数化它:
$$\mathbf{W}' = \mathbf{W}_0 + \frac{\alpha}{r}\, \mathbf{B}\mathbf{A}, \qquad \mathbf{A} \in \mathbb{R}^{r \times d_{\text{in}}},\; \mathbf{B} \in \mathbb{R}^{d_{\text{out}} \times r},\; r \ll \min(d_{\text{in}}, d_{\text{out}}).$$冻结的 $\mathbf{W}_0$ 有 $d_{\text{in}} d_{\text{out}}$ 个参数;可训练的增量只有 $r(d_{\text{in}} + d_{\text{out}})$ 个。以 $d=4096, r=8$ 为例,LoRA 引入的参数仅占原矩阵的 0.39%。
为什么"低秩"是个好假设
两个经验结果支撑了这个假设:
- 本征维度(Aghajanyan 等,2020):微调过程实际上只在权重空间的一个低维子空间里走动。在不少任务上,几百个参数的子空间就足以追平全量微调。
- 预训练矩阵的奇异值谱:注意力投影矩阵的奇异值衰减很快,少数方向承载了大部分能量;而"在已经很专业的模型上做任务适配"所需要的更新方向,比这个还要更集中。
直觉上,预训练模型已经几乎什么都会了,下游任务只是让它"换一个角度看问题”,自然不需要动太多自由度。
初始化、缩放与前向
落地 LoRA 时有几个细节决定成败:
- 初始化:$\mathbf{A} \sim \mathcal{N}(0, \sigma^2)$(Kaiming 风格),$\mathbf{B} = \mathbf{0}$。这样保证了第 0 步时 $\Delta\mathbf{W} = \mathbf{0}$,模型从预训练行为开始训练,不会一步把它打坏。
- 前向计算:$\mathbf{h} = \mathbf{W}_0 \mathbf{x} + \tfrac{\alpha}{r}\,\mathbf{B}(\mathbf{A}\mathbf{x})$。绝对不要显式构造 $\mathbf{B}\mathbf{A}$——它就是那个 $d_{\text{out}}\times d_{\text{in}}$ 的稠密矩阵,正是我们要避免的。
- 缩放因子 $\alpha/r$:把"学习率"和"秩"解耦。秩翻倍时,等效学习率不变,因此 $\alpha$ 可以在不同 rank 之间复用。
- 权重合并:推理时执行 $\mathbf{W}_{\text{merged}} = \mathbf{W}_0 + (\alpha/r)\,\mathbf{B}\mathbf{A}$,把增量合并回原权重。推理时延零额外开销——你交付的依旧是单个权重矩阵。
- 该装在哪:实测把 LoRA 装在 Attention 的 query 和 value 投影上效果最好;只装其中一个不够,装到所有线性层收益边际明显,性价比反而下降。
体感对比:到底小多少?

以 GPT-3 175B 为基座,全量微调与 LoRA $r=8$ 的可训练参数差距大约是 五个数量级——但稍后我们会看到,在 GLUE 上得分几乎一样。
Adapter:在 Block 中插入瓶颈模块

Houlsby 等人(2019)走的是另一条路:不修改原有权重,而是在每个 Transformer Block 里插入小型可训练模块。Adapter 是一个带残差的瓶颈结构:
$$\text{Adapter}(\mathbf{h}) = \mathbf{h} + \mathbf{W}_{\text{up}}\, \sigma(\mathbf{W}_{\text{down}}\, \mathbf{h}), \qquad \mathbf{W}_{\text{down}} \in \mathbb{R}^{m \times d},\; \mathbf{W}_{\text{up}} \in \mathbb{R}^{d \times m},\; m \ll d.$$“先降维再升维"的把戏和 LoRA 一脉相承,区别在于:Adapter 是新加一层,LoRA 是改写一层。把 $\mathbf{W}_{\text{up}}$ 初始化在零附近,可以让新插入的 Adapter 一开始相当于恒等映射,不会破坏预训练行为。
Adapter vs LoRA:
| Adapter | LoRA | |
|---|---|---|
| 改了什么 | 新加一层 | 重新参数化已有权重 |
| 推理时延 | 增加(串行多了一层) | 无(合并进 $W_0$) |
| 单任务存储 | 每层 ~$2md$ 参数 | 每层 ~$r(d_\text{in}+d_\text{out})$ 参数 |
| 适合 | 编码器(BERT 系) | 生成式(GPT 系) |
后续两个变体值得了解。Pfeiffer Adapter 每个 Block 只在 FFN 之后保留一个 Adapter,参数减半但效果几乎不掉。并行 Adapter(He 等,2021)把瓶颈与 FFN 并行计算,避免 GPU 上的串行依赖,把推理延迟拉得很接近 LoRA。
Prefix-Tuning:前置软 Token

Prefix-Tuning(Li & Liang, 2021)干脆不动模型权重,而是在每一层的 key/value 序列前面,拼接 $m$ 个可学习的"虚拟 token”:
$$\bigl[\mathbf{P}_1, \ldots, \mathbf{P}_m,\; \mathbf{x}_1, \ldots, \mathbf{x}_n\bigr] \to \text{Transformer}.$$只有这些前缀矩阵参与训练,参数总量是 $m \times d \times L \times 2$(key + value,$L$ 层)。两个工程细节:
- 直接优化前缀向量训练不稳。原论文先把前缀过一个小 MLP 再喂给模型,推理时把 MLP 丢掉、只保留 MLP 输出的前缀向量。
- 前缀容量有限,硬任务上比 LoRA 差 0.5-1 分。
直觉上,这些前缀就像每层注意力的"调音器"——它们从第一层开始就引导模型对真实 token 的注意力分布,相当于把任务知识压缩在了 K/V 缓存里。
Prompt-Tuning 与 P-Tuning v2

Prompt-Tuning(Lester 等,2021)是极简版本:只在输入层前加 $m$ 个可学习 prompt,参数量仅 $m \times d$,往往只有几千个。
代价是它只在足够大的模型上才好用。Lester 等人的实验显示,模型规模越大,与全量微调的差距越小:1B 以下差距明显,10B 以上几乎可以忽略。直觉上,参数量大的模型自带"翻译任意连续向量"的能力,小模型则需要更局部、更具体的修改。
P-Tuning v2(Liu 等,2022)是 Prompt-Tuning 与 Prefix-Tuning 的折中:在每一层都加可学习 prompt,而不只是输入层。结果是无论模型大小、无论任务难易,都能追平全量微调,可训练参数依然只有 ~0.1%。
BitFit:只调 Bias
最极简的方法:只微调偏置项(Zaken 等,2021)。BERT 的偏置约占总参数的 0.08%,但在小数据 GLUE 任务上能与全量微调打平。原理也直观——偏置改变了每个非线性的输入分布,相当于不改"线性映射本身"的前提下,重新分配激活路径。它当 baseline 极其便宜;当主力方法时,比 LoRA 略弱。
QLoRA:量化 + LoRA

QLoRA(Dettmers 等,2023)让单张 48 GB 显卡微调 65B 模型成为可能。它把三件事组合在一起:
- NF4(4-bit NormalFloat)量化冻结的基座权重。NF4 是在"预训练权重近似零均值高斯"的假设下信息论最优的码本——而这个假设大体成立。
- 双重量化:把每个 block 的量化常数本身再量化一次,每个参数再省 ~0.4 bit。
- 分页优化器:让 Adam 的状态在 CPU 与 GPU 之间通过统一内存分页,长序列时不再 OOM。
关键点是:梯度仍然能穿过量化矩阵传到上面 bf16 的 LoRA 适配器。基座永远不需要 FP16 副本,只有小小的 LoRA 参数需要。右图说明了重量级:65B 全量微调要 ~700 GB 显存,QLoRA 只要 ~50 GB。
QLoRA 在 Vicuna 评测上与全量微调相比性能下降 <2%,硬件成本却下降了一两个数量级。
实现:从零写一遍 LoRA
| |
三个值得注意的细节:
- 前向永远不构造 $\mathbf{B}\mathbf{A}$——先左乘 $\mathbf{A}$ 得到一个宽度只有 $r$ 的中间张量,再乘 $\mathbf{B}$。
merge_weights是一次性的、原地的合并。合并之后这个 Layer 与nn.Linear在数值上完全等价,部署时延和不用 LoRA 一模一样。apply_lora沿模型树递归,只替换名字含"query"/"value"的层——这是 LoRA 论文给出的默认推荐。
方法对比:一张图看懂 GLUE 上的取舍

把 RoBERTa-base 在 GLUE 上的近似结果画成气泡图,整个设计空间就清楚了:
- LoRA $r=8$:仅训练 0.24% 的参数,与全量微调差距小于 0.1 分,性价比之王。
- Adapter:与 LoRA 准确率相当,但参数量约 4 倍、推理还有额外延迟。
- Prefix-Tuning:用很小的精度让步换来极少的参数,适合需要存几百份任务适配器的场景。
- Prompt-Tuning:在 RoBERTa-base 这种规模上不够看;底座越大它越好用。
- BitFit:作为最朴素的 baseline,效果好得令人意外。
选型指南
| 场景 | 首选 | 原因 |
|---|---|---|
| GPT 类生成模型微调 | LoRA(q,v) | 零延迟、易合并、可扩展到 70B+ |
| BERT 类多任务分类 | Adapter(Pfeiffer) | 单任务存储极小,工具链成熟 |
| 超大基座(>10B),多任务 | Prompt-Tuning | 存储开销可忽略,规模越大越好 |
| 推理时延零容忍 | LoRA + 合并 | 最终模型就是单个权重矩阵 |
| 小样本(千例量级) | Prefix-Tuning 或 BitFit | 强归纳偏置,过拟合风险低 |
| 单卡 24-48 GB,30B+ 模型 | QLoRA | NF4 + 分页 Adam 解锁这个尺寸段 |
LoRA 秩的选择:默认从 $r=8$ 开始。如果验证集差距超过 0.5 分,提到 16;显存吃紧降到 4。大模型反而更喜欢小 r——任务适配的本征维度并不会随模型尺寸线性增长。
Q&A
相对全量微调,PEFT 会损失多少性能?
模型规模 >10B 时通常 <1 分,常常落在噪声范围内;<1B 时差距可能 2-5 分,特别是数据量小的任务。
LoRA 的学习率怎么设?
比全量微调高 1-2 个数量级。可训练参数从零附近出发,可以承受更大的步长而不发散。常用配置:$\text{lr} = 1\text{e-}4$ 到 $5\text{e-}4$,配 cosine 衰减。
PEFT 能和量化结合吗?
这正是 QLoRA 在做的事——NF4 + 双重量化 + bf16 LoRA,把 65B 模型微调塞进单张 48 GB GPU,性能下降 <2%。
要不要把 LoRA 装到所有线性层?
不必。原论文实测 query+value 已经拿到大部分增益;加 key 和 output 边际很小,参数翻倍。Decoder-only LLM 上有时再加 MLP up/down 投影对长上下文任务略有帮助。
服务端 Adapter vs LoRA?
LoRA 合并后无任何额外延迟,与全量微调推理性能一致;Adapter 因为多了一层串行子层,延迟会增加 1-3%(并行 Adapter 能压到 1% 以下)。
小结
PEFT 的核心思想可以浓缩为一句话:预训练模型已经几乎什么都会了,下游任务只需要一个低维的"调音"。
- LoRA 用低秩分解参数化这个调音,零延迟、易合并,是当前事实上的默认方法
- Adapter 用瓶颈模块在 Block 内插入调音,存储开销小但有推理延迟
- Prefix-Tuning / Prompt-Tuning / P-Tuning v2 把调音做成"软 token",参数极少
- BitFit 极简到只调 bias,作为 baseline 出奇地有用
- QLoRA 把 4-bit 量化叠加到 LoRA 上,把单卡微调的尺寸上限推到了 65B
下一篇我们进入持续学习,看模型如何在不忘旧知识的前提下不断吸收新任务。
参考文献
- Hu, E. J., et al. (2021). LoRA: Low-Rank Adaptation of Large Language Models. ICLR.
- Aghajanyan, A., Gupta, S., & Zettlemoyer, L. (2020). Intrinsic Dimensionality Explains the Effectiveness of Language Model Fine-Tuning. ACL.
- Houlsby, N., et al. (2019). Parameter-Efficient Transfer Learning for NLP. ICML.
- Pfeiffer, J., et al. (2021). AdapterFusion: Non-Destructive Task Composition for Transfer Learning. EACL.
- He, J., et al. (2021). Towards a Unified View of Parameter-Efficient Transfer Learning. ICLR.
- Li, X. L., & Liang, P. (2021). Prefix-Tuning: Optimizing Continuous Prompts for Generation. ACL.
- Lester, B., Al-Rfou, R., & Constant, N. (2021). The Power of Scale for Parameter-Efficient Prompt Tuning. EMNLP.
- Liu, X., et al. (2022). P-Tuning v2: Prompt Tuning Can Be Comparable to Fine-Tuning Universally Across Scales and Tasks. ACL.
- Zaken, E. B., Ravfogel, S., & Goldberg, Y. (2021). BitFit: Simple Parameter-Efficient Fine-Tuning for Transformer-Based Masked Language-Models. ACL.
- Dettmers, T., et al. (2023). QLoRA: Efficient Finetuning of Quantized LLMs. NeurIPS.
系列导航
| 部分 | 主题 |
|---|---|
| 1 | 基础与核心概念 |
| 2 | 预训练与微调 |
| 3 | 域适应 |
| 4 | 小样本学习 |
| 5 | 知识蒸馏 |
| 6 | 多任务学习 |
| 7 | 零样本学习 |
| 8 | 多模态迁移 |
| 9 | 参数高效微调(本文) |
| 10 | 持续学习 |
| 11 | 跨语言迁移 |
| 12 | 工业应用与最佳实践 |