Function ‘MseLossBackward0‘ returned nan values in its 0th output.

这个比较奇怪的提示来自于Pytorch计算梯度的过程中产生了一个nan值。
如果开启了:

torch.autograd.set_detect_anomaly(True)

那么在loss.backward()的时候就会出现这个提示。
为什么会出现这的情况呢?
在pytorch的一个讨论中出现过这个问题,链接:https://discuss.pytorch.org/t/function-mselossbackward-returned-nan-values-in-its-0th-output/94875。
讨论中有提到:

x = torch.randn(1, 1, requires_grad=True)
y = torch.zeros(1, 1)
criterion = nn.MSELoss()

loss = torch.sqrt(criterion(x * 0, y))
loss.backward()
print(x.grad)
> tensor([[nan]])

那么问题就很明显了,因为在loss的计算中出现了不可求导的情况,导致了梯度计算出现nan值。所以在写损失函数时需要注意计算过程中的那些可能导致求导失败的操作。
那是不是数学上不能计算出梯度的函数在pytorch中也不能计算梯度呢?答案是否定的。
进行如下简单的试验:

    torch.autograd.set_detect_anomaly(True)
    x = torch.randn(1, requires_grad=True)
    loss = torch.abs((x * 0))  # abs的0值是不会导致backward出现问题的。

    # loss = torch.sqrt(loss)  # sqrt的0值会导致backward计算出nan的数据。
    loss.backward()
    print(x.grad)

输出:

tensor([0.])

当去掉torch.sqrt()的注释后,输出:

Traceback (most recent call last):
  File "d:/Code/python/base-python/my_torch.py", line 183, in 
    gradient()
  File "d:/Code/python/base-python/my_torch.py", line 160, in gradient
    loss.backward()
  File "C:\ProgramData\Anaconda3\lib\site-packages\torch\_tensor.py", line 307, in backward
    torch.autograd.backward(self, gradient, retain_graph, create_graph, inputs=inputs)
  File "C:\ProgramData\Anaconda3\lib\site-packages\torch\autograd\__init__.py", line 154, in backward
    Variable._execution_engine.run_backward(
RuntimeError: Function 'AbsBackward0' returned nan values in its 0th output.
ERROR conda.cli.main_run:execute(33): Subprocess for 'conda run ['python', 'd:/Code/python/base-python/my_torch.py']' command failed.  (See above for error)

成功地触发了error。
所以,虽然绝对值函数在0处应当是没有梯度定义的,但是在pytorch中没有问题,而取平方根函数会有问题。
那么怎么处理这种情况呢?一个比较简单的方法是添加一个微量的偏移,如下:

    torch.autograd.set_detect_anomaly(True)
    x = torch.randn(1, requires_grad=True)
    loss = torch.abs((x * 0))+1e-6  # abs的0值是不会导致backward出现问题的。

    loss = torch.sqrt(loss)  # sqrt的0值会导致backward计算出nan的数据。
    loss.backward()
    print(x.grad)

输出

tensor([0.])

你可能感兴趣的:(机器学习,pytorch,深度学习,python)