我有三个简单的问题。PyTorch中的自定义丢失函数
- 如果我的自定义丢失函数不可区分会发生什么?将pytorch通过错误或做别的?
- 如果我在自定义函数中声明了一个将代表模型最终损失的损失变量,那么我应该为该变量放置
requires_grad = True
吗?或者没关系?如果没关系,那为什么? - 我已经看到人们有时会编写一个单独的图层并计算
forward
函数中的损失。编写一个函数或一个图层最好采用哪种方法?为什么?
我需要对这些问题有一个清晰而好的解释来解决我的困惑。请帮忙。
我有三个简单的问题。PyTorch中的自定义丢失函数
requires_grad = True
吗?或者没关系?如果没关系,那为什么?forward
函数中的损失。编写一个函数或一个图层最好采用哪种方法?为什么?我需要对这些问题有一个清晰而好的解释来解决我的困惑。请帮忙。
让我走了。
这取决于你的意思是“不可微分”。第一个有意义的定义是PyTorch不知道如何计算渐变。如果您尝试计算渐变,则会产生错误。这两种可能的情况是:
a)您正在使用自定义的PyTorch操作,其渐变尚未实现,例如, torch.svd()
。在这种情况下,你会得到一个TypeError
:
import torch
from torch.autograd import Function
from torch.autograd import Variable
A = Variable(torch.randn(10,10), requires_grad=True)
u, s, v = torch.svd(A) # raises TypeError
b)你已经实现了你自己的操作,但没有规定backward()
。在这种情况下,你会得到一个NotImplementedError
:
class my_function(Function): # forgot to define backward()
def forward(self, x):
return 2 * x
A = Variable(torch.randn(10,10))
B = my_function()(A)
C = torch.sum(B)
C.backward() # will raise NotImplementedError
是有道理的是“数学上不可微分的”第二个定义。显然,数学上不可区分的操作应该没有执行backward()
方法或者是合理的子梯度。例如,考虑torch.abs()
其backward()
方法在0返回梯度0:
A = Variable(torch.Tensor([-1,0,1]),requires_grad=True)
B = torch.abs(A)
B.backward(torch.Tensor([1,1,1]))
A.grad.data
对于这些情况,你应该参考PyTorch文档直接,直接挖掘出各自的操作方法backward()
。
没关系。使用requires_grad
是为了避免不必要的子图梯度计算。如果需要渐变的操作有单个输入,则其输出也需要渐变。相反,只有当所有输入不需要渐变时,输出也不需要它。反向计算从不在子图中执行,其中所有变量不需要渐变。
因为,最有可能的一些Variables
(例如nn.Module()
的子类的参数),您的loss
变量也将自动需要梯度。但是,您应该注意到requires_grad
的工作原理(请参阅上面的内容),无论如何,您只能更改图表的叶变量requires_grad
。
所有自定义PyTorch丢失函数都是_Loss
的子类,它是nn.Module
的子类。See here.如果您想坚持这一惯例,则在定义自定义丢失函数时应划分_Loss
。除了一致性之外,如果您尚未将目标变量标记为volatile
或requires_grad = False
,则其中一个优点是您的子类将提高AssertionError
。另一个优点是,你可以将你的损失函数嵌套在nn.Sequential()
中,因为它的一个nn.Module
我会推荐这种方法出于这些原因。
不客气。不幸的是无法打开链接。 – mexmex
我之所以删除这个问题,是因为我解决了这个问题。但你能帮我在这个问题 - https://stackoverflow.com/questions/44580450/cuda-vs-dataparallel-why-the-difference? –