一、问题背景:为什么不用全量微调?

我手头有个项目需要把法院判决书自动压缩成“案情摘要+裁判要点”。基座选了Qwen2.5-7B-Instruct,零样本测试时发现它能理解案情,但输出结构混乱——经常把“本院认为”部分漏掉,或者自己编造法条。

直接全量微调?7B模型用AdamW优化器,仅梯度就要占28GB显存(7B×4字节),加上激活值,两张3090(24GB×2)根本塞不下。用DeepSpeed ZeRO-3倒是能跑,但配置复杂,而且我只需要微调最后几层,全量更新70亿参数纯属浪费。

所以锁定LoRA——冻结原模型,只训练低秩分解矩阵。理论上显存需求能降到原来的1/3左右。

二、环境与版本:先踩个CUDA坑

我的环境:
- Ubuntu 22.04,两张RTX 3090(单卡24GB)
- CUDA 12.1,PyTorch 2.1.2
- transformers 4.38.2,peft 0.9.0,bitsandbytes 0.43.1
- 模型:Qwen/Qwen2.5-7B-Instruct (torch_dtype=bf16)

坑1:bitsandbytes在CUDA 12.x下需要0.43+版本,旧版0.41会报libcudart.so: cannot open shared object file。如果你用conda,直接conda install -c conda-forge bitsandbytes不会升级到最新,必须pip install。

坑2:transformers 4.38.2加载Qwen2.5会警告token_type_ids问题,但不影响使用。如果你遇到KeyError: 'qwen2',说明transformers版本低于4.37,升级即可。

三、方案设计:LoRA还是QLoRA?

先看显存预算分析:

方案 参数量 训练显存(估算) 训练速度(tokens/s)
全量微调 7.6B >60GB(需张量并行) -
LoRA(rank=8) 18M ~26GB 1800
QLoRA(NF4) 18M ~11.5GB 1500

LoRA方案在单卡3090上的理论峰值是26GB,但实际跑起来激活值波动大,偶尔会飙到27-28GB。QLoRA引入4bit NF4量化,把原始权重压到0.5字节/参数,节省约(7.6B-18M)×(2-0.5)≈11.4GB。

我最终选了QLoRA,理由:
1. 两张卡可以跑更大的batch,或者用其中一张做验证集推理
2. 18%的速度损失换2.3倍显存余量,值得
3. NF4量化对LoRA微调效果影响=48GB,追求效果 | LoRA(rank=16)足够,避免量化带来的精度损失 |
| 微调3B以下模型 | 全量微调也不怕,没必要折腾LoRA |
| 推理部署 | 用AWQ/GPTQ 4bit量化,比QLoRA训练后直接推理快 |

最终建议:QLoRA能让你在消费级显卡上微调7B模型,代价是训练速度慢18%左右,效果损失在可接受范围。如果追求极致效果且预算充足,LoRA+BF16是更好选择。另外,adapter文件只有38MB,比原模型7.6B小了200倍,部署时只需要分发adapter,基座模型用vLLM预加载,爽到飞起。

下次遇到长文本分类任务,我打算试试LoRA+LoRA的堆叠方案,有结果再分享。