当我使用运算符时,我发现了一个奇怪的事情,例如*=
或+=
代码:
aa = Variable(torch.FloatTensor([[1,2],[3,4]]))
bb = aa
bb = bb*2
print(bb)
print(aa)
cc = Variable(torch.FloatTensor([[1,2],[3,4]]))
dd = cc
dd *= 2
print(cc)
print(dd)
结果显示如下:
Variable containing:
2 4
6 8
[torch.FloatTensor of size 2x2]
Variable containing:
1 2
3 4
[torch.FloatTensor of size 2x2]
Variable containing:
2 4
6 8
[torch.FloatTensor of size 2x2]
Variable containing:
2 4
6 8
[torch.FloatTensor of size 2x2]
如您所见,当我使用bb=bb*2
时,aa
未受影响。但是,如果使用dd *= 2
,cc
似乎指向(共享)与cc
相同的地址,则会更改。
他们各自的前一行是相同的,例如bb = aa
和dd = cc
。似乎*=
运算符将原始深层副本更改为浅副本,并且在复制行本身之后进行了更改。
我想知道这是不是一个错误。如果是,它很重要,因为它影响基本的数学运算。一般来说,我认为只需使用内置的操作功能,例如torch.add()
是一个很好的解决方案。
OS: Mac OS X
PyTorch version: 3.0
How you installed PyTorch (conda, pip, source): conda
Python version: 3.6
CUDA/cuDNN version: None
GPU models and configuration: None
* ---------------------------------------
我理解dd *= 2
是就地增殖,但dd
的价值如何转移到cc
?但如果我使用dd = dd * 2
,则新值不会转移到cc
?上一行没有区别:dd = cc
和bb =aa
。
顺便说一句,在python(不是pytorch变量或张量)中,dd *= 2
和dd = dd * 2
都不会影响cc
值。
答案 0 :(得分:4)
执行dd = cc
时,dd
和cc
现在都是对同一对象的引用(bb = aa
相同)。什么都没有被复制!
执行bb = bb * 2
时,*
运算符会创建一个新对象,bb
现在引用该对象。没有更改现有对象。
执行dd *= 2
后,dd
引用的对象(以及cc
也引用的对象)会发生变化。
不同之处在于*
创建了一个新对象,=
使变量引用一个新对象(而不是以任何方式更改对象),而*=
更改了对象
x *= y
与x = x * y
的行为不同,可能违反直觉,但这些是语言的语义,而不是错误。
答案 1 :(得分:0)
重复测试,但另外打印对象的ID:
aa = Variable(torch.FloatTensor([[1,2],[3,4]]))
bb = aa
bb = bb*2
print(bb , id(bb))
print(aa , id(aa))
cc = Variable(torch.FloatTensor([[1,2],[3,4]]))
dd = cc
dd *= 2
print(cc, id(cc))
print(dd, id(dd))
这可以让您了解会发生什么。
我没有火炬,但正常的名单也是这样做的:
aa = [1,2,3,4]
bb = aa
bb = bb*2
print(bb, id(bb))
print(aa, id(aa))
cc =[1,2,3,4]
dd = cc
dd *= 2
print(cc, id(cc))
print(dd, id(dd))
正常列表的输出(没有火花):
([1, 2, 3, 4, 1, 2, 3, 4], 140432043987888) # bb different ids
([1, 2, 3, 4], 140432043930400) # aa different ids
([1, 2, 3, 4, 1, 2, 3, 4], 140432043916032) # cc same id, same object
([1, 2, 3, 4, 1, 2, 3, 4], 140432043916032) # dd same id, same object