Как использовать функцию numpy как функцию потерь в PyTorch и избежать ошибок во время выполнения? - PullRequest
0 голосов
/ 13 января 2019

Для моей задачи мне не нужно вычислять градиенты. Я просто заменяю nn.L1Loss функцией numpy (corrcoef) в моей оценке потерь, но получаю следующую ошибку:

RuntimeError: Can’t call numpy() on Variable that requires grad. Use var.detach().numpy() instead.

Я не мог понять, как именно я должен отсоединить график (я пытался torch.Tensor.detach(np.corrcoef(x, y)), но я все еще получаю ту же ошибку. В конце концов я обернул все, используя torch.no_grad, как показано:

with torch.no_grad():
    predFeats = self.forward(x)
    targetFeats = self.forward(target)
    loss = torch.from_numpy(np.corrcoef(predFeats.cpu().numpy().astype(np.float32), targetFeats.cpu().numpy().astype(np.float32))[1][1])

Но на этот раз я получаю следующую ошибку:

TypeError: expected np.ndarray (got numpy.float64)

Интересно, что я делаю не так?

1 Ответ

0 голосов
/ 13 января 2019

TL; DR

with torch.no_grad():
    predFeats = self(x)
    targetFeats = self(target)
    loss = torch.tensor(np.corrcoef(predFeats.cpu().numpy(),
                                    targetFeats.cpu().numpy())[1][1]).float()

Вы бы избежали первого RuntimeError, отсоединив тензоры (predFeats и targetFeats) от вычислительного графика. то есть получение копии тензорных данных без градиентов и функции градиента (grad_fn).

Итак, вместо

torch.Tensor.detach(np.corrcoef(x.numpy(), y.numpy())) # Detaches a newly created tensor!
# x and y still may have gradients. Hence the first error.

который ничего не делает, делает

# Detaches x and y properly
torch.Tensor(np.corrcoef(x.detach().numpy(), y.detach().numpy()))

Но давайте не будем беспокоиться обо всех отрядах.

Как вы правильно сделали, давайте отключим градиенты.

torch.no_grad()

Теперь вычислите функции.

predFeats = self(x) # No need for the explicit .forward() call
targetFeats = self(target)

Мне показалось полезным разбить вашу последнюю строку.

loss = np.corrcoef(predFeats.numpy(), targetFeats.numpy()) # We don't need to detach

# Notice that we don't need to cast the arguments to fp32
# since the `corrcoef` casts them to fp64 anyway.

print(loss.shape, loss.dtype) # A 2-dimensional fp64 matrix

loss = loss[1][1]
print(type(loss)) # Output: numpy.float64
# Loss now just a simple fp64 number

И это проблема!

Потому что, когда мы делаем

loss = torch.from_numpy(loss)

мы передаем число (numpy.float64), в то время как ожидается нулевой тензор (np.ndarray).

Если вы используете PyTorch 0.4 или выше, есть встроенная поддержка скаляров.

Просто замените метод from_numpy() на универсальный метод создания tensor().

loss = torch.tensor(loss)

P.S. Возможно, вы захотите взглянуть на установку rowvar=False в corrcoef, поскольку строки в тензорах PyTorch обычно представляют наблюдения.

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