美文网首页
pytorch训练时前一次迭代的loss正常后一次迭代却报nan

pytorch训练时前一次迭代的loss正常后一次迭代却报nan

作者: ce0b74704937 | 来源:发表于2021-05-28 20:21 被阅读0次

问题描述:训练一个有四个阶段模型的网络(可以简单理解每一阶段就是一个卷积层),每阶段输出都会进行loss计算。现将pytorch原始的ce loss改为focal loss后,网络训练了数个迭代后loss 报nan。输入数据检查过没有问题,报nan时的前一个迭代的loss是正常的。报nan的当前迭代,第一个阶段所有的卷积参数都已经是nan了。

一、问题排除

  1. 因为查看过数据,完全没有问题,排除输入
  2. 因为参数在报nan时已经是nan了,不是前向问题
  3. 前一次迭代loss完全没问题,可能不是bp的问题,但是还没有排除是bp的问题,虽然前一次迭代loss是正常的

二、问题定位

将所有反向梯度打印出来,发现第一个阶段的所有参数梯度为nan,其它正常。

for name, param in net.named_parameters():
    print('name:{} param grad:{} param requires_grad:{}'.format(name, param.grad, param.requires_grad))

采用toch.autograd.detect_anomaly()发现loss报错为“RuntimeError: Function 'LogBackward' returned nan values in its 0th output”

with autograd.detect_anomaly():
    loss.backward()

说明是在第一阶段计算focalloss时,bp出现了nan。

三、问题发生原因

3.1 为什么bp出现了nan,但是forward计算loss没有inf之类的东西出现?

因为focal loss计算的时候采用了gather,选取了对应label类别的概率来计算loss。

class FocalLoss(nn.Module):
    def __init__(self, alpha=0.25, gamma=2, num_classes=2, reduction='mean'):
        """
        focal_loss , -αt(1-pt)**gamma * log(pt)
        :param alpha:   balance class. list(alpha = alpha) or constant([alpha, 1-alpha, 1-alpha, ...]), default 0.25
        :param gamma:   gamma, default 2
        :param num_classes:  num classes
        :param reduction: mean or sum, default mean
        """

        super().__init__()
        self.reduction = reduction
        if isinstance(alpha, list):
            assert len(alpha) == num_classes
            self.alpha = torch.Tensor(alpha)
        else:
            assert alpha < 1   # background decay
            self.alpha = torch.zeros(num_classes)
            self.alpha[0] += alpha
            self.alpha[1:] += (1 - alpha) #  [ α, 1-α, 1-α, 1-α, 1-α, ...] size:[num_classes]
        self.gamma = gamma

    def forward(self, preds, labels):
        """
        focal_loss forward
        :param preds:   size:[N, T, C] or [T, C]    N: batch size T: video length C: num classes
        :param labels:  size:[N, T] or [T]
        :return:
        """
        preds = preds.view(-1, preds.size(-1))
        self.alpha = self.alpha.to(preds.device)
        preds_softmax = F.softmax(preds, dim=1)
        preds_logsoft = torch.log(preds_softmax)
        preds_softmax = preds_softmax.gather(1, labels.view(-1, 1))
        preds_logsoft = preds_logsoft.gather(1, labels.view(-1, 1))
        self.alpha = self.alpha.gather(0, labels.view(-1))
        loss = -torch.mul(torch.pow((1 - preds_softmax), self.gamma), preds_logsoft)
        loss = torch.mul(self.alpha, loss.t())
        if self.reduction == 'mean':
            loss = loss.mean()
        elif self.reduction == 'sum':
            loss = loss.sum()
        return loss
3.2 为什么gather后,计算bp没有只根据对应的类别的的loss计算梯度?

https://github.com/pytorch/pytorch/issues/46225

类似的

import torch
from torch.autograd import Variable

x = Variable(torch.FloatTensor([1.,1]), requires_grad=True)
div = Variable(torch.FloatTensor([0.,1]))
y = x/div

loss = y.gather(0, 1)
loss.backward()
print(x.grad)

四、解决办法

避免loss计算出现inf这种结果,如将preds_logsoft = torch.log(preds_softmax)替换为preds_logsoft = torch.log(preds_softmax+1e-8)

相关文章

  • pytorch训练时前一次迭代的loss正常后一次迭代却报nan

    问题描述:训练一个有四个阶段模型的网络(可以简单理解每一阶段就是一个卷积层),每阶段输出都会进行loss计算。现将...

  • 训练深度学习模型时出现nan的原因

    在训练深度学习的网络时候,迭代一定次数,会出现loss是nan,然后acc很快降低到了0.1,训练也就无法继续了。...

  • 16|系统迭代:微信红包的意外与刻意

    微信迭代逻辑:前一次的迭代都是后一次迭代的前置动作。 1.0版本只是一个熟人之间沟通的产品 2.0版本增设查找附近...

  • tensorflow2.x的keras训练模型loss出现nan

    最近使用tf2.0的keras训练模型时,loss在训练一段时间后就变成了nan,此时虽然acc却还在一直上升,但...

  • pytorch loss 出现 nan

    排查问题: 调整学习率为0,loss还为NAN---->与学习率无关 模型内关于除、log等可能出现异常的操作,加...

  • 机器学习6:感知器算法python实现

    单样本感知器算法 单样本感知器算法仅读取一次样本,每读取一次样本,就是一次迭代。每次迭代时,只考虑用一个训练模式修...

  • 迭代器,生成器,面向过程编程

    迭代器 一、迭代的概念迭代器即迭代的工具,那什么是迭代呢?迭代是一个重复的过程。每一次重复即一次迭代,并且每次迭代...

  • caffe训练报错集锦

    Caffe 训练时loss等于87.33或者NAN问题描述:训练过程中突然loss一直等于87.33原因:计算过程...

  • js 迭代器与生成

    1 迭代器:循环时迭代器的基础,迭代器可以指定迭代的次数,以及每次迭代要执行什么操作。每次都会在下一次迭代之前完成...

  • 迭代器

    参考文献: PEP 234 迭代器 一、迭代器 数学中的迭代可以指函数迭代的过程,即反复地运用同一函数计算,前一次...

网友评论

      本文标题:pytorch训练时前一次迭代的loss正常后一次迭代却报nan

      本文链接:https://www.haomeiwen.com/subject/dyclsltx.html