2017-10-01 1 views
0

Je voulais écrire ma propre fonction d'activation, mais j'ai eu un problème. Dire la multiplication de la matrice appellera .data. J'ai cherché mais j'ai eu peu d'informations utiles. Toute aide serait appréciée. Les informations d'erreur estPytorch: définir une fonction personnalisée

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

S'il vous plaît fournir votre code source complet ... –

+0

Pourquoi voudriez-vous mettre en œuvre votre propre fonction en arrière. PyTorch a intégré autograd. Tant que vos opérations sont différentiables, vous n'avez pas besoin d'écrire une fonction arrière personnalisée. – jdhao

Répondre

0

Les pytorch tenseurs que vous utilisez doit être enveloppé dans un objet torch.Variable comme si

v=torch.Variable(mytensor) 

Le autograd suppose que tenseurs sont enveloppés dans des variables et peuvent ensuite accéder à la données utilisant v.data. La classe Variable est la structure de données utilisée par Autograd pour effectuer des dérivées numériques au cours de la passe arrière. Assurez-vous que les tenseurs de données que vous passez sont enveloppés dans torch.Variable.

-Mo

+0

Merci! Et je suis encore confus, Est-ce que les tenseurs utilisés en avant et en arrière doivent être des Variables? Autograd utilise la Variable pour passer en arrière, mais j'écris moi-même en arrière, donc il semble inutile d'utiliser Variable, ou je n'ai pas besoin d'écrire en arrière, car Autograd peut le faire lui-même avec Variable. – zhaosl