nan报错

前言

  • 文章来源:CSDN@LawsonAbs
  • 系统环境:torch 1.9.1
  • 遇到nan 的主要排查顺序:(1)先检查主要代码有没有写错?(2)接着看会不会再log,exp()的时候出现计算问题?(3)梯度大小设置是否合理?


20230327更新
这两天写的一个损失函数又报nan了。如下图所示:
在这里插入图片描述
这个nan大概是在20epoch之后才出现,这大抵能说明:我的代码是写的没问题,可能是随着训练的过程,导致某些地方可能出现了问题。众所周知,最有可能出现问题的则是:softmax 和 log 函数两处,那么我看看我的对应处代码,发现如下:
在这里插入图片描述
这里我为了防止除0得到无穷大,所以加了一个self.eps,理论上不会得到inf了。同理,在计算log值的时候,也是用到了self.eps。但是为啥还有问题呢?于是我看了看我的eps值为1e-10。然后执行一下上面这个操作,竟然发现sim的值为inf!
在这里插入图片描述
这说明eps取值太小,导致没有什么作用!故修改即可。
总结便是:eps 取值过小没有作用,导致最后防止除0操作时失败!


1. 场景1

前几天在写一段代码的时候,遇到了nan错误,但是一直么有找到问题所在。我的代码主要是将一个 batch 中的entity对应的 embedding 送到自定义的2层BertModel中。

原因

  • 送入到BertModel中仅传入了 hidden_states,没有传入attention_mask。但是后来搞定这个bug之后还是有nan值的村子。
  • 于是按行debug,发现问题在于送入到BertEncoder中的 hidden_states 中有nan的存在。
    我们可以用下面这行代码检查tensor中是否有nan 值。
    torch.any(torch.isnan(entity_bank)) 这个 entity_bank 便是一个待检测的向量。于是对应解决这个nan值的生成即可。
    但奇怪的是,使用下图中注释的一行就会有nan 的问题,但是用第二行代码则没有这个问题。
    在这里插入图片描述

2. 场景2

最近在写一个自定义的损失函数,形式如下:
在这里插入图片描述
其中的L1 是正样本的损失,L2是负样本的损失。

原因

训练过程中再次出现nan,后来发现原因是:上式中的 log(*) 中的值可能存在0,我是先对0求了log,然后过滤掉了inf值,但是事实证明这么做是不行的。最好的方式是:

eps=1e-7
log(x+eps)

从而避免nan值的产生。

3. 场景3

nan最近真的是粘上我了 ┭┮﹏┭┮
短短几天,碰到了3次nan报错,而且每次都不一样。今天(2021/12/18)这次碰到的情况是模型训练到了一定的epoch时就开始出现nan。如下所示:

在这里插入图片描述
因为已经到了第50epoch,所以我就怀疑是梯度的问题了。如果是脏数据的问题,那么应该在一个epoch之内就会报错。从网上查阅资料,感觉像是因为梯度爆炸导致的nan错,于是我调整了一个动态学习率,就没有再报这个错了。
如果是自己手写的loss,那么一定要保证最后得到的loss是一个均值,要么是除以batch_size,要么是除以样本条数,因为这个系数在求导的时候,就会被带到其中作为梯度的系数,这样就会把梯度降下来。

4. 场景4

因为代码bug导致的nan。
我在使用 R-Drop 的时候,需要使用KL散度求两个 predict logit 间的距离,pytorch中的 kl_div 函数有个参数说明如下:
在这里插入图片描述
这个参数:表示传入的 target 是否是在log空间下(即是否由log处理过),推荐传入固定的分布结果,(如softmax)避免由log导致的数值问题。

5. 场景5

还有一种常见的nan报错是 除零导致的错。如下所述:
背景:同一个entity可以对应多个mention,但是我想取这个entity的表示,就可以通过取各个mention表示的平均来获取。最后除以这个mention的个数即可。
于是我这么写了代码:

cur_entity_emb = torch.mm(cur_entity2mention,x) / torch.sum(cur_entity2mention,dim=1).unsqueeze_(1).expand(-1,808) # 拿到整个entity的表示

得到的这个 cur_entity_emb 中存在nan,那么罪魁祸首应该就是后面的这个 torch.sum()存在问题,果不其然,查了一下的确是这个的问题。

6. 场景6

还是之前那个损失函数(如下图所示)
在这里插入图片描述
实现过后,代码在epoch 35 - epoch 40 之间总会报一个nan错,但是epoch 不固定,看看具体的报错信息:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
发现这些报错信息下,都有一个常见的情况,那就是 NA acc 的准确率已经到了0.98-0.99 了,那这个跟报错有关系吗?于是我尝试将负样本损失单独训练,果不其然,在仅使用 loss_neg 下训练模型,发现不到10 step 损失就报nan !震惊,原来问题出现在负样本的损失上!
经仔细发现,原来是我负样本的损失在一定epoch的学习下就变成了0,显然这是不大可能的啊,针对情况改代码就可以了吧。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

说文科技

看书人不妨赏个酒钱?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值