Обратите внимание, что b *=b
не то же самое, что b = b*b
.
Возможно, это сбивает с толку, но основные операции различаются.
В случае b *=b
in- выполняется операция place, которая приводит к путанице с градиентами и, следовательно, с RuntimeError
.
В случае b = b*b
, два тензорных объекта умножаются, и результирующему объекту присваивается имя b
. Таким образом, нет RuntimeError
, когда вы запускаете таким образом.
Вот вопрос SO по базовой операции python: Разница между x + = y и x = x + y
В чем разница между fn
в первом случае и fn2
во втором? Операция c*=b
не уничтожает связи графика с b
из c
. Операция c*=c
сделала бы невозможным создание графа, соединяющего два тензора с помощью операции.
Ну, я не могу работать с тензорами, чтобы продемонстрировать это, потому что они вызывают RuntimeError. Поэтому я попробую со списком python.
>>> x = [1,2]
>>> y = [3]
>>> id(x), id(y)
(140192646516680, 140192646927112)
>>>
>>> x += y
>>> x, y
([1, 2, 3], [3])
>>> id(x), id(y)
(140192646516680, 140192646927112)
Обратите внимание, что новый объект не создан. Таким образом, невозможно отследить от output
до исходных переменных. Мы не можем различать guish и object_140192646516680
как выход или вход. Итак, как создать график с этим ..
Рассмотрим следующий альтернативный случай:
>>> a = [1,2]
>>> b = [3]
>>>
>>> id(a), id(b)
(140192666168008, 140192666168264)
>>>
>>> a = a + b
>>> a, b
([1, 2, 3], [3])
>>> id(a), id(b)
(140192666168328, 140192666168264)
>>>
Обратите внимание, что новый список a
на самом деле является новым объектом с id
140192666168328
. Здесь мы можем проследить, что object_140192666168328
пришел из addition operation
между двумя другими объектами object_140192666168008
и object_140192666168264
. Таким образом, можно динамически создавать график и распространять градиенты с output
на предыдущие слои.