我想写我自己的激活函数,但我遇到了一个问题。说矩阵乘法将调用.data
。我搜索了,但得到的有用信息很少。任何帮助将不胜感激。错误信息是
Traceback (most recent call last):
File "defineAutogradFuncion.py", line 126, in <module>
test = gradcheck(argmin, input, eps=1e-6, atol=1e-4)
File "/home/zhaosl/.local/lib/python2.7/site-packages/torch/autograd/gradcheck.py", line 154, in gradcheck
output = func(*inputs)
File "defineAutogradFuncion.py", line 86, in forward
output = output.mm(dismap).squeeze(-1)
File "/home/zhaosl/.local/lib/python2.7/site-packages/torch/autograd/variable.py", line 578, in mm
output = Variable(self.data.new(self.data.size(0), matrix.data.size(1)))
File "/home/zhaosl/.local/lib/python2.7/site-packages/torch/tensor.py", line 374, in data
raise RuntimeError('cannot call .data on a torch.Tensor: did you intend to use autograd.Variable?')
RuntimeError: cannot call .data on a torch.Tensor: did you intend to use autograd.Variable?
class Softargmin(torch.autograd.Function):
"""
We can implement our own custom autograd Functions by subclassing
torch.autograd.Function and implementing the forward and backward passes
which operate on Tensors.
"""
@staticmethod
def forward(self, input):
"""
In the forward pass we receive a Tensor containing the input and return a
Tensor containing the output. You can cache arbitrary Tensors for use in the
backward pass using the save_for_backward method.
"""
#P = Fun.softmax(-input)
inputSqueeze = input.squeeze(-1)
P = Fun.softmax(-inputSqueeze)
self.save_for_backward(P)
output = P.permute(0,2,3,1)
dismap = torch.arange(0,output.size(-1)+1).unsqueeze(1)
output = output.mm(dismap).squeeze(-1)
return output
@staticmethod
def backward(self, grad_output):
"""
In the backward pass we receive a Tensor containing the gradient of the loss
with respect to the output, and we need to compute the gradient of the loss
with respect to the input.
"""
P, = self.saved_tensors
P = P.unsqueeze(-1)
Pk = torch.squeeze(P,-1).permute(0,2,3,1)
k = torch.arange(0,Pk.size(-1)+1).unsqueeze(1)
sumkPk = Pk.mm(k)
sumkPk = sumkPk.unsqueeze(1).expand(P.size())
i = torch.arange(0,Pk.size(-1)+1).view(1,-1,1,1,1).expand(P.size())
grad_output_expand =grad_output.unsqueeze(-1).unsqueeze(1).expand(P.size())
grad_input = grad_output_expand*P*(sumkPk-i)
return grad_input
3条答案
按热度按时间xj3cbfub1#
PyTorch中最基本的元素是一个
Tensor
,它相当于numpy.ndarray
,唯一的区别是Tensor
可以放在GPU上进行任何计算。Variable
是Tensor
的 Package 器,包含三个属性:data
、grad
和grad_fn
。data
包含原始的Tensor
;grad
包含相对于该Variable
的某个值的导数/梯度;grad_fn
是Function
对象的指针,Function
对象创建了这个Variable
。grad_fn
属性实际上是autograd
正常工作的关键,因为PyTorch使用这些指针在每次迭代时构建计算图,并相应地对图中的所有Variables
执行微分。这不仅仅是通过您正在创建的这个定制Function
对象进行正确区分。因此,每当你在计算中创建一些需要微分的
Tensor
时,把它 Package 成Variable
。首先,这将使Tensor
能够在你调用backward()
之后保存得到的导数/梯度值。其次,这有助于autograd
构建正确的计算图。另一件需要注意的事情是,每当你把一个
Variable
发送到你的计算图中时,任何使用这个Variable
计算的值都会自动成为一个Variable
,所以你不必手动把所有的Tensors
都打包到你的计算图中。您可能想看看this。
回到您的错误,要找出真正导致问题的原因有点困难,因为您没有显示所有代码(比如您如何在计算图中使用这个自定义的
Function
),但我怀疑最有可能发生的情况是您在需要通过进行区分的子图中使用了这个Function
,当PyTorch对模型使用数值梯度检查来查看微分是否正确时,它假设该子图中的每个节点都是Variable
,因为这是通过该子图进行微分所必需的,然后它尝试调用该Variable
的data
属性,很可能是因为该值在区分中的某处被使用,并且由于该节点实际上是Tensor
并且不具有data
属性而失败。unguejic2#
您使用的pytorchTensor应该像这样 Package 到
torch.Variable
对象中autograd假设Tensor Package 在变量中,然后可以使用
v.data
访问数据。Variable
类是Autograd在反向传递过程中用于执行数值导数的数据结构。确保传递的数据Tensor Package 在torch.Variable
中。7uzetpgm3#
这里是一个简单的激活的例子,使用 Torch 激活功能内,但工程,并可以扩展到自定义。