大模型训练出现NaN怎么办?梯度异常定位与修复实战

发布时间:2026/11/4 2:34:17
大模型训练出现NaN怎么办?梯度异常定位与修复实战

大模型训练过程中,Loss突然变成NaN或Inf,是GPU服务器租用项目里最棘手的异常之一。GPU算力平台资源本身可能完全正常,真正原因可能来自脏数据、学习率、混合精度溢出或自定义算子。

一、问题背景

深度学习训练存在长链路:数据预处理、前向计算、损失函数、反向传播、优化器更新,任一环节出现非有限值都会向后扩散。若只降低学习率,可能暂时隐藏问题,却无法解释为何同一批次反复失败。到了推理部署阶段,异常权重还可能输出无效概率。因此,AI算力平台上的训练任务应建立可重复的NaN定位流程。

二、环境准备

准备可复现的训练脚本、固定随机种子、最近一次正常检查点和小规模样本。先在独立分支排查,不要覆盖原权重。

importrandom,numpyasnp,torch seed=2026random.seed(seed)np.random.seed(seed)torch.manual_seed(seed)torch.cuda.manual_seed_all(seed)

同时记录代码提交号、镜像Digest、GPU型号、框架版本和启动参数。

三、实操步骤

1. 确认首次异常位置

在损失计算后立即检查:

ifnottorch.isfinite(loss):print("bad loss",step,loss.detach().cpu())raiseRuntimeError("non-finite loss")

不要继续执行优化器更新,否则错误参数会写入后续检查点。

2. 检查输入与标签

defcheck_tensor(name,x):iftorch.is_tensor(x):asserttorch.isfinite(x).all(),f"{name}has NaN/Inf"print(name,x.dtype,x.min().item(),x.max().item())check_tensor("input",batch["input"])check_tensor("label",batch["label"])

保存问题样本索引和预处理参数,避免记录敏感原始数据。分类任务还需确认标签是否越界,回归任务应关注极端值。

3. 打开异常检测

withtorch.autograd.detect_anomaly():loss.backward()

它会降低速度和增加内存,只适合最小复现,不建议在完整训练中长期启用。根据堆栈定位第一个产生非有限梯度的算子。

4. 统计梯度范围

forname,pinmodel.named_parameters():ifp.gradisNone:continueifnottorch.isfinite(p.grad).all():print("bad grad:",name)breakprint(name,p.grad.norm().item())

如果梯度范数持续增大,可尝试梯度裁剪,但应先确认损失函数、数据尺度和学习率是否合理。

5. 核对混合精度流程

使用AMP时,应通过GradScaler处理缩放:

scaler.scale(loss).backward()scaler.unscale_(optimizer)torch.nn.utils.clip_grad_norm_(model.parameters(),1.0)scaler.step(optimizer)scaler.update()optimizer.zero_grad(set_to_none=True)

裁剪前要先unscale_。若关闭AMP后错误消失,继续检查不稳定算子和精度转换,而不是永久退回低效率配置。

6. 回放问题批次

将异常批次单独保存为脱敏后的最小测试输入,从最近正常检查点重复运行。逐步关闭数据增强、自定义算子和复杂损失项,找出最小触发条件。

7. 验证修复效果

用相同种子、相同批次和相同参数运行多次,记录Loss、梯度范数和显存。大模型训练修复不能只看“跑过一个step”,还应覆盖足够窗口并验证检查点可加载。

四、常见问题与解决方案

1. 降低学习率后不再NaN

这说明更新幅度可能参与触发,但仍需检查数据尺度、损失函数和梯度变化,不能直接结束排查。

2. 只有AMP模式报错

定位对低精度敏感的算子,检查GradScaler使用顺序,并对必要计算局部使用更高精度。

3. 每次异常批次不同

检查随机增强、并发数据加载、未固定种子和非确定性算子,同时保存样本索引。

4. 恢复检查点后立即NaN

检查该检查点是否已包含异常参数,并回退到更早的正常版本。

五、总结

NaN排查要从首次异常入手,依次验证输入、前向结果、梯度、AMP和问题批次。建立可回放样例比盲目改参数更有效,也能保护深度学习实验与推理部署的结果可靠性。

FAQ

Q1:梯度裁剪能彻底解决NaN吗?

不能,它只能限制梯度范数,无法修复脏数据或错误算子。

Q2:detect_anomaly为什么不建议长期开启?

它会显著降低训练速度并增加资源消耗,适合调试阶段。

Q3:出现NaN后还能继续保存检查点吗?

不建议,应停止更新并保留最近正常检查点及异常批次信息。

Q4:需要更换GPU吗?

先完成软件和数据排查;只有结合硬件日志发现异常时,才进入设备诊断。