赞
踩
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操作时失败!
前几天在写一段代码的时候,遇到了nan
错误,但是一直么有找到问题所在。我的代码主要是将一个 batch
中的entity对应的 embedding
送到自定义的2层BertModel中。
torch.any(torch.isnan(entity_bank))
这个 entity_bank
便是一个待检测的向量。于是对应解决这个nan值的生成即可。最近在写一个自定义的损失函数,形式如下:
其中的L1 是正样本的损失,L2是负样本的损失。
训练过程中再次出现nan,后来发现原因是:上式中的 log(*)
中的值可能存在0,我是先对0求了log,然后过滤掉了inf值,但是事实证明这么做是不行的。最好的方式是:
eps=1e-7
log(x+eps)
从而避免nan值的产生。
nan最近真的是粘上我了 ┭┮﹏┭┮
短短几天,碰到了3次nan报错,而且每次都不一样。今天(2021/12/18)这次碰到的情况是模型训练到了一定的epoch时就开始出现nan
。如下所示:
因为已经到了第50epoch,所以我就怀疑是梯度的问题了。如果是脏数据的问题,那么应该在一个epoch之内就会报错。从网上查阅资料,感觉像是因为梯度爆炸导致的nan错,于是我调整了一个动态学习率,就没有再报这个错了。
如果是自己手写的loss,那么一定要保证最后得到的loss是一个均值,要么是除以batch_size
,要么是除以样本条数
,因为这个系数在求导的时候,就会被带到其中作为梯度的系数,这样就会把梯度降下来。
因为代码bug导致的nan。
我在使用 R-Drop 的时候,需要使用KL散度求两个 predict logit
间的距离,pytorch中的 kl_div 函数有个参数说明如下:
这个参数:表示传入的 target
是否是在log
空间下(即是否由log处理过),推荐传入固定的分布结果,(如softmax
)避免由log导致的数值问题。
还有一种常见的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()
存在问题,果不其然,查了一下的确是这个的问题。
还是之前那个损失函数(如下图所示)
实现过后,代码在epoch 35 - epoch 40 之间总会报一个nan错,但是epoch 不固定,看看具体的报错信息:
发现这些报错信息下,都有一个常见的情况,那就是 NA acc 的准确率已经到了0.98-0.99 了,那这个跟报错有关系吗?于是我尝试将负样本损失单独训练,果不其然,在仅使用 loss_neg 下训练模型,发现不到10 step 损失就报nan !震惊,原来问题出现在负样本的损失上!
经仔细发现,原来是我负样本的损失在一定epoch的学习下就变成了0,显然这是不大可能的啊,针对情况改代码就可以了吧。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。