LoRA 与 PEFT 微调
难度:⭐⭐ | 高频指数:🔥🔥 | 应用岗相关度:★★★
面试回答
常见问法
- 为什么不直接全参微调,非得搞 LoRA / PEFT 这一套?
- LoRA 的低秩假设到底是什么,为什么 r 设得很小也能 work?
- QLoRA、DoRA、AdaLoRA、LoRA+ 这几个变体分别解决什么问题?
- 你们项目里用什么工具链跑微调?踩过哪些坑?
- 推理时 LoRA 要不要 merge 进基座,怎么决策?
- 微调和改 prompt / RAG 之间怎么选?
回答
PEFT(Parameter-Efficient Fine-Tuning)的出发点很朴素——全量微调一个 7B 模型显存就要几十 G,70B 直接劝退;而且每个业务存一份全量权重,部署成本也顶不住。 PEFT 的思路是冻住主干权重,只训练一小撮新加进来的参数,显存、磁盘、部署成本全部数量级下降。
LoRA 是 PEFT 里最主流的一支,核心假设是「模型微调时的权重更新 ΔW 是低秩的」——既然是低秩,就能拆成两个小矩阵 B × A,其中 B 是 d × r、A 是 r × k,r 远小于 d 和 k。训练时只更新 B 和 A,原始 W 完全冻结,参数量能压到原来的 0.1% ~ 1%。
工程上的关键判断是:LoRA 适合「增量能力」,不适合「领域重塑」。教模型一种新的回复风格、注入一个垂类问答能力、对齐一种业务输出格式,LoRA 都很合适;但要让模型重新学一门小语种、补全大段缺失的领域知识,就该走继续预训练(continue pretraining)而不是 LoRA。
面试时要表现出的判断力是:会跑 LoRA 脚本不等于会做微调,面试官真正想问的是数据准备、超参选型、效果评估、和 prompt / RAG 的边界——脚本是工具,决策才是难点。
追问
- LoRA 的 rank r 怎么选?是不是越大越好?
- alpha 这个超参的物理含义是什么,和 r 怎么配合?
- 为什么 LoRA 一般只挂在 attention 的 Q / K / V 上,不挂 FFN?
- QLoRA 的 4-bit 量化会不会让训练不稳定?
- 多 LoRA 热切换(S-LoRA、LoRAHub)在生产里是怎么实现的?
- 你怎么判断微调有没有引入灾难性遗忘?
原理展开
1. 为什么需要 PEFT
全量微调的代价分三块:
- 显存爆炸:训练时除了模型权重,还要存梯度、优化器状态(Adam 是 2 倍参数量)、激活值。粗算 7B 模型 FP16 全参微调要 100G+ 显存,单卡根本放不下
- 存储爆炸:每个业务一份全量权重,7B 就是 14G、70B 就是 140G,10 个业务下来磁盘和加载时间都不可接受
- 灾难性遗忘:全参微调小数据集,原模型的通用能力会被破坏——尤其是数据量只有几千到几万条的常见业务场景
PEFT 一次性解决三个问题:冻主干、只训一小撮新参数、按需切换 adapter。LoRA 训完一个 7B 模型的 adapter 通常只有几十 MB,部署多份业务变成「一个基座 + N 个小补丁」的形态。
2. LoRA 的数学原理
核心公式就一行:
W' = W + ΔW = W + B × A
其中:
W ∈ R^{d×k}:原始预训练权重,完全冻结B ∈ R^{d×r}:初始化为零,可训练A ∈ R^{r×k}:高斯初始化,可训练r:低秩矩阵的秩,典型取值 4 / 8 / 16 / 32
forward 时计算变成:
# 原本
y = x @ W
# LoRA 之后
y = x @ W + (x @ A.T) @ B.T * (alpha / r)
B 初始化为零,所以训练开始时 ΔW = 0,模型行为和基座完全一致——这是为什么 LoRA 训练初期非常稳定。
低秩假设的直觉是:预训练模型已经学到了通用表示,下游任务的「微调增量」其实只在一个很小的子空间里活动。LoRA 原论文做过实验,r = 1 都能在很多任务上 work,r = 8 通常已经足够。
3. 主流变体差异
LoRA ──→ 最基础形态,rank-r 分解 ΔW
QLoRA ──→ 4-bit 量化主干 + LoRA,消费级显卡训 65B
LoRA+ ──→ B 用更大学习率(10x A),收敛更快
DoRA ──→ 把权重分解成方向 + 幅度,方向用 LoRA、幅度单独训
AdaLoRA ──→ 动态分配各层的 rank,重要层多分配
VeRA ──→ 共享随机 A / B,只训缩放向量,参数量再降一个数量级
工程里 90% 场景用普通 LoRA 或 QLoRA 就够,剩下的变体大多是论文层面的优化。实战里数据质量和数据量的影响远大于变体选择——这点要在面试里强调出来。
4. 超参选型
| 超参 | 含义 | 典型取值 | 调参直觉 |
|---|---|---|---|
r | 低秩矩阵的秩 | 8 / 16 / 32 | 任务复杂度越高 r 越大,一般 16 起步 |
alpha | 缩放系数 | 通常 = 2r | alpha / r 控制 LoRA 实际作用强度 |
target_modules | 挂载位置 | q_proj, v_proj | 强场景全挂(QKVO + FFN),弱场景只挂 QV |
dropout | LoRA 内 dropout | 0.0 ~ 0.1 | 小数据集开 0.05,大数据集 0 |
learning_rate | 学习率 | 1e-4 ~ 3e-4 | 比全参微调高 10 倍以上 |
实战经验:alpha 和 r 一起调比单独调任一个都重要——很多人调了半天发现 alpha 设成了默认 16,r 改成 64 后实际作用强度反而变弱了。
5. 挂在哪里
原论文只挂 Q / V,后来发现挂得越多效果越好(但参数量也线性涨):
- 保守方案:只挂 q_proj, v_proj —— 参数量最小,适合简单风格对齐
- 主流方案:挂 q_proj, k_proj, v_proj, o_proj —— attention 全挂
- 激进方案:attention + FFN(gate_proj, up_proj, down_proj)—— 表达能力最强,QLoRA 论文推荐
面试时如果被追问「为什么 FFN 也要挂」,标准答案是:FFN 占模型参数量的 2/3,是知识存储的主要位置,挂上去对知识类任务收益明显。
6. QLoRA 是怎么省显存的
QLoRA 三件套:
- 4-bit NormalFloat 量化主干:把 FP16 权重压成 4-bit,显存直接 1/4
- Double Quantization:连量化常数也量化一次,再省一点
- Paged Optimizer:用 NVIDIA 的 unified memory,OOM 时自动 swap 到 CPU
效果:7B 模型微调能塞进 12G 显存,65B 能塞进 48G——消费级 4090 单卡就能跑。代价是训练慢 30% ~ 50%,效果略低于 FP16 LoRA 但差距很小。
工程上 QLoRA 几乎是显存受限场景的默认选择。
7. 合并 vs 不合并
训练完成后两个选项:
# 选项 A:合并进基座
merged = base_model + B @ A # 推理时和原模型完全等价
# 优点:推理零开销
# 缺点:失去切换能力,每个业务存一份完整权重
# 选项 B:保留 adapter
load_base() + load_adapter("biz_a") # 切到业务 A
load_base() + load_adapter("biz_b") # 切到业务 B
# 优点:一个基座 + N 个小补丁,多租户方便
# 缺点:推理时多一次矩阵加法,吞吐略降
S-LoRA、LoRAX 等推理框架专门优化「不合并」场景,支持单 GPU 同时服务上百个 adapter,每个请求按 token 级路由——这是多租户 LoRA 服务的标配。
实战里:单业务直接 merge,多业务多场景用 adapter 池。
8. PEFT 工具链
主流选择:
| 工具 | 定位 | 适合谁 |
|---|---|---|
| HuggingFace PEFT | 官方库,最通用 | 二次开发、做研究 |
| LLaMA-Factory | 一站式微调脚手架 | 快速试错、覆盖最多模型 |
| Axolotl | YAML 配置驱动 | 团队规范化、可复现 |
| Unsloth | 速度优化 2-5x | 算力紧张 |
| TRL(HF) | RLHF / DPO 专用 | 对齐训练 |
面试里如果被问「你用哪个」,最好答两个:日常试错用 LLaMA-Factory 或 Unsloth 求速度,生产链路用 PEFT + 自家训练框架求可控。
9. 什么时候不该用 LoRA
LoRA 不是万能解,下面几类场景该用别的方案:
- 想注入大段新知识 → 走 RAG,不是微调
- 想改答案的准确性 → 先改 prompt、加 few-shot、上 RAG,都不行再考虑微调
- 想让模型学一门它没见过的语言 → 继续预训练(continue pretraining),LoRA 不够
- 数据量只有几百条 → 数据太少,微调容易过拟合,先做 prompt engineering
- 想改模型推理能力 → 走 SFT + RLHF / DPO,纯 LoRA 不够
微调的优先级永远在 prompt 和 RAG 之后——这是面试加分点。
对比总结
| 方案 | 训练参数量 | 显存占用 | 适合场景 | 代价 |
|---|---|---|---|---|
| 全量微调 | 100% | 极高 | 大数据、领域重塑 | 显存爆炸、易遗忘 |
| LoRA | 0.1% ~ 1% | 中 | 风格 / 格式 / 垂类对齐 | 增量能力,知识注入弱 |
| QLoRA | 同 LoRA | 低(1/4) | 消费级显卡训大模型 | 慢 30% ~ 50% |
| Prompt Tuning | < 0.01% | 极低 | 极轻量任务适配 | 效果不稳定 |
| Prefix Tuning | < 0.1% | 低 | 生成任务、可控生成 | 调参困难 |
| Adapter | ~ 1% | 中 | 多任务切换 | 推理多一层延迟 |
| 继续预训练 | 100% | 极高 | 领域 / 语言重塑 | 数据 / 算力要求高 |
简单记:改格式选 LoRA,改知识选 RAG,改语言选继续预训练。
易错点
- 把 LoRA 当万能解——大段知识注入它做不到,那是 RAG 或继续预训练的活
- rank 越大越好——r 上去了参数量和过拟合风险都跟着上去,收益边际递减
- alpha 和 r 不配合调——只改一个常常等于没改
- 忘了 alpha / r 的实际作用强度——很多人改 r 不动 alpha,导致 LoRA 实际影响变了都没察觉
- 数据质量没把好关——脏数据下 LoRA 反而放大训练集偏差,效果还不如不微调
- 没验证灾难性遗忘——微调完通用任务 benchmark 不跑一遍,线上才发现模型变笨了
- 多租户场景忘了能不能切回基座——merge 了之后基座行为不可逆,多业务部署要慎重
记忆技巧
记三组锚点:
- 低秩假设:ΔW = B × A,r 远小于 d / k,只训 0.1% 参数
- 三个变体:LoRA(基础)/ QLoRA(省显存)/ DoRA(拆方向幅度)
- 选型口诀:增量能力上 PEFT,领域重塑上继续预训练,知识问答上 RAG
面试速答版
PEFT 的本质是冻住基座、只训一小撮新参数,目的是省显存、省存储、避免灾难性遗忘。LoRA 是其中最主流的方案,核心假设是微调时的权重更新 ΔW 是低秩的,所以可以拆成 B × A 两个小矩阵,只训这两个,参数量能压到 0.1% ~ 1%。
工程上的关键判断是:LoRA 适合「增量能力」——风格、格式、垂类问答;不适合「领域重塑」——补大段知识或学新语言,那是 RAG 或继续预训练的场景。
超参里 r 一般 16 起步,alpha 通常 = 2r,挂载位置至少 q_proj / v_proj,强场景全 attention + FFN。显存紧张就用 QLoRA,多租户就用 adapter 池配 S-LoRA。
面试加分版
如果想多讲一层,可以补:
- LoRA 的初始化决定了训练初期稳定性——B 初始化为零、A 高斯初始化,保证训练开始时 ΔW = 0,模型行为不会突变
- alpha / r 才是 LoRA 实际作用强度——这是新人最容易忽略的细节,调 r 不动 alpha 等于偷偷改了影响系数
- 微调的优先级永远在 prompt 和 RAG 之后——能用 prompt 解决就不上 RAG,能用 RAG 解决就不微调,能 LoRA 解决就不全参,这是工程上的成本递增逻辑