我想编写自己的激活功能,但是我遇到了问题。说矩阵乘法将调用.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
答案 0 :(得分:2)
PyTorch中最基本的元素是Tensor
,它相当于numpy.ndarray
,唯一的区别是可以将Tensor
放到GPU上进行任何计算。
Variable
是Tensor
的包装,其中包含三个属性:data
,grad
和grad_fn
。 data
包含原始Tensor
; grad
包含与此Variable
相关的某个值的派生/梯度; grad_fn
是指向创建此Function
的{{1}}对象的指针。 Variable
属性实际上是grad_fn
正常工作的关键,因为PyTorch使用这些指针在每次迭代时构建计算图,并相应地对图中的所有autograd
进行微分。这不仅仅是通过您正在创建的自定义Variables
对象进行正确区分。
因此,无论何时在计算中创建一些需要区分的Function
,请将其包装为Tensor
。首先,这将使Variable
能够在您调用Tensor
后保存生成的派生/梯度值。其次,这有助于backward()
构建正确的计算图。
另一件需要注意的事情是,每当您向计算图表中发送autograd
时,使用此Variable
计算的任何值都将自动为Variable
。因此,您不必手动将所有Variable
包装在计算图中。
您可能需要查看this。
回到你的错误,找出真正导致问题的原因有点困难,因为你没有显示所有代码(比如你在自己的Tensors
中使用这个自定义Function
的信息计算图),但我怀疑最有可能发生的是你在一个需要区分的子图中使用了这个Function
,当PyTorch在你的模型上使用数值梯度检查来判断区分是否正确时,它假设该子图中的每个节点都是Variable
,因为这是通过该子图进行区分所必需的,然后它试图调用该data
的{{1}}属性,很可能是因为该值在区分中的某处使用,并且失败,因为该节点实际上是Variable
并且没有Tensor
属性。
答案 1 :(得分:0)
你正在使用的pytorch张量应该包含在torch.Variable
对象中,如此
v=torch.Variable(mytensor)
autograd假设张量包含在变量中,然后可以使用v.data
访问数据。 Variable
类是Autograd用于在向后传递期间执行数值导数的数据结构。确保您传递的数据张量包含在torch.Variable
中。
-Mo
答案 2 :(得分:0)
以下是简单激活的示例,该示例内部使用了割炬激活功能,但可以正常使用,并且可以扩展为自定义。
import torch as pt
import torch.nn as nn
from torch.nn.modules import Module
# custom activation
class Act(Module):
def forward(self, z):
if(do_ratio > 0):
return nn.functional.dropout(pt.tanh(z), do_ratio)
else:
return pt.tanh(z)
act_fn = Act()
model = pt.nn.Sequential(
pt.nn.Linear(features, n_layer0, bias=enable_bias),
act_fn,
pt.nn.Linear(n_layer0, n_layer1, bias=enable_bias),
act_fn,
pt.nn.Linear(n_layer1, n_layer2, bias=enable_bias)
)