Эффективный способ избежать изменения параметра операцией на месте - PullRequest
0 голосов
/ 02 октября 2019

У меня есть model, который имеет шумные линейные слои (для которого вы можете выбрать значения из параметров mu и sigma) и мне нужно создать два декоррелированных его выхода.

Это означает, что у меня есть что-то вроде:

model.sample_noise()
output_1 = model(input)

with torch.no_grad():
     model.sample_noise()
     output_2 = model(input)

sample_noise на самом деле изменяет веса, прикрепленные к model в соответствии с нормальным распределением.

Но в итоге это приводитto

RuntimeError: одна из переменных, необходимых для вычисления градиента, была изменена операцией на месте

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

1 Ответ

0 голосов
/ 02 октября 2019

Если я правильно понимаю вашу проблему, вы хотите создать линейный слой с матрицей M, а затем создать два вывода

y_1 = (M + μ_1) * x + b
y_2 = (M + μ_2) * x + b

, где μ_1, μ_2 ~ P. Самый простой способ, на мой взгляд, создать пользовательский класс

import torch
import torch.nn.functional as F
from torch import nn

class NoisyLinear(nn.Module):
    def __init__(self, n_in, n_out):
        super(NoisyLinear, self).__init__()

        # or any other initialization you want
        self.weight = nn.Parameter(torch.randn(n_out, n_in))
        self.bias = nn.Parameter(torch.randn(n_out))

    def sample_noise(self):
        # implement your noise generation here
        return torch.randn(*self.weight.shape) * 0.01

    def forward(self, x):
        noise = self.sample_noise()
        return F.linear(x, self.weight + noise, self.bias)

nl = NoisyLinear(4, 3)
x = torch.randn(2, 4)

y1 = nl(x)
y2 = nl(x)

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