LoRA(低秩适配)
Low-Rank Adaptation,一种高效微调方法:冻结原模型权重,只训练一个很小的低秩矩阵,大幅降低微调成本。
什么是 LoRA
LoRA(Low-Rank Adaptation)是一种参数高效微调方法。核心思想:不修改原始模型权重,而是在旁边加一个很小的"适配器"矩阵来学习任务特定知识。
打个比方:原模型是一本教科书(不能改写),LoRA 是你在书页边写的笔记——不改原书,但补充了特定场景的知识。
原理
传统微调
全量微调要更新模型所有参数。一个 70B 模型有 700 亿参数,全部更新需要:
- 700 亿参数的梯度计算
- 700 亿参数的优化器状态
- 至少 8×A100 GPU
LoRA 微调
LoRA 的数学原理:大模型权重矩阵 W 的更新可以用两个小矩阵 A × B 来近似:
W' = W + A × B
W: 原始权重 (d×d),冻结不动
A: 降维矩阵 (d×r),需要训练
B: 升维矩阵 (r×d),需要训练
r: 秩(rank),通常 8-64
当 r=8, d=4096 时:
- 原始参数:4096×4096 = 1678 万
- LoRA 参数:4096×8 + 8×4096 = 6.6 万
训练参数减少 99.6%。
优势
1. 显存大幅降低
| 方法 | 70B 模型显存 | GPU 需求 |
|---|---|---|
| 全量微调 | ~500GB | 8×A100 80G |
| LoRA 微调 | ~80GB | 1×A100 80G |
| QLoRA(量化+LoRA) | ~24GB | 1×RTX 4090 |
2. 训练速度快
参数少,梯度计算和优化器更新都更快。通常比全量微调快 2-3 倍。
3. 可插拔
LoRA 适配器是一个独立的小文件(几十 MB),可以:
- 随时加载/卸载
- 多个 LoRA 切换使用
- 不同用户用不同 LoRA
4. 不破坏原模型
原模型权重不变,可以随时回到原始状态。多个 LoRA 可以叠加。
LoRA 家族:LoRA / QLoRA / DoRA / AdaLoRA
LoRA 出来后衍生了一堆变体,按需选用:
| 方法 | 核心改动 | 相对 LoRA 的变化 | 适合 |
|---|---|---|---|
| LoRA | 基础版 | — | 通用、入门首选 |
| QLoRA | 把原模型量化到 4bit 再加 LoRA | 显存 -70%,速度略慢 | 消费级 GPU |
| DoRA | 分解为「方向 + 大小」分别学 | 同参数量下效果接近全量微调 | 追求效果上限 |
| AdaLoRA | 训练中动态调整每层的 rank | 自动找最优 rank 分配 | 不想手调 rank |
| VeRA | 共享随机矩阵 + 缩放向量 | 参数量再降 10x | 多 LoRA 大量部署 |
经验:80% 场景 LoRA 就够,显存不够上 QLoRA。DoRA 适合 LoRA 效果不到位但又不想全量微调的中间地带。
劣势
1. 效果略逊全量微调
LoRA 在大多数任务上接近全量微调,但在需要大幅改变模型行为的场景(如全新语言学习)可能不如全量。
2. 需要调参
LoRA 的关键参数:
- r(秩):8-64,越大效果越好但参数越多
- alpha:缩放因子,通常设为 r 的 2 倍
- target_modules:对哪些层加 LoRA(通常选 q_proj, v_proj)
- dropout:0.0-0.1,防过拟合
- 学习率:1e-4 到 5e-4(比全量微调高一个数量级)
3. 推理时需要决定合不合并
LoRA 推理时有两种姿势,各有取舍:
| 方案 | 推理性能 | 灵活性 | 适合 |
|---|---|---|---|
| 合并到原模型(merge) | 与原模型完全一致,零开销 | 死板,换 LoRA 要重新合并、重新部署 | 单一固定 LoRA、生产稳定环境 |
| 运行时加载 | 多一次矩阵加法,延迟 +5-15% | 同进程切换多个 LoRA、A/B 测试 | 多租户 / 多版本场景 |
target_modules 怎么选
这是 LoRA 调参里最玄学也最关键的一项。常见组合:
| 组合 | 训练参数 | 效果 | 何时用 |
|---|---|---|---|
只 q_proj, v_proj | 最少 | 一般 | 显存极紧 / 快速实验 |
q_proj, k_proj, v_proj, o_proj(全注意力) | 中 | 较好 | 通用推荐起点 |
全注意力 + MLP(gate_proj, up_proj, down_proj) | 多 | 接近全量微调 | 任务复杂、显存够 |
LLaMA-Factory / PEFT 都允许 target_modules="all-linear" 一把梭,对小模型(< 13B)通常直接用这个最省心。
QLoRA:4bit 量化 + LoRA
QLoRA 是 LoRA 的进一步优化:把原模型量化到 4bit 再做 LoRA 微调。
| 指标 | LoRA | QLoRA |
|---|---|---|
| 70B 模型显存 | 80GB | 24GB |
| GPU 需求 | A100 | RTX 4090 |
| 效果损失 | 无 | <1% |
| 训练速度 | 基准 | 慢 20% |
QLoRA 让在消费级 GPU(RTX 4090/3090)上微调 70B 模型成为可能。
推理服务的 LoRA 支持
把 LoRA 跑到生产,关键看推理框架支不支持多 LoRA 动态切换:
| 框架 | LoRA 支持 | 多 LoRA 热加载 |
|---|---|---|
| vLLM | ✅ | ✅ 一份基础模型 + 多个 LoRA 同时服务 |
| TGI(HuggingFace) | ✅ | ✅ 支持运行时切换 |
| TensorRT-LLM | ✅ | ⚠️ 需要预编译 |
| llama.cpp | ✅ GGUF + LoRA | ⚠️ 通常建议合并后再用 |
| Ollama | ⚠️ 通常合并 | ❌ |
真正的杀手锏场景:vLLM 的多 LoRA 部署。1 张 80G A100 可以同时服务 1 个 70B 基础模型 + 几十个 LoRA Adapter,不同用户请求路由到不同 LoRA。SaaS 化 fine-tune 服务(Together、Modal 等)背后基本都是这套。
多 Adapter 切换的实战案例
一个客服系统服务多个品牌客户:
共享基础模型: Qwen-2.5-7B
├─ adapter_brand_A.safetensors (40MB) ← A 品牌话术 / 知识
├─ adapter_brand_B.safetensors (40MB) ← B 品牌话术 / 知识
└─ adapter_brand_C.safetensors (40MB)
请求时按 brand 字段路由到对应 LoRA。优势:
- 7B 基础模型只占一份 GPU 显存
- 新增品牌只要训练一个 40MB 的 LoRA,几小时上线
- 任一品牌出问题,回滚单个 LoRA 即可,不影响其他
如果用全量微调,要么每个品牌一份 14GB 模型权重(贵),要么混在一起训(容易互相干扰)。
实操工具
LLaMA-Factory
开箱即用的 LoRA 微调工具:
# 安装
pip install llama-factory
# Web UI 启动
llamafactory-cli webui
# 命令行微调 Qwen
llamafactory-cli train \
--model_name_or_path Qwen/Qwen2.5-7B \
--finetuning_type lora \
--lora_rank 8 \
--dataset your_dataset \
--output_dir ./output
PEFT (Hugging Face)
from peft import LoraConfig, get_peft_model
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2.5-7B")
config = LoraConfig(
r=8, lora_alpha=16,
target_modules=["q_proj", "v_proj"],
lora_dropout=0.05,
)
model = get_peft_model(model, config)
# 训练...
Axolotl
YAML 驱动的训练框架,社区配方丰富,适合追新(DoRA / 新优化器先到)。
什么时候用 LoRA
| 场景 | 推荐 |
|---|---|
| 风格/格式调整 | ✅ LoRA |
| 领域知识注入 | ✅ LoRA + RAG |
| 多租户定制 | ✅ LoRA(多 Adapter 部署) |
| 快速实验 | ✅ LoRA |
| 消费级 GPU | ✅ QLoRA |
| 全新语言学习 | 全量微调 |
| 安全对齐 | 全量微调 / DPO |
| 闭源模型微调 | 用厂商 fine-tuning API |
延伸阅读
- 路线选型:Fine-tuning vs RAG
- 数据准备前:Embedding / RAG
- 模型部署:Token 计费视角