前言
来自: https://huggingface.co/blog/mlabonne/sft-llama3从全量微调到LoRA再到QLoRA,核心是为了解决在有限显存资源下微调大模型的问题。
| 方法 | 核心理念 | 一句话概括 |
|---|---|---|
| 全量微调 | 更新全部参数 | 搬整个图书馆,效果好但显存爆炸 |
| LoRA | 冻结原模型,只训练旁路小矩阵 A×B | 不搬书,只做索引卡,显存省10倍+ |
| QLoRA | LoRA + 4-bit量化 | 先把书压缩成口袋书,再做索引卡,显存再省60% |
技术细节对比
| 维度 | 全量微调 | LoRA | QLoRA |
|---|---|---|---|
| 模型精度 | FP16/FP32 | FP16 | 4-bit NF4 |
| 训练参数 | 全部(70亿) | 仅A和B(~800万) | 仅A和B(~800万) |
| 显存占用(7B) | 56+ GB | 14-16 GB | 6-8 GB |
| 训练速度 | 基准 | 快 | 更快(量化后计算量小) |
| 精度损失 | 无 | 无 | 极小(~1%) |
| 硬件要求 | A100/H100 | RTX 3090/4090 | RTX 3060(12GB即可) |
为什么 QLoRA 比 LoRA 还快? 数据变小了,计算自然变快。QLoRA计算4-bit数据,虽然多了“临时反量化”步骤,但整体计算量小,速度反而快20-50%。
📐 LoRA 核心技术原理
1. 核心思想:低秩分解
不碰原始权重W,在旁边加可训练的小补丁 A×B。
输出 = 输入 × W + 输入 × A × B
2. 为什么拆成 A 和 B?(数学原理)
将增量更新 ΔW 分解为两个小矩阵:ΔW (d×k) = A (d×r) × B (r×k),其中 r « d, k。
参数对比(d=4096, k=4096, r=8):
- 全量微调 (整个W):1600万参数/层
- LoRA (A+B):6.6万参数/层 (节省240倍)
3. 训练与推理流程
- 训练时:W冻结,梯度只流向A和B并更新。
- 推理时:计算新权重 W’ = W + A × B,使用W’推理,零额外开销。
⚙️ LoRA 三大核心参数详解
这三个参数共同决定了LoRA的容量、影响力和作用位置。
1. Rank(秩 r)
- 作用:决定LoRA补丁的“大小”或“容量”,即能存储多少信息。
- 影响:r越大,补丁越厚,参数量越大,表达能力越强,但显存占用也越高。
- 选择建议:
- r=4 ~ 8:数据少(几百条),追求极致速度。
- r=16:✅ 最常用、性价比最高,大多数任务首选。
- r=32 ~ 64:数据多(数万条)、任务复杂。
- 经验法则:从 r=16 开始尝试。
2. Alpha(α)—— 缩放因子
- 作用:控制LoRA补丁对最终输出的“影响力”。
- 实际计算:
实际补丁贡献 = (α / r) × (输入 × A × B)。关键在于 α/r 这个比值。 - 影响:α越大,补丁影响力越大,模型“更听LoRA的话”;反之则更保守。
- 选择建议:
- 常见配置:α = r(缩放系数=1)或 α = 2×r(缩放系数=2,学习更激进)。
- 经验法则:从
α = r或α = 2×r开始。
3. Target Modules(目标模块)
- 作用:指定在模型的哪些“部位”(如注意力层的Q、K、V投影)挂载LoRA补丁。
- 各策略对比:
| 策略 | Target Modules | 可训练参数(7B, r=16) | 推荐度 |
|---|---|---|---|
| 极致轻量 | ["q_proj"] |
~210万 | ⭐⭐ |
| ✅ 保守推荐 | ["q_proj", "v_proj"] |
~420万 | ⭐⭐⭐⭐ |
| ✅ 标准推荐 | ["q_proj", "k_proj", "v_proj"] |
~630万 | ⭐⭐⭐⭐⭐ |
| 激进 | 更多模块(如Q,K,V,O,FFN) | ~1500万+ | ⭐⭐ |
- 经验法则:从
["q_proj", "v_proj"]或["q_proj", "k_proj", "v_proj"]开始。
🧩 参数间的协同关系:α 与 r 的本质
核心结论:α和r共同决定缩放因子(α/r),但分开设计是为了独立控制LoRA的“容量”(r)和“强度”(α/r)。
- r(秩):控制 “容量”——补丁能存多少信息。比喻:笔记本的页数。
- α(缩放系数):控制 “强度”——补丁对模型的影响有多大。比喻:每页字号大小。
- α/r(缩放因子):实际训练中补丁的最终影响力。
为什么这样设计? 为了解耦“容量”和“强度”,获得更高的调参自由度和可解释性。
实际应用场景:
- 增大容量,保持强度:同步增大 r 和 α(如 r: 8→16, α: 8→16)。
- 保持容量,增大强度:只增大 α(如 r=16, α: 16→32)。
- 保持容量,降低强度:只减小 α(如 r=16, α: 16→8)。
🚀 新手起步配置建议
从以下经典配置中二选一,可覆盖90%的微调场景:
python
# 配置一:标准稳定
from peft import LoraConfig
lora_config = LoraConfig(
r=16,
lora_alpha=16, # 比值 = 1.0
target_modules=["q_proj", "v_proj"], # 或 ["q_proj", "k_proj", "v_proj"]
)
# 配置二:效果通常更好,学习更激进
lora_config = LoraConfig(
r=16,
lora_alpha=32, # 比值 = 2.0
target_modules=["q_proj", "v_proj"],
)
💡 补充说明:SFT的局限性
你提供的资料也提到,监督微调(SFT) 最适合利用基座模型已有的知识。若要模型学习完全全新的信息(如未知语言),SFT效果不佳且易产生幻觉,此时建议先进行持续预训练(继续预训练)。
进阶阅读:
Finetuning LLMs with LoRA and QLoRA: Insights from Hundreds of Experiments - Lightning AI