系统学习 AI 学习路径:从 GPU 运行时到推理、微调与 RAG 评估

版本信息最后核对:2026-10-25

training-loss-anomaly

训练 loss 异常的定位:先分清指标算错、数值溢出和训练动力学问题。

现象

训练日志中的 loss 突然变成 nan、inf 或极大的数值,梯度范数同步飙升,优化器开始跳过更新;也可能 loss 始终有限,但长期不降、反复尖峰、训练与验证背离。混合精度训练还常伴随 GradScaler 连续跳过 step、loss scale 一降再降。

分布式训练会放大误判:只打印 rank 0 时,其他 rank 可能早已出现非有限值;各 rank 用未加权平均时,日志 loss 与真实优化目标也不是一回事。被抢占后恢复还可能带来 step 回退、学习率重新 warmup 和曲线跳变。

需要区分三类问题:

  1. 数值真的坏了:前向、反向或优化器更新中出现非有限值,权重被污染,后续 step 全部无效。
  2. 训练动力学变差:数值始终有限,但学习率、batch 语义或数据分布导致不收敛、发散或过拟合。
  3. 指标与日志算错:模型训练正常,只是 loss 的归约方式、采样范围、step 对齐或平滑逻辑有误。

快速判断

先保住现场:记录第一个异常 step、最后一个正常 step、学习率、loss scale、梯度范数、出问题的 rank、全局 batch 配置、数据 shard 与随机种子。再把“第一次异常”与配置变更点对齐:

# 找第一个非有限值,以及它前后的学习率和 scale
python - <<'PY'
import re
bad = []
for i, line in enumerate(open("train.log", errors="ignore"), 1):
    if re.search(r"\b(nan|inf|-inf)\b", line, re.I):
        bad.append((i, line.strip()))
print("non-finite lines:", len(bad))
for item in bad[:20]:
    print(item)
PY

# 对齐学习率、warmup、恢复点和扩卡时间
grep -nE 'lr|learning_rate|scale|grad_norm|resume|world_size' train.log | tail -200

再固定出问题的 batch,分别用训练态、评估态和 fp32 前向复算 loss:都正常则查混合精度、反向或优化器;评估态也异常则说明权重或输入已坏。

回答四个问题:

  1. 从哪一步开始:step 0 异常查初始化、数据、标签和 loss 公式;训练后异常查学习率、数值累积、坏样本和恢复点。
  2. 所有 rank 还是个例:只在一个 rank 出现,先看该 rank 的数据 shard、显存和进程日志;所有 rank 同步异常,先看全局配置和通信后的参数。
  3. 是 NaN 还是无限大:NaN 常来自 0/0、对负数取对数、mask 全空;inf 常来自溢出、除零和过大的学习率。
  4. 看固定 batch:评估 loss 正常而训练日志异常,查指标聚合;两者都异常,按训练故障处理。
线索 更可能的方向
step 0 即 NaN,单卡也复现 数据、标签、loss 公式、初始化
学习率升高或 warmup 结束后开始异常 学习率过大、schedule 配置
混合精度开启后出现 inf,关闭后恢复 loss scale、fp16 溢出、归约精度
扩卡或改梯度累积后曲线突变 全局 batch 语义、学习率未同步调整
只有部分 rank 异常 数据分片、设备、进程退出
恢复 checkpoint 后 step 回退或 loss 跳变 优化器、scheduler、RNG、sampler 状态缺失
评估正常、训练日志异常 指标聚合、日志采样、正则化差异

常见原因

学习率与 warmup

峰值学习率过高是最常见的发散来源。warmup 太短、按 step 与按 epoch 计数混用、恢复后 scheduler 从零开始,都会让实际学习率与预期不符。扩大全局 batch 后学习率调整不当,常表现为前期正常、随后爆炸;每个 micro-batch 都推进 scheduler,也会让梯度累积时的学习率被多推数倍。

数据与标签

输入含 NaN/Inf、解码失败、文本为空、标签越界、padding 未忽略、mask 全为负无穷,都会让 loss 变成非有限值。分片重复或遗漏、最后一个 batch 过小、动态 batch 只剩填充样本,会造成周期性尖峰;离线与在线预处理不一致则让训练和评估分布不同。

混合精度与数值稳定

fp16 动态范围有限,未做 loss scale、scale 初始值过大、梯度裁剪放在 scaler.step 之后、loss 在低精度下归约,都可能产生 inf。bf16 范围更大但精度更低,关键归约仍建议用 fp32;自定义算子与归一化在低精度下计算也容易出问题。

梯度与模型结构

没有梯度裁剪、阈值过大、残差增长、初始化不当、共享参数重复更新,都可能让梯度爆炸。适配器初始化错误、冻结参数仍参与优化,也会改变训练动力学。

分布式 batch 语义

全局 batch 通常等于单卡 batch × 数据并行度 × 梯度累积步数。扩卡后未同步调整学习率和 warmup,原有的步长、梯度噪声和 batch 语义不再等价,可能表现为发散、尖峰或收敛变慢。DDP 默认对梯度求平均,日志若按 micro-batch 简单平均就与优化目标不一致;各 rank 样本数不同又未加权,同样会让日志失真。

指标与日志本身

