Pytorch: градиент при использовании тензорного присваивания - PullRequest
0 голосов
/ 30 мая 2019

Я совершенно новичок в pytorch, поэтому я проверял, как работает функция autograd, и обнаружил странное нелогичное поведение при использовании тензорного присваивания.Давайте предположим, что я хочу запустить следующий пример кода:


import os
import numpy as np
import torch
import torch.nn as nn
from torch import autograd


torch.set_default_tensor_type('torch.cuda.FloatTensor')




class Mult_Input(nn.Module):
    def __init__(self):
        super(Mult_Input, self).__init__()


    def forward(self, inp_list):

        print(inp_list[0].size())

        inp_list[0] = inp_list[0] +  inp_list[1]
        inp_list[1] = inp_list[1]
        inp_list[2] = inp_list[2]


        return torch.stack(inp_list).sum()



real_data = [ (torch.from_numpy(np.array([1], dtype=np.float32)).cuda()), 
              (torch.from_numpy(np.array([1], dtype=np.float32)).cuda()), 
              (torch.from_numpy(np.array([1], dtype=np.float32)).cuda())
             ]


netD = Mult_Input()


interpolates_current =[ autograd.Variable(
    real_data[idx], 
    requires_grad=True) for idx in range(len(real_data))]

new_d_input_data = interpolates_current

disc_interpolates = netD(new_d_input_data)


gradients = autograd.grad(outputs=disc_interpolates, inputs=new_d_input_data,
                          grad_outputs=torch.ones(disc_interpolates.size()), 
                          create_graph=True, retain_graph=True, only_inputs=True) 

print(gradients)

Таким образом, входные данные 1,1,1 и являются отдельными (это важно для меня), а Mult_Input имеет простую функцию, которую я хочудифференцировать по своим входам.

Результат, на мой взгляд, правильный:

(tensor([1.]), tensor([2.]), tensor([1.]))

Таким образом, факел autograd правильно понимает назначение тензоров.

Теперь я попробую немного другой пример с pow(2):

class Mult_Input(nn.Module):
    def __init__(self):
        super(Mult_Input, self).__init__()


    def forward(self, inp_list):

        print(inp_list[0].size())

        inp_list = [x.pow(2) for x in inp_list]

        return torch.stack(inp_list).sum()

Результат снова верен:

(tensor([2.], grad_fn=<MulBackward0>), tensor([2.], grad_fn=<MulBackward0>), tensor([2.], grad_fn=<MulBackward0>))

Теперь я делаю небольшое изменение ихотите изменить элемент списка на месте:

class Mult_Input(nn.Module):
    def __init__(self):
        super(Mult_Input, self).__init__()


    def forward(self, inp_list):

        print(inp_list[0].size())

        inp_list[0] = inp_list[0].pow(2)

        return torch.stack(inp_list).sum()

Результат неверный :

(tensor([1.]), tensor([1.]), tensor([1.]))

Когда я делаю

inp_list[0] = inp_list[0].pow(2) + inp_list[1]

Возвращает (tensor([1.]), tensor([2.]), tensor([1.])) игнорируя квадрат.

версия pytorch - 1.0.1.post2

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...