我有三个简单的问题.
requires_grad = True
为该变量添加吗?或者没关系?如果没关系那么,为什么呢?forward
.编写函数或层是哪种方法更可取?为什么?我需要对这些问题做出明确而好的解释才能解决我的困惑.请帮忙.
mex*_*mex 12
我来吧
这取决于你所说的"不可微分".这里有意义的第一个定义是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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
有意义的第二个定义是"数学上不可微分".显然,在数学上不可微分的操作应该不具有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
Run Code Online (Sandbox Code Playgroud)
对于这些情况,您应该直接参考PyTorch文档并直接挖掘backward()
相应操作的方法.
没关系.使用requires_grad
是为了避免对子图的渐变进行不必要的计算.如果对需要渐变的操作有单个输入,则其输出也需要渐变.相反,只有当所有输入都不需要梯度时,输出也不需要它.从不在子图中执行向后计算,其中所有变量都不需要渐变.
因为,很可能有一些Variables
(例如子类的参数nn.Module()
),你的loss
变量也会自动需要渐变.但是,您应该注意到确切的requires_grad
工作原理(再次参见上文),您只能更改requires_grad
图表的叶子变量.
所有自定义PyTorch损失函数都是其子类的_Loss
子类nn.Module
.看这里.如果您想坚持这个约定,那么_Loss
在定义自定义损失函数时应该是子类.除了一致性之外AssertionError
,如果您没有将目标变量标记为volatile
或,则一个优点是您的子类将引发一个requires_grad = False
.另一个优点是你可以嵌入你的损失函数nn.Sequential()
,因为nn.Module
我会推荐这种方法出于这些原因.
归档时间: |
|
查看次数: |
7887 次 |
最近记录: |