日志里的 loss 可能是滑动平均、裁剪值或只在部分 step 打印;各 rank 未加权聚合时,样本长度差异会带来明显偏差。训练 loss 含 dropout 与数据增强,评估 loss 不含,本就不应完全重合。重复消费样本或 step 从零计数,也常被误判为退化。

恢复训练与 checkpoint

只恢复模型权重、缺少优化器动量、scheduler、loss scale、RNG 和 sampler,会让恢复后的前几步明显异常。step 与 epoch 对不上时 warmup 可能重跑,学习率跳到错误位置;数据顺序重置还会造成短期重复。

排查步骤

第一步:固定证据与判定标准

保存异常前后的日志、配置、随机种子、checkpoint 路径、全局 batch 算法和数据版本。明确“坏”的定义:非有限值、连续不降还是评估退化。没有统一标准,后续对比就失去意义。

第二步:定位第一个异常 step

不要只看最后一个报错。找出最后一个正常 step 和第一个异常 step,对齐学习率变化、warmup 结束、shard 切换、扩卡、恢复和代码变更。日志没有 step 时先补上再复现。

第三步:用固定 batch 区分指标与训练

固化异常 batch,分别跑训练态、评估态、fp32 和关闭混合精度的前向,比较 loss 与中间激活。评估正常而训练异常,查 dropout、增强、AMP 和反向;fp32 正常而低精度异常,查溢出与归约;全都异常则检查输入和权重。

第四步:定位第一个非有限值

在测试环境用逐层 hook 记录输出和梯度的有限性,找到最早出现 NaN/Inf 的层。torch.autograd.set_detect_anomaly(True) 能定位反向,但会显著拖慢训练,只用于小 batch。逐层梯度范数比总范数更容易找到爆炸来源。

第五步:审计数据与标签

统计各 shard 的样本数、token 长度、空样本比例、标签范围和非有限值;检查 mask、padding、ignore index 与 reduction。再固定一个小 batch、关闭正则化做过拟合测试:loss 降不下去时,优先怀疑标签、mask 或学习率,而不是模型容量。

第六步:审计精度与梯度处理

记录 loss scale、跳过 step 次数和梯度范数;确认 loss 在 fp32 中计算,裁剪在 scaler.unscale_ 之后、scaler.step 之前,scaler.update 每步一次。关闭混合精度后恢复,就保留 fp32 归约和关键归一化,再逐步放开低精度算子。

第七步:审计分布式 batch 语义

算出当前有效全局 batch,与改动前逐项对比;确认学习率缩放、warmup、累积边界、DDP 平均和指标权重。固定数据顺序与种子,用相同全局 batch 做单卡/多卡对照,前若干 step 的差异应在数值误差内。

第八步:审计恢复链路

检查 checkpoint 是否含模型、优化器、scheduler、loss scale、RNG、sampler 与 step。恢复后先用固定 batch 比较 loss、学习率和梯度范数,再连续跑若干 step 看曲线是否连续。缺优化器状态时应视为热启动,而不是无损续训。

第九步:二分与最小复现

每次只改一个变量:单卡单 batch、单卡多 batch、多卡,最后恢复完整配置。优先在测试环境验证学习率、精度和裁剪改动,生产任务保留原 checkpoint,避免排障变成不可回滚的实验。

修复与验证

按根因处理:

验证至少覆盖:

  1. 固定 batch 在关闭 dropout、数据增强等训练态差异后,训练态、评估态与 fp32 的 loss 可比且有限;剩余差异应能由正则化或数值精度解释。
  2. 从异常点之前的 checkpoint 续训,loss、学习率和梯度范数连续,没有跳变。
  3. 连续运行足够长的窗口,非有限值扫描为零,梯度范数在基线范围内。
  4. 单卡与多卡在相同全局 batch 下的曲线可比,评估指标没有退化。

回滚和删除 checkpoint 前先备份;覆盖 best 或唯一可用 checkpoint 属于高风险操作,应只在测试环境或确认有副本时进行。

预防

相关命令

参考链接

读完自测

合上页面,先回答,再展开对照。

  1. 训练日志出现 NaN,但固定 batch 的评估 loss 正常,应该先查什么?
  2. 扩卡后 loss 曲线突然变差,为什么要先核对有效全局 batch 和学习率?
  3. 从 checkpoint 恢复后 loss 跳变,可能缺少哪些训练状态?
答案
  1. 先查指标聚合与日志路径,而不是立刻回滚:确认归约方式、各 rank 加权、采样范围和 step 对齐,再用固定 batch 在训练态和评估态复算。评估正常说明权重大概率没坏,问题更可能在日志、混合精度、反向或优化器。
  2. 扩卡会改变有效全局 batch,进而改变梯度噪声尺度和等效学习率。不同步调整学习率与 warmup,原超参数不再等价,曲线变差并不说明模型或数据坏了。应固定全局 batch 定义,按既定策略调整,并用单卡/多卡对照验证。
  3. 常见缺失包括优化器动量、学习率 scheduler、loss scale、RNG、数据 sampler 与 step/epoch。只恢复模型权重时,优化器状态和训练进度都会重置,恢复后的前几步自然不连续;这类加载应视为热启动,而不是无损续训。
微信小程序码:扫码打开命令速查小程序

小程序版

微信扫码,随时查命令