pytorch crossentropy为nan

 

pytorch crossentropy为nan

交叉熵损失函数的具体为:

loss = -(x*ln(z)+(1-x)*ln(1-z)) 
z = softmax(pred_x)

这样当z为0/1时会出现loss为nan的情况

本人的具体原因
网络中用了MultiHeadAttention,attention的mask全为0,这样attention就为nan,造成个别样本的输出特征全为nan。于是就自己用pytorch写了一个cross_entropy loss函数,剔除掉有时候个别为nan的样本。
github地址:Self_cross_entropy

参考解决方案

在pred_x上加一个很小的量,如1e-10
loss = crossentropy(out+1e-8, target)
1
采用更小的学习率
做梯度裁剪

pytorch 梯度裁剪

import torch.nn as nn

 

outputs = model(data)

loss= loss_fn(outputs, target)

optimizer.zero_grad()

loss.backward()

nn.utils.clip_grad_norm_(model.parameters(), max_norm=20, norm_type=2)

optimizer.step()

nn.utils.clip_grad_norm_ 的参数:

parameters – 一个基于变量的迭代器,会进行梯度归一化

max_norm – 梯度的最大范数

norm_type – 规定范数的类型,默认为L2


还可能是数据有问题
比如这位的.链接
[参考]

https://stats.stackexchange.com/questions/108381/how-to-avoid-nan-in-using-relu-cross-entropy
 

且新的变量自动全是variable类型,可顺利反向传播
实现好后运行结果出现大量的nan,无法正常运算,使用clamp限制loss计算值的范围
class CrossEntropy(nn.Module):
    def __init__(self):
        super(CrossEntropy, self).__init__()
        
    def forward(self, inputs, targets):
        ## torch中要想实现backward就不能使用np,不能用array,只能使用tensor,只有tensor才有requires_grad参数
        loss1=-targets*(torch.log(inputs)).cuda()
        loss=torch.sum(loss1.clamp(min=0.0001,max=1.0))

 

你可能感兴趣的:(深度学习基础)