Операции на месте с PyTorch
Мне было интересно, как справляться с операциями на месте в PyTorch. Насколько я помню, использование на месте работы с автографом всегда было проблематичным.
И на самом деле Im удивил, что этот код ниже работает, хотя я и не тестировал его. Я считаю, что этот код вызвал бы ошибку в версии 0.3.1
.
В принципе, я хочу сделать, это установить определенную позицию вектора тензора на определенное значение в подобном:
my_tensor[i] = 42
Рабочий пример кода:
# test parameter a
a = torch.rand((2), requires_grad=True)
print('a ', a)
b = torch.rand(2)
# calculation
c = a + b
# performing in-place operation
c[0] = 0
print('c ', c)
s = torch.sum(c)
print( ', s)
# calling backward()
s.backward()
# optimizer step
optim = torch.optim.Adam(params=[a], lr=0.5)
optim.step()
# changed parameter a
print('changed a', a)
Выход:
a tensor([0.2441, 0.2589], requires_grad=True)
c tensor([0.0000, 1.1511], grad_fn=<CopySlices>)
s tensor(1.1511, grad_fn=<SumBackward0>)
changed a tensor([ 0.2441, -0.2411], requires_grad=True)
Так очевидно в версии 0.4.1
. это работает отлично, без предупреждений или ошибок.
Ссылаясь на эту статью в документации: autograd-mechanics
Поддержка операций на месте в автографе является трудной задачей, и мы в большинстве случаев отговариваем их использовать. Освобождение и повторное использование агрессивных буферов Autograds делает его очень эффективным, и очень мало случаев, когда операции на месте фактически уменьшают использование памяти на любую значительную сумму. Если вы не работаете под сильным давлением памяти, вам, возможно, никогда не понадобится их использовать.
Но даже при том, что это работает, использование операций на месте в большинстве случаев не рекомендуется.
Поэтому мои вопросы:
-
Сколько влияет на эффективность работы на месте?
-
Как мне обойти использование операций на месте в таких случаях, когда я хочу установить один элемент тензора на определенное значение?
Заранее спасибо!
Ответы
Ответ 1
Я не уверен, насколько эффективная работа на месте влияет на производительность, но я могу решить второй запрос. Вы можете использовать маску вместо операций на месте.
a = torch.rand((2), requires_grad=True)
print('a ', a)
b = torch.rand(2)
# calculation
c = a + b
# performing in-place operation
mask = np.zeros(2)
mask[1] =1
mask = torch.tensor(mask)
c = c*mask
...
Ответ 2
Для вашего второго запроса, когда вы делаете c[i] = i
или подобные операции, обычно вызывается __setitem__
. Чтобы сделать эту операцию на месте, вы можете попробовать вызвать функцию __setitem__
(если это то, что выполняет операцию c[i] = i
.