Преобразование списка списков и скаляров в список тензоров PyTorch вызывает предупреждение - PullRequest
0 голосов
/ 03 августа 2020

Я преобразовывал список списков в тензор PyTorch и получил предупреждающее сообщение. Само преобразование не сложно. Например:

>>> import torch
>>> thing = [[1, 2, 3, 4, 5], [2, 3], 2, 3]
>>> thing_tensor = list(map(torch.tensor, thing))

Я получаю предупреждение:

home/user1/files/module.py:1: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).

, и мне интересно, в чем может быть причина. Есть ли другой способ преобразовать данные в тензор, о котором я не знаю? Спасибо.

Ответы [ 3 ]

2 голосов
/ 03 августа 2020

Я пытался воспроизвести ваше предупреждение, но не смог. Однако я мог бы получить такое же предупреждение, создав, если бы заменил списки в thing тензорами.

Я go объясню, почему лучше использовать x.clone().detach(), а не torch.tensor(x) для сделать копию:

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

Не отсоединяется:

x = torch.tensor([0.],requires_grad=True)
y = x.clone()
y[0] = 1
z = 2 * y
z.backward()
print(x, x.grad)
tensor([0.], requires_grad=True) tensor([0.])

Как вы можно увидеть, что градиент x обновляется, пока вычисление выполняется для y, но изменение значения y не изменит значение x, потому что они не занимают одно и то же пространство памяти.

Занимает то же пространство памяти:

x = torch.tensor([0.],requires_grad=True)
y = x.detach().requires_grad_(True)
z = 2 * y
z.backward()
y[0] = 1
print(x, x.grad)
tensor([1.], requires_grad=True) None

В этом случае градиенты не обновляются, но изменение значения y изменяет значение x, поскольку они занимают то же пространство памяти.

Лучшая практика:

Как указано в предупреждении, лучше всего как отсоединить, так и клонировать тензор:

x = torch.tensor([0.],requires_grad=True)
y = x.clone().detach().requires_grad_(True)
z = 2 * y
z.backward()
y[0] = 1
print(x, x.grad)
tensor([0.], requires_grad=True) None

Это гарантирует, что будущие модификации и вычисления из y не повлияют на x

1 голос
/ 04 августа 2020

@ StatisticDean дает хороший ответ, я просто добавлю один бит c к тому, что вы делаете:

«Я преобразовывал список списков в тензор PyTorch» - То есть совсем не то, что происходит. Ваш пример кода преобразует список списков чисел в список тензоров. Распечатайте thing_tensor, он должен быть:

[tensor([1, 2, 3, 4, 5]), tensor([2, 3]), tensor(2), tensor(3)] 

Это потому, что map вызывает torch.tensor для каждого элемента списка верхнего уровня, создавая отдельные тензоры. Кроме того, это выполняется без ошибок.

Вероятно, вы сначала попытались torch.tensor(thing) преобразовать список списков в один go и получили ошибку ValueError: expected sequence of length 5 at dim 1 (got 2). Причина в том, что тензоры должны быть прямоугольными angular - например, для двумерного тензора каждая строка / столбец должны иметь одинаковый размер. Фактически вы не можете преобразовать список списков, который у вас есть, в тензор, не изменив размеры некоторых элементов.

Пример преобразования списка списков в один тензор с помощью всего одного вызова:

torch.tensor([[11,12,13],[21,22,23]])

Прекрасно работает, так как каждая строка имеет размер 3, а размер каждого столбца - 2; карта не требуется.

0 голосов
/ 04 августа 2020

Он хорошо работает в моей среде Pytorch. Я думаю, что предупреждение, которое вы встретили, было вызвано другой причиной, например, версией Pytorch или версией python, et c.

Это мой результат для запуска вашего кода без каких-либо исправлений.

...