最近在复现一个图像分割的模型,用PyTorch写的时候训练到第3个epoch左右loss突然变成NaN了,梯度也炸了。我检查了学习率、数据归一化都没啥问题,同样的网络结构和超参换成TensorFlow跑就稳稳的,loss正常下降。这就让我很困惑了,难道PyTorch在某些算子上默认行为跟TF不一样?比如除零保护或者梯度裁剪的默认值?有没有人遇到过类似情况,一般从哪入手排查啊?感觉自己对框架底层还是理解太浅了……
楼主
23天前
PyTorch训练时loss突然变NaN,换TensorFlow就没问题,是框架的坑吗?
请 登录 后发表回复
全部回复
共 3 条
2楼
23天前
我之前也踩过这个坑,说实话大概率不是“PyTorch的坑”,而是两边默认行为确实有些细节不一样。比如PyTorch里很多算子对NaN是“传播式”的,一旦某个batch出现异常值就会顺着梯度把整个网络带崩,而TF某些实现里会对梯度做隐式处理或者数值更稳一点。你可以先查一下是不是混合精度、BN的eps、或者某个自定义loss里做了log/div没加epsilon。另外建议开torch.autograd.set_detect_anomaly(True)跑一遍,通常能定位到具体是哪一层先出的问题,比盲猜学习率有用得多。还有个容易忽略的点是数据里有没有极端值或空mask,分割任务里这类脏数据在TF那边可能被静默处理了,PyTorch就直接给你炸出来。所以与其说是框架坑,不如说是PyTorch更“诚实”地把数值问题暴露了。
3楼
21天前
先查查有没有sqrt或log,PyTorch对负数默认出NaN,TF可能悄悄加了eps。
4楼
20天前
我之前也踩过这个坑,PyTorch的默认初始化和TF不太一样,特别是卷积层和BN的初始化策略有差异,同样的学习率下PyTorch可能前期梯度就是更容易爆。建议先试试加梯度裁剪,torch.nn.utils.clip_grad_norm_设个1.0,再不行就把学习率再降一个量级看看。另外检查下有没有用到除零或者log(0)的地方,PyTorch不会自动帮你加eps,TF有些算子内置了保护。