Pytorch:定义自定义函数

dfty9e19  于 2022-12-18  发布在  其他
关注(0)|答案(3)|浏览(234)

我想写我自己的激活函数,但我遇到了一个问题。说矩阵乘法将调用.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
xj3cbfub

xj3cbfub1#

PyTorch中最基本的元素是一个Tensor,它相当于numpy.ndarray,唯一的区别是Tensor可以放在GPU上进行任何计算。
VariableTensor的 Package 器,包含三个属性:datagradgrad_fndata包含原始的Tensor; grad包含相对于该Variable的某个值的导数/梯度; grad_fnFunction对象的指针,Function对象创建了这个Variablegrad_fn属性实际上是autograd正常工作的关键,因为PyTorch使用这些指针在每次迭代时构建计算图,并相应地对图中的所有Variables执行微分。这不仅仅是通过您正在创建的这个定制Function对象进行正确区分。

因此,每当你在计算中创建一些需要微分的Tensor时,把它 Package 成Variable。首先,这将使Tensor能够在你调用backward()之后保存得到的导数/梯度值。其次,这有助于autograd构建正确的计算图。
另一件需要注意的事情是,每当你把一个Variable发送到你的计算图中时,任何使用这个Variable计算的值都会自动成为一个Variable,所以你不必手动把所有的Tensors都打包到你的计算图中。
您可能想看看this
回到您的错误,要找出真正导致问题的原因有点困难,因为您没有显示所有代码(比如您如何在计算图中使用这个自定义的Function),但我怀疑最有可能发生的情况是您在需要通过进行区分的子图中使用了这个Function,当PyTorch对模型使用数值梯度检查来查看微分是否正确时,它假设该子图中的每个节点都是Variable,因为这是通过该子图进行微分所必需的,然后它尝试调用该Variabledata属性,很可能是因为该值在区分中的某处被使用,并且由于该节点实际上是Tensor并且不具有data属性而失败。

unguejic

unguejic2#

您使用的pytorchTensor应该像这样 Package 到torch.Variable对象中

v=torch.Variable(mytensor)

autograd假设Tensor Package 在变量中,然后可以使用v.data访问数据。Variable类是Autograd在反向传递过程中用于执行数值导数的数据结构。确保传递的数据Tensor Package 在torch.Variable中。

7uzetpgm

7uzetpgm3#

这里是一个简单的激活的例子,使用 Torch 激活功能内,但工程,并可以扩展到自定义。

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)        
)

相关问题