何时需要全参数微调
大多数场景 LoRA/QLoRA 已经足够,但以下情况考虑全参数微调:
- 需要从根本上改变模型的"世界观"(语言、领域)
- 持续预训练(Continual Pretraining)在新语料上
- LoRA 效果达到瓶颈,评估指标不再提升
- 数据量 > 10 万条,充分利用大数据集
- 追求最高精度,不关心显存成本
DeepSpeed ZeRO:分割显存压力
ZeRO Stage 1 — 分割优化器状态
Adam 优化器状态(momentum、variance)分散到各 GPU,每张 GPU 显存减少约 4×(8 GPU)。梯度和参数仍然每卡一份。
ZeRO Stage 2 — 分割梯度 + 优化器状态
在 Stage 1 基础上,梯度也分散存储。总节省约 8×(8 GPU)。训练速度基本不受影响,是多数场景的推荐选择。
ZeRO Stage 3 — 分割参数 + 梯度 + 优化器
模型参数本身也分散存储。总节省约 64×(8 GPU)。但 forward 需要 all-gather 参数,通信开销较大。适合极大模型(70B+)。
DeepSpeed 配置
{
"zero_optimization": {
"stage": 2,
"overlap_comm": true,
"contiguous_gradients": true,
"sub_group_size": 1e9,
"reduce_bucket_size": "auto",
"stage3_prefetch_bucket_size": "auto",
"stage3_param_persistence_threshold": "auto",
"gather_16bit_weights_on_model_save": true
},
"bf16": {"enabled": true},
"gradient_clipping": 1.0,
"train_micro_batch_size_per_gpu": 4,
"gradient_accumulation_steps": 4
}
启动多 GPU 训练
# 单机 8 GPU 训练
deepspeed --num_gpus=8 train.py \
--deepspeed ds_config.json \
--model_name_or_path meta-llama/Meta-Llama-3-8B \
--dataset_path data/train.jsonl \
--output_dir ./output \
--num_train_epochs 3
# 或使用 torchrun(FSDP)
torchrun --nproc_per_node=8 \
--master_addr="localhost" \
--master_port=29500 \
train_fsdp.py
FSDP vs DeepSpeed 选择
| 特性 | FSDP | DeepSpeed ZeRO |
|---|---|---|
| 来源 | PyTorch 原生 | 微软独立库 |
| 集成难度 | 较简单 | 需要配置 JSON |
| HuggingFace 集成 | Trainer 原生支持 | 需要 deepspeed 库 |
| 多机支持 | 好 | 好 |
| CPU Offload | 有限 | 强大(可卸载到 CPU/NVMe) |
| 推荐场景 | 单机多卡,7B-30B | 多机多卡,30B+ |
全参数微调训练技巧
使用更低的学习率
全参数微调的学习率通常比 LoRA 低 10 倍:1e-5 到 5e-5。过高学习率会"灾难性遗忘"预训练知识。
Flash Attention 2
安装 flash-attn 可将 Attention 计算速度提升 2-4 倍,显存降低 50%。这是全参数微调的必选项。
混合精度 BF16
使用 BF16 而不是 FP16。BF16 数值范围更大,不容易出现 loss scaling 相关的训练不稳定问题。
本章小结
全参数微调适合大数据集和极高精度要求。ZeRO Stage 2 是多数场景的最佳起点,Flash Attention + BF16 是标配优化。下一章进入 DPO 偏好对齐训练。