大模型后训练:SFT 之 Full Fine-Tuning、LoRA、QLoRA
1. 全量微调 (Full Fine-Tuning)
假设要微调一个 8B 模型,
- 权重矩阵:比如是一个 4096 × 4096 的矩阵。
- 全量微调:意味着你要更新这 4096 × 4096 个参数里的每一个数字。
- 显存爆炸:你需要存储 权重(Weight) + 梯度(Gradients) + 优化器状态(Optimizer States, AdamW需要存两份) + 激活值(Activations) + 临时缓冲区(Temp Buffers)。对于 8B 模型,这通常需要 100GB 甚至更多的显存。
⼤模型后训练任务的显存主要部分组成:
- 模型参数显存:Qwen ⼤模型的精度的⼀般为 BF16,BF16=16bit=2byte,所以Qwen3-8B模型部分⼤约占⽤ 8×2byte×1000^3/1024/1024/1024 约等于 16GB。
- 梯度显存:BF16 训练时:每个梯度占 2 字节 8e9 × 2 bytes = 16 GB。
- 优化器状态显存(以 Adam 优化器为例):一阶动量(Momentum,历史梯度的平均)和二阶动量(Variance,历史梯度的方差),每个参数需 8 字节(FP32)8e9 × 8 bytes = 64 GB。
- 激活值与临时缓冲区:⼀般与批次⼤⼩(batch size)、序列⻓度相关,通常需额外 15-20 GB(以实际训练配置为准)。
综上,Qwen3-8B模型全参SFT训练所需的基础显存需求总和预估为:
16 GB(模型) + 64 GB(优化器) + 16 GB(梯度) + 20 GB(激活值)≈ 116 GB
全参微调速算系数:
在资源充⾜的情况下,可以以【参数量⼤⼩ × 16】的⽅式估算显存占⽤(以 BF16 精度为例,若是 FP8 则是 12 倍)
2. LoRA (Low-Rank Adaptation)
核心思想:装饰器模式 (Decorator Pattern) + 矩阵分解
LoRA 认为:大模型虽然很大,但当你微调它去做特定任务时,需要改变的参数其实并不多,而且主要集中在某些特定的“方向”上(低秩)。
实现逻辑
- 冻结 (Freeze):把原本的大矩阵 W 锁死,不准动。
- 旁路 (Bypass):在旁边挂两个非常小的矩阵 A 和 B。
- 假设 W 是 d × d (比如 4096 × 4096)。
- 定义一个秩 (Rank) r,比如 r = 8 (非常小)。
- 矩阵 A 的形状是 d × r (4096 × 8)。
- 矩阵 B 的形状是 r × d (8 × 4096)。
- 计算:
- 原本的输出:h = W ⋅ x
- LoRA 的输出:h = W ⋅ x + ΔW ⋅ x = W ⋅ x + (B⋅A) ⋅ x
为什么省显存?
- 参数量骤减,只有原来的 1/250:
- 原矩阵参数:4096 × 4096 ≈ 16, 000, 000 个。
- LoRA 参数:4096 × 8 × 2 ≈ 65, 000 个。
- 梯度只需传给 A 和 B:大矩阵 W 不需要梯度,也不需要存优化器状态。这就把显存需求砍掉了一大半。
3. QLoRA (Quantized LoRA)
核心思想:LoRA 还是嫌太贵,把“地基”也给压缩了
LoRA 虽然省了梯度的显存,但原始的 (底座模型)依然要占显存。 如果 70B 的底座加载进来就要 140GB (FP16),你只有 24GB 显卡,连 LoRA 都跑不了。
QLoRA = 4-bit 量化底座 + LoRA + 分页优化器
QLoRA 的三个关键黑科技:
- 4-bit NormalFloat (NF4) 量化:
- 把那个锁死的底座矩阵 W,用 NF4 算法压成 4-bit。
- 效果:70B 的模型底座只需要 35GB 显存,直接砍到 1/4。
- 混合精度计算 (Mixed Precision Compute):
- 存储时:底座是 4-bit,LoRA 适配器 (A, B) 是 16-bit (BF16/FP16)。
- 计算时 (Forward Pass):
- 数据 x 来了 (BF16)。
- 把 4-bit 的 W 里的相关部分,临时解压成 BF16。
- 计算 W ⋅ x。
- 计算完把解压后的 BF16 丢掉,只保留结果。
- 同时计算 LoRA 的 (B⋅A) ⋅ x。
- 把两边的结果相加。
- 反向传播 (Backward Pass):梯度只传给 A 和 B。底座 W 依然是冻结且量化的。
- 分页优化器 (Paged Optimizers): 如果在训练过程中显存偶发性不够用了,QLoRA 允许把优化器的状态(Optimizer States)自动换页(Offload)到 CPU 内存里去,等需要更新参数时再拷回 GPU。哪怕慢点,也能保证不 OOM。
4. 总结对比:Full vs LoRA vs QLoRA
假设我们要微调 8B 模型(FP16):
| 特性 | Full Fine-Tuning | LoRA | QLoRA |
|---|---|---|---|
| 底座模型状态 | 可训练 (FP16/FP32) | 冻结 (FP16) | 冻结 (Int4) |
| 适配器 () | 无 | 可训练 (FP16) | 可训练 (FP16) |
| 显存需求 (8B) | > 100 GB ❌ | ≈ 20-24 GB ✅ | ≈ 6-10 GB ⚡️ |
| 计算速度 | 最快 (无反量化开销) | 快 | 稍慢 (需要解压 4-bit) |
| 微调效果 | 理论上限最高 | 接近全量 (98%+) | 接近 LoRA (微乎其微的损失) |
| 硬件门槛 | A100 (80G)×2 | RTX 3090/4090 (24G) | RTX 3060/4060 (12G) |
大模型后训练:SFT 之 Full Fine-Tuning、LoRA、QLoRA
https://www.haoyizebo.com/posts/f9ed9460/