经验驱动。微调前先算账——很多人显存爆了都不知道钱花在哪。下面是我本机按真实公式算出来的 7B 显存账,以及 27B 本机实战的踩坑。数字都是算出来的,不是拍脑袋。

先算账:7B 模型到底吃多少显存

以 bf16 精度、7B 参数为基准,显存主要由四块构成:基座权重 + 优化器状态 + 梯度 + 激活值。前三项只和参数量有关,先算清楚:

部分计算显存
基座权重(bf16)7e9 × 214.00 GB
全量微调·优化器(AdamW)7e9 × 1284.00 GB
全量微调·梯度7e9 × 214.00 GB
全量微调合计112.00 GB

关键认知:全量微调的显存大头不是权重,是 AdamW 的优化器状态(fp32 主副本 + 一阶矩 m + 二阶矩 v,共 12 字节/参数)。所以 7B 全量微调要 112GB,单卡 80GB(A100)都吃紧。

LoRA 把账砍到哪了

LoRA 的核心思想:不训全量权重,只在权重旁挂一对低秩矩阵 A(r×d)、B(d×r),只训 A、B。以 r=8、目标模块 224 个(LLaMA 类每层 q/k/v/o/gate/up/down × 32 层)为例:

  • 可训练参数 = 2 × r × hidden(4096) × 224 ≈ 14.7M,仅占 7B 的 **0.21%**;
  • 优化器和梯度也只给这 14.7M 参数,基座冻结;
  • LoRA 总显存(bf16 基座)= 14(基座)+ 0.18(LoRA 优化器+梯度)≈ 14.21 GB。

QLoRA:再把基座压到 4bit

如果连 14GB 都没有(比如我本机只有 12G 显存),用 QLoRA 把基座量化为 4bit:

  • 基座 4bit = 7e9 × 0.5 = 3.5 GB;
  • QLoRA 总显存 ≈ 3.5 + 0.18 ≈ 3.71 GB。

实测算出来的对比:

1
2
3
4
5
基座权重(bf16)        :  14.00 GB
全量微调 总显存 : 112.00 GB (训练参数 7.0B)
LoRA 可训练参数 : 14.7 M (0.210% of 7B)
LoRA 总显存(bf16基座) : 14.21 GB
QLoRA 总显存(4bit基座) : 3.71 GB

27B 本机实战踩坑

我本机是 12G 显存,跑 27B 模型的相关实验时踩过这些:

  1. 12G 只能 QLoRA(r≤8)+ gradient_checkpointing。27B 基座 bf16 就要 54GB,全量微调更是不敢想——按上面的公式,27B 全量微调轻松破 430GB,得 8 张 A100 量级。
  2. 量化省的是基座,LoRA 参数仍是 bf16。QLoRA 的省显存上限就是基座那部分,别指望靠调 r 把 4bit 模型再省一截。
  3. 激活值显存随 batch × 序列长度涨。长文本(几 K context)比短文本吃好几倍显存,控制 max_seq_length 和 per_device_train_batch_size 是直接有效的手段。
  4. gradient_checkpointing 用时间换显存。约多 30% 训练时间,但能省下一大块激活显存,12G 卡基本必开。
  5. PagedAdamW(bitsandbytes)能缓解峰值。它把优化器状态分块驻留,避免瞬时 OOM,QLoRA 默认走这个。

面试常考点

  • LoRA 原理:对权重 ΔW 做低秩分解 ΔW = BA,B∈ℝ^{d×r}, A∈ℝ^{r×k},r≪d,训练参数量从 d×k 降到 r×(d+k)。
  • 为什么 QLoRA 能在消费级卡跑大模型:基座 4bit 量化 + 只训 LoRA + 分页优化器,三者叠加。
  • rank 怎么选:r 太小欠拟合、太大失去低秩意义且显存涨;常见 8/16/32/64,配合 α(通常 2r)。
  • 显存构成:权重 + 优化器 + 梯度 + 激活,优化器(AdamW)是很多人忽略的大头。

小结

微调不是 lora=True 点一下就行。先把显存账算明白:全量微调的 112GB 里优化器占 84GB,LoRA 靠只训 0.21% 的参数把账砍到 14GB,QLoRA 再压到 3.7GB。本机 12G 只能走 QLoRA + 梯度检查点的组合拳,这些数字是真算出来的,面试时能直接摆。