首先,我知道有人提出了一个相关的问题here。
然而,这个问题是关于实施和内部的。 我正在阅读论文“A Tour of TensorFlow”。从那里引用以下两点:
1
张量本身不会在内存中保存或存储值,但提供 只是一个用于检索张量引用的值的接口。
这告诉我,Tensor是一个简单地将指针存储到操作结果的对象,并且在检索张量的结果或值时,它只是取消引用该指针。
2
变量可以描述为存储张量的内存缓冲区的持久,可变句柄。因此,变量的特征在于某种形状和固定类型。
在此我感到困惑,因为我认为,基于前一点,Tensors只存储一个指针。如果它们只是指针,它们也可能是可变的。
准确地说,这些是我的问题:
答案 0 :(得分:46)
在解释张量和变量之间的区别之前,我们应该准确地说明“张量”这个词在TensorFlow的背景下意味着什么:
在 Python API 中,tf.Tensor
对象表示TensorFlow操作的符号结果。例如,在表达式t = tf.matmul(x, y)
中,t
是一个tf.Tensor
对象,表示乘以x
和y
的结果(它们本身可能是其他的符号结果)操作,具体值,如NumPy数组或变量)。
在此上下文中,“符号结果”比指向操作结果的指针更复杂。它更类似于一个函数对象,当被调用(即传递给tf.Session.run()
)时,将运行必要的计算以产生该操作的结果,并将其作为具体值返回给您(例如NumPy数组)
在 C ++ API 中,tensorflow::Tensor
对象表示多维数组的具体值。例如,MatMul
内核将两个二维tensorflow::Tensor
对象作为输入,并生成一个二维tensorflow::Tensor
对象作为其输出。
这种区别有点令人困惑,如果我们重新开始,我们可能会选择不同的名称(在其他语言API中,我们更喜欢名称Output
表示符号结果,Tensor
表示具体值)
变量存在类似的区别。在Python API中,tf.Variable
是变量的符号表示,它具有创建读取变量当前值的操作的方法,并为其赋值。在C ++实现中,tensorflow::Var
对象是共享的可变tensorflow::Tensor
对象的包装器。
有了这样的背景,我们可以解决您的具体问题:
“内存缓冲区”是什么意思?
内存缓冲区只是一个已分配有TensorFlow分配器的连续内存区域。 tensorflow::Tensor
个对象包含指向内存缓冲区的指针,该缓冲区保存该张量的值。缓冲区可以在主机存储器中(即可从CPU访问)或设备存储器(例如只能从GPU访问),TensorFlow具有在这些存储空间之间移动数据的操作。
“句柄”的含义是什么?
在the paper的解释中,“handle”一词以两种不同的方式使用,这与TensorFlow使用该术语的方式略有不同。本文使用“符号句柄”来引用tf.Tensor
对象,使用“持久性,可变句柄”来引用tf.Variable
对象。 TensorFlow代码库使用“句柄”来引用有状态对象的名称(如tf.FIFOQueue
或tf.TensorArray
),可以在不复制所有值的情况下传递(即call-by-reference)
我对张量内部的初步假设是正确的吗?
您的假设与(C ++)tensorflow::Tensor
对象的定义最匹配。 (Python)tf.Tensor
对象更复杂,因为它引用了一个计算值的函数,而不是值本身。
张量和变量之间的基本内部实现差异是什么?
在C ++中,tensorflow::Tensor
和tensorflow::Var
非常相似;唯一不同的是,tensorflow::Var
还有一个mutex
,可用于在变量更新时锁定变量。
在Python中,本质区别在于tf.Tensor
是作为数据流图实现的,它是只读的(即通过调用tf.Session.run()
)。可以读取tf.Variable
(即通过评估其读取操作)并写入(例如通过运行分配操作)。
为什么它们的声明不同?为什么这种差异对于TensorFlow来说至关重要?
张量和变量用于不同的目的。张量(tf.Tensor
个对象)可以表示数学表达式的复杂组合,如神经网络中的损失函数或符号渐变。变量表示随时间更新的状态,如训练期间的权重矩阵和卷积滤波器。虽然原则上你可以表示没有变量的模型的演化状态,但你最终会得到一个非常大的(并且重复的)数学表达式,因此变量提供了一种方便的方法来实现模型的状态,例如 - 分享与其他机器进行并行训练。