训练出现了nan的排查血泪

模型训练一开始好好的,前几轮也好好的,突然,loss出现了nan,我的模型准确率本来都很高了,啪地跌到了0.

排查1:可能是数据集有问题。经过更换100%没问题的数据集之后,nan问题仍然出现

排查2:通过调试,发现计算loss之前的模型输出全是nan,啊啊啊

             网上有说lr过大导致参数nan,有除0 log0 等无效计算导致nan,也有说梯度爆炸导致更新模型参数有了nan。

             我觉得我的lr没问题,也没有无效计算的情况,所以我猜测是梯度爆炸。我尝试了如下的代码,放在更新参数之前。意外之喜是 它能使得我的模型加速收敛,准确率噌噌噌提高!!!

torch.nn.utils.clip_grad_norm_(model.parameters(), 5.0)

but,nan依旧!!

排查3:我只能用下面的代码+断点排查nan在哪

if torch.isnan(grasp_cos_out).any() or torch.isinf(grasp_cos_out).any():
    assert True

奈何复现一次nan出现需要等很久,我很难受。于是我去学习一位老哥的钩子函数方法来排查。形成的成果见我的上一篇文章

扑朔迷离的情况:我发现在一个卷积输出全是nan,是全是nan,而输入是"正常的"(后来发现,应该是混有了nan), 我百思不得其解,卷积不就是对应相乘相加,也不可能出现nan啊。

我看了看输入输出dtype,是torch.float16! 精度范围只有1e-8 最大最小值只有6.5w。我怀疑会不会是卷积相乘相加溢出了?我又看了一眼nan出现时的输入,它几乎都是0,难道是计算结果太接近0,然后下溢了?

经过测试,发现计算结果只可能趋于0,而不会到+-6.5w,所以不是上溢出,下溢出是小数直接没有了,变为0,然而这是成了nan。

我寻思到底是不是torch.float16的问题。我想方设法将卷积计算那一块 变成torch.float32进行计算,发现nan依旧。啊啊啊!!!。我干脆把amp.auto_cast()注释掉,哈模型显存占用量直接翻倍,计算速度也慢了很多。但是!!nan一直都没有出现!!!

最后的曙光:经过关闭amp,我认为很可能就是torch.float16的问题!!!但是把卷积那里修改成32类型,nan依旧出现。

我认真想了想之前的钩子代码排查出来的nan出现的地方:包括BatchNorm、ReLU。BatchNorm要求mena和方差,要求和,很可能会上溢出。我发现确实中间的输入有10这个级别的数字,我估计就是BatchNorm没准了。 

欧耶!我猜中了!BatchNorm换成了32类型进行计算,没有问题!!!!!!!!

总结:

        问题根源:amp混合精度计算,使用fp16的精度计算batch_norm 导致nan

参考:预训练模型输出nan的问题解决方法-优快云博客

但是后面 batch_norm还是nan了,于是我只能删掉这个batch_norm了,然后就,没有问题了!!!

参考:警惕!损失Loss为Nan或者超级大的原因-腾讯云开发者社区-腾讯云

### 深度学习训练中 Loss 出现 NaN 并且 Training Accuracy 低于 Validation Accuracy 的解决方案 #### 学习率调整策略 在 warmup 阶段后的训练过程中,采用适当的学习率衰减策略有助于提升模型性能并防止数值不稳定。如果学习率过高可能导致梯度爆炸,进而使损失函数变为 NaN 值[^1]。 ```python from torch.optim.lr_scheduler import StepLR scheduler = StepLR(optimizer, step_size=30, gamma=0.1) for epoch in range(num_epochs): train(model_engine, data_loader_train, optimizer) validate(model_engine, data_loader_val) scheduler.step() ``` #### 训练循环优化 Deepspeed 提供了一套标准的训练流程,该流程与 PyTorch 类似但有所改进。确保按照 Deepspeed 推荐的方式实现前向传播、反向传播以及参数更新操作能够有效减少潜在错误的发生概率[^2]。 ```python for step, batch in enumerate(data_loader): # Forward pass loss = model_engine(batch['input'], batch['target']) # Backward pass and optimization model_engine.backward(loss) model_engine.step() # Optional: Gradient clipping to prevent exploding gradients torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0) ``` #### 数据预处理与正则化技术应用 为了获得更好的泛化能力,在输入特征层面实施标准化或其他形式的数据增强措施至关重要;同时引入 L2 正则项或 dropout 层来抑制过拟合现象也十分必要。这不仅提高了测试集上的表现,还可能间接改善了训练过程中的稳定性[^3]。 ```python import torchvision.transforms as transforms transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize(mean=[0.485], std=[0.229]) ]) class Net(nn.Module): def __init__(self): super(Net, self).__init__() ... self.dropout = nn.Dropout(p=0.5) def forward(self, x): out = F.relu(self.fc1(x)) out = self.dropout(out) return self.fc2(out) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值