LoRA 微调:低秩适配原理与上手实践
全量微调一个 7B 模型需要多张高端显卡,而 LoRA 让单张消费级显卡微调成为可能。这篇笔记记录它的原理直觉和实践配置。
一、核心思想
研究发现,模型微调时权重的变化量 ΔW 是低秩的——也就是说它包含的有效信息远少于矩阵本身的规模。既然如此,就不必更新完整的 W,而是把 ΔW 分解为两个小矩阵的乘积:
W' = W + ΔW = W + B·A
其中 W 是 d×d,A 是 r×d,B 是 d×r,秩 r ≪ d(常用 8~64)
训练时冻结原始 W,只训练 A 和 B。以 r=16 为例,可训练参数量只有原矩阵的 32/d 倍——7B 模型的 LoRA 适配器通常只有几十 MB。
二、为什么好用
- 省显存:不存全量参数的优化器状态(Adam 要存两份动量,这是显存大头)。
- 可插拔:适配器和基座模型解耦,一个基座可以挂多个不同任务的 LoRA,按需加载。
- 无推理损耗:部署时可以把 B·A 合并回 W,推理速度和原模型完全一致。
三、实践配置要点
from peft import LoraConfig, get_peft_model
config = LoraConfig(
r=16, # 秩,越大能力越强但越容易过拟合
lora_alpha=32, # 缩放系数,一般设为 r 的 2 倍
target_modules=["q_proj", "v_proj"], # 只挂在注意力的 Q、V 上是经典做法
lora_dropout=0.05,
task_type="CAUSAL_LM",
)
model = get_peft_model(base_model, config)
model.print_trainable_parameters()
# 通常显示可训练参数占比不到 1%
四、经验之谈
- 学习率可以比全量微调大一个数量级(如 1e-4 ~ 3e-4),因为可训练参数少。
- 数据质量远比数量重要:几百条精心构造的指令数据,好过几万条噪声数据。
- 任务复杂或数据量大时,把 target_modules 扩展到所有线性层,效果更好。
- 显存还是不够?上 QLoRA:基座模型 4bit 量化 + LoRA,8G 显存也能微调 7B。
一句话总结:LoRA = "原模型别动,我只是在旁边小声补充",用小矩阵的低秩更新替代全量微调,是个人玩家微调大模型的首选方案。