前言
曾在游戏世界挥洒创意,也曾在前端和后端的浪潮间穿梭,如今,而立的我仰望AI的璀璨星空,心潮澎湃,步履不停!愿你我皆乘风破浪,逐梦星辰!
核心
其实,LoRA 核心就一句话:“用局部微调的方法去逼近全量微调的效果。”
📌 如何理解?
-
全量微调(Full Fine-tuning):
- 需要更新模型所有参数,计算量和存储开销大。
- 如果模型有 100 亿个参数,就要微调 100 亿个参数,需要大量 GPU 显存。
-
LoRA(Low-Rank Adaptation):
- 冻结原始模型权重,不直接修改参数。
- 只在部分层(如 Attention 层)插入低秩矩阵(A, B),用较小的参数量去拟合完整的微调效果。
- 训练时 只更新 A, B,最终计算: W=W0+ABW = W_0 + AB
- 参数量大幅减少,但仍然能近似达到全量微调的效果。
📌 直观理解:
- 全量微调 就像 重新装修一整个房子(耗时、耗钱)。
- LoRA 只是在关键点 增加可移动家具,改变风格但不动房子本身(快速、低成本)。
📌 直观数学示例
假设原始模型参数矩阵:
W0∈R ^ (4×6)
如果直接全参数微调,我们需要更新 4 x 6 = 24 个参数。
✅ 全量微调
W=W0+ΔW
其中:
ΔW∈R8×10
需要训练 80 个参数,计算量大。
✅ LoRA 微调
ΔW=AB
其中:
- A∈R8 × 2(8×2 低秩矩阵)
- B∈R2 x 10(2×10 低秩矩阵)
参数总量:
(8×2)+(2×10)=16+20=36
相比全量微调的 80 个参数,参数量大幅减少,但 AxB 仍然可以逼近 W0。
📌 结果
- 训练的参数量减少,但最终效果接近全量微调。
- 计算复杂度降低,适合大模型(GPT, LLaMA)。
📌 LoRA 微调 vs. 增量微调(Incremental Fine-tuning)
LoRA(Low-Rank Adaptation)和增量微调(Incremental Fine-tuning)都属于高效微调方法,但它们在 参数更新方式、存储方式、计算开销 方面有显著不同。
1️⃣ 主要区别
对比项 | LoRA(局部低秩微调) | 增量微调(Incremental Fine-tuning) |
---|---|---|
原始权重 | 冻结,不修改 $W_0$ | 复制一份 $W_0$,修改部分参数 |
训练参数 | 仅训练低秩矩阵 $A, B$,计算量低 | 训练部分或全部参数,计算量大 |
计算复杂度 | $O(d_{out} \times r + r \times d_{in})$(远小于全参数) | $O(d_{out} \times d_{in})$(部分更新) |
存储开销 | 只存储 $A, B$,存储开销小 | 存储新的 $W'$(部分更新) |
推理方式 | $W = W_0 + AB$(可合并) | 切换到新模型 $W'$ 进行推理 |
适用场景 | 适用于大模型(如 GPT、LLaMA),低显存设备 | 适用于长期训练,持续优化模型 |
📌 总结
- LoRA → 仅用两个小矩阵 $A, B$ 调整 $W_0$,不修改原始权重,节省计算量。
- 增量微调 → 修改部分参数(如 Adapter 层),但比 LoRA 占用更多计算资源。
2️⃣ LoRA 微调原理
LoRA 采用:
W=W0+ΔWW = W_0 + \Delta W
其中:
ΔW=AB\Delta W = AB
- $A$(低秩矩阵,$d_{out} \times r$)
- $B$(低秩矩阵,$r \times d_{in}$)
- LoRA 仅训练 $A, B$,不修改 $W_0$,所以存储开销小。
3️⃣ 增量微调(Incremental Fine-tuning)原理
增量微调的策略通常有:
- Adapter 层:在原始模型 $W_0$ 之外添加新的参数层: W′=Adapter(W0)W' = \text{Adapter}(W_0)
- 部分参数更新:只训练Transformer 某些层的参数:
for param in model.encoder.layer[-2:].parameters(): param.requires_grad = True # 仅微调最后两层
- 长期训练模式:支持多个阶段训练,每个阶段都增量更新参数。
4️⃣ 计算复杂度对比
(1) LoRA
如果原始 Transformer 权重矩阵为:
W0∈Rd{out}×d{in}
LoRA 只需训练:
A∈Rd{out}×r, B∈Rr×d{in}
计算复杂度:
O(d{out}×r+r×d{in}), 显存占用大幅减少。
(2) 增量微调
假设只微调最后 N 层 Transformer,参数量:
O(N×d{out}×d{in})
- 计算量比 LoRA 大,但比全参数微调(Fine-tuning)小。
5️⃣ 代码对比
(1) LoRA 代码
from peft import LoraConfig, get_peft_model
from transformers import AutoModelForCausalLM
model_name = "facebook/opt-1.3b"
model = AutoModelForCausalLM.from_pretrained(model_name)
lora_config = LoraConfig(
r=8, # 低秩参数
lora_alpha=32,
target_modules=["q_proj", "v_proj"]
)
model = get_peft_model(model, lora_config)
- 只训练
q_proj
,v_proj
层的 LoRA 矩阵。 - 不修改原始 $W_0$,只增加 $A, B$ 训练参数。
(2) 增量微调代码
from transformers import AutoModelForCausalLM
model_name = "facebook/opt-1.3b"
model = AutoModelForCausalLM.from_pretrained(model_name)
# 仅微调最后两层 Transformer
for param in model.transformer.h[-2:].parameters():
param.requires_grad = True
- 仅更新最后两层 Transformer 权重,减少计算量
- 比 LoRA 存储开销大
6️⃣ 适用场景
场景 | LoRA 微调 | 增量微调 |
---|---|---|
大语言模型(GPT-3, LLaMA) | ✅ 适合(低计算量) | ❌ 计算太大 |
持续优化的 AI 模型 | ❌ LoRA 训练完就定型 | ✅ 适合持续优化 |
低显存设备(8GB 显存) | ✅ 适合(节省显存) | ❌ 需要更高显存 |
高精度任务(如 BERT QA) | ❌ 可能损失精度 | ✅ 适合 |
多任务迁移学习 | ✅ LoRA 参数可迁移 | ❌ 需要重新训练 |
7️⃣ 总结
对比项 | LoRA 微调 | 增量微调 |
---|---|---|
是否修改原始参数 | ❌ 不修改 W_0 | ✅ 修改部分参数 |
训练参数量 | 🎯 少($O(d_{out} x r)) | 🚀 中($O(N xd_{out} x d_{in})) |
计算量 | 🎯 小(适合大模型) | 🚀 较大(适合小模型) |
存储开销 | 🏆 最小,只存 A,B | 📈 需要存储新 W |
推理方式 | ✅ 可合并参数 | ❌ 需要加载新权重 |
适用场景 | 🎯 适合 LLM(GPT, LLaMA) | 🚀 适合任务优化(BERT QA) |