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 обычно представляют наблюдения.