pytorch训练出现nan是什么意思

1.背景

训练时忽然发现某几项loss变成了nan。


2.nan的含义

nan值在python往往可以直接与无穷大,无穷小等价。

常见根本来源:

  • a/0

  • log(0)

  • 空索引

第一个常见例子: l o s s / p o s n u m loss / posnum loss/posnum,希望根据正例个数平分loss,却忽视pos_num可能为0,也就是图片中没有正例,常见解决 l o s s / ( 0.0001 + n u m ) loss/(0.0001 + num) loss/(0.0001+num)或者if判断;
第二个常见例子:loss计算中带有log( p)时,p却为0,后果就是反传梯度无穷大
第三个常见例子:mask = gt>0, 然后索引 pos_p = pred[mask],却不知此时的pos_p为空;


3.解决

原因:上面第二条

debug
当出现nan后在模型forward函数上打断点,结果发现在第一步时就出现了nan,正常的x输入后出来就有nan值。

def forward(self, x):
    x = self.base_layer(x)
    ...

而self.base模块只是简单的卷积模块:

self.base_layer = nn.Sequential(
     nn.Conv2d(3,self.channels[0], kernel_size=7, stride=1,padding=3,bias=False),
     nn.BatchNorm2d(self.channels[0],momentum=0.1),
     nn.ReLU(inplace=True)
 )

再打印出它的学习参数:

for p in self.base_layer.parameters():
	print(p)

结果发现大部分参数已经是nan了,而这里只是整个模型第一层…
显然梯度爆炸了,自然检查去loss。

重新开始,在总的loss处debug:

if(torch.isnan(loss).sum()>0):
	print("here!")

当首次出现loss时在此处断点,结果发现,nan来源某一项loss,我这里是focal loss,显然是来自里面的log(p ),而p,也就是网络预测为0了,本该 p ∈ [ 0 , 1 ] p\in[0, 1] p[0,1],怎么会有0?

最后想起是Sigmoid函数:

z['hm'] = z['hm'].sigmoid() * out_branch

最后调整为:

z['hm'] = torch.clamp(z['hm'].sigmoid(),min=1e-4,max=1-1e-4) * out_branch
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值