TensorFlow变量和TensorFlow张量的实现区别

24

首先,我知道有一个相关问题被问到了这里.

然而,这个问题是关于TensorFlow的实现和内部的。我正在阅读论文《A Tour of TensorFlow》。以下两点摘自该论文:

1.

张量本身不在内存中保存或存储值,但仅提供检索由张量引用的值的接口。

这使我认为Tensor是一个对象,它简单地存储指向操作结果的指针,并且在检索张量的结果或值时,它只是取消引用该指针。

2.

变量可以被描述为存储张量的持久性可变句柄的内存缓冲区。因此,变量具有特定的形状和固定类型。

这让我感到困惑,因为我根据以前的那一点认为张量只是简单地存储指针。如果它们只是指针,它们也可能是可变的。

准确来说,这些是我的问题:

  1. "内存缓冲区"的含义是什么?
  2. “句柄”的含义是什么?
  3. 我的关于张量内部的初始假设是否正确?
  4. 张量和变量之间的基本内部实现差异是什么?为什么它们被声明为不同,并且这种差异对TensorFlow至关重要?
1个回答

52
在解释张量和变量之间的区别之前,我们应该明确“张量”一词在TensorFlow上下文中的意义。
Python API中,tf.Tensor对象表示TensorFlow操作的符号结果。例如,在表达式t = tf.matmul(x, y)中,t是一个tf.Tensor对象,代表将xy相乘的结果(它们自己可能是其他操作的符号结果、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对象。
有了这个背景,我们可以回答你的具体问题:
  1. "内存缓冲区"的含义是什么?

    内存缓冲区只是使用 TensorFlow 分配器分配的一段连续内存区域。 tensorflow::Tensor 对象包含指向内存缓冲区的指针,该缓冲区保存张量的值。缓冲区可以位于主机内存中(即可从 CPU 访问)或设备内存中(例如仅可从 GPU 访问),TensorFlow 有操作可在这些内存空间之间移动数据。

  2. "句柄"的含义是什么?

    论文 中的解释中,"句柄"这个词用了几种不同的方式,与 TensorFlow 使用的术语略有不同。该论文使用 "符号句柄" 来指代 tf.Tensor 对象,并使用 "持久、可变句柄" 来指代 tf.Variable 对象。TensorFlow 代码库使用 "句柄" 来指代具有状态的对象(如 tf.FIFOQueuetf.TensorArray),它可以传递而无需复制所有值(即 按引用调用)。

  3. 我对张量的内部实现的最初假设是否正确?

    您的假设最接近(C++)tensorflow::Tensor 对象的定义。 (Python)tf.Tensor 对象更加复杂,因为它引用计算值的函数,而不是值本身。

  4. 张量和变量之间的内部实现差异是什么?

    在 C++ 中,tensorflow::Tensortensorflow::Var 非常相似;唯一的区别是 tensorflow::Var 还有一个可用于在更新时锁定变量的 mutex

    在 Python 中,本质上的区别在于 tf.Tensor 作为数据流图实现,并且是只读的(即通过调用 tf.Session.run())。tf.Variable 既可以被读取(例如通过评估其读取操作),也可以被写入(例如通过运行分配操作)。

    它们为什么声明不同,并且这种差异对 TensorFlow 很重要吗?

    张量和变量具有不同的用途。张量(tf.Tensor 对象)可以表示数学表达式的复杂组合,例如神经网络中的损失函数或符号梯度。变量表示随时间更新的状态,例如训练过程中的权重矩阵和卷积滤波器。虽然原则上您可以不使用变量来表示模型的演变状态,但您最终会得到一个非常大(且重复)的数学表达式,因此变量提供了一种方便的方式来实现模型的状态,并且 - 例如 - 与其他机器共享以进行并行训练。


这是一份非常有启发性的解释,感谢您提供。如果我理解正确,张量的只读状态很有用,因为它们用于表示中间操作,这些操作与模型的最终状态无关。 这是否是我们将卷积参数的内核存储为tf.Variable的原因相同,以便在更新期间稍后编写并稍后存储? - Ujjwal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接