为什么 Tensor 的值会改变?

Why does the Tensor's value change?

# Using Python state
x = tf.zeros([10, 10])
x += 2  # This is equivalent to x = x + 2, which does not mutate the original
        # value of x
print(x)

x 从 0 变为 2。 它显示了 x = tf.zeros([10,10]):

的以下结果
<tf.Tensor: id=266, shape=(10, 10), dtype=float32, numpy=
array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]], dtype=float32)>

然后执行后变成如下: x += 2

<tf.Tensor: id=263, shape=(10, 10), dtype=float32, numpy=
array([[2., 2., 2., 2., 2., 2., 2., 2., 2., 2.],
       [2., 2., 2., 2., 2., 2., 2., 2., 2., 2.],
       [2., 2., 2., 2., 2., 2., 2., 2., 2., 2.],
       [2., 2., 2., 2., 2., 2., 2., 2., 2., 2.],
       [2., 2., 2., 2., 2., 2., 2., 2., 2., 2.],
       [2., 2., 2., 2., 2., 2., 2., 2., 2., 2.],
       [2., 2., 2., 2., 2., 2., 2., 2., 2., 2.],
       [2., 2., 2., 2., 2., 2., 2., 2., 2., 2.],
       [2., 2., 2., 2., 2., 2., 2., 2., 2., 2.],
       [2., 2., 2., 2., 2., 2., 2., 2., 2., 2.]], dtype=float32)>

为什么评论说"which does not mutate the original value of x"?

Chris Heald 是对的。使用 NumPy 最容易看出区别:

import numpy as np

a = np.array(2)
b = a  # Set up an alias

a += 1  # NumPy operations are in-place - they mutate the array
print(b)  # Output: 3!

由于 ndarray__iadd__ 就地改变数组,任何对数组的引用都会更新,所以代码打印 3。 NumPy 数组在这方面更像是对象。

将其与不可变的 TF Tensors 进行比较(代码为 TF 2):

import tensorflow as tf

a = tf.constant(2)
b = a  # Set up an alias

a += 1  # Tensor operations are not in-place - a new tensor is created
print(b)  # Output: 2

打印 2,因为 Tensor 是不可变的。所以它们更像是原始值。

然后访问原始值很简单 - 只需将其分配给其他变量(就像我对 b = a 所做的那样)。

另一种描述方式是使用列表:

l = [1]
l[0] = 2  # I can mutate the list...
l = [2]   # ... or I can create a new one