loss不下降时首要检查optimizer.zero_grad()是否每步都调用,否则梯度累积导致更新混乱;其次排查学习率是否合理、反向传播是否生效、loss计算是否正确、数据加载是否异常。

loss不下降时先确认 optimizer.zero_grad() 是否真被调用
很多情况下 loss 卡住不动,不是模型问题,而是梯度没清零导致梯度累积,loss.backward() 算出来的梯度叠加在旧梯度上,更新方向混乱。最典型的表现是 loss 在几个值之间来回跳,或完全不变。
常见错误写法:
for epoch in range(10):
for x, y in dataloader:
pred = model(x)
loss = criterion(pred, y)
loss.backward()
optimizer.step() # ❌ 没有 zero_grad()
检查点:
- 确认
optimizer.zero_grad()出现在loss.backward()之前,且每轮 iteration 都执行一次 - 如果用了梯度裁剪(
torch.nn.utils.clip_grad_norm_),它不会自动清梯度,zero_grad()仍需显式调用 - 多卡训练(
DDP)下,zero_grad()依然有效,但别误写成只在 rank 0 调用——它必须每个进程都调
学习率设太高或太低都会让 loss 不动
学习率不对,loss 可能爆炸、震荡、缓慢下降甚至完全停滞。不能只看“有没有设”,要看数值是否落在合理区间,以及是否适配当前优化器和初始化方式。
立即学习“Python免费学习笔记(深入)”;
实操建议:
- 从
1e-3开始试Adam,SGD建议从1e-2或更低(尤其没加 BN 时) - 如果 loss 第一轮就
nan或暴涨,大概率是学习率 >1e-2(Adam)或 >1e-1(SGD),立刻降一个数量级 - 如果 loss 下降极慢(比如 100 个 epoch 才降 0.01),尝试把学习率 ×2~×5;若仍无改善,检查是否忘了归一化输入(
x /= 255.0漏写很常见) -
lr_scheduler过早启用(如 warmup 阶段没过就进入 decay)也可能导致实际 lr 快速掉到 1e-6 以下,用print(optimizer.param_groups[0]["lr"])实时确认
loss 不下降还可能是反向传播根本没生效
loss 值正常打印、backward() 也调了,但模型参数纹丝不动——说明梯度没传到可训练参数上。这是静默失败,比报错更难察觉。
排查路径:
- 检查 loss 是否依赖模型输出:比如误写成
loss = criterion(pred.detach(), y),.detach()切断了梯度流 - 确认模型参数在
optimizer中:打印len(list(model.parameters()))和sum(p.numel() for group in optimizer.param_groups for p in group["params"]),二者应一致 - 验证梯度是否生成:训练循环里加一句
print(model.layer1.weight.grad is not None)(选一个中间层),True才算走通 - 用了
torch.no_grad()包裹整个 forward?或者不小心在model.eval()模式下训练(BN 层冻结、Dropout 失效,间接影响 loss 曲线)
验证 loss 计算逻辑本身是否可靠
有时候 loss 不下降,是因为你压根没在优化目标函数。比如分类任务用了回归 loss,或 label 维度/类型不匹配导致 loss 始终返回常数。
关键检查项:
-
criterion输入 shape 是否对齐:例如nn.CrossEntropyLoss要求pred是[N, C]、y是[N]且 dtype=torch.long;若y是 one-hot,会静默返回巨大常数 loss - 自定义 loss 里用了
.item()或.numpy()提前取值,导致计算图断裂 - loss 被
torch.mean()或torch.sum()错误聚合:比如 batch 内样本权重不均,或 reduction 设为"none"后没再 mean,导致 scaler loss 值异常小 - 数据加载出错:所有
y都是同一个值(label 文件读错、transform 顺序颠倒),loss 天然无法下降
最省事的验证动作:拿一个 batch 数据,手动跑一次 forward + backward,然后 print(loss.item()) 和 print([p.grad.norm().item() for p in model.parameters() if p.grad is not None]) —— 如果 grad 全是 0 或 nan,问题一定出在数据、loss 或计算图链路上。


















