常见问题

此文档对关于TensorFlow的一些常见问题提供了答案,如果这里没有你问题的答案,你可能会在社区资源中找到它。

内容

常见问题

建立 TensorFlow graph

参看
建立 graph 的 API 文档.

为什么c = tf.matmul(a, b) 不立即执行矩阵相乘?

在 TensorFlow 的 Python API 中, a, b, and c 都是
Tensor 对象. 一个 Tensor 对象是一个操作(operation)结果的字符别名,它实际上并不储存操作(operation)输出结果的值。
TensorFlow 鼓励用户去建立复杂的表达式(如整个神经网络及其梯度)来形成 data flow graph 。
然后你可以将整个 data flow graph 的计算过程交给一个 TensorFlow 的 Session,
Session 可以运行整个计算过程,比起操作(operations)一条一条的执行效率高的多。

设备是如何命名的?

对CPU设备而言,支持的设备名是"/device:CPU:0" (或 "/cup:0"),对第 i 个 GPU 设备是"/device:GPU:i" (或 "/gpu:i")

如何在指定的设备上运行操作(operations)?

with tf.device(name): context 中创建操作(operation),这样可以在指定的设备上运行操作(operation)。
关于 TensorFlow 怎样将操作(operations)分配给设备的细节,参看 TensorFlow使用 GPU ; 使用多 GPU 的示范实例参看 CIFAR-10 教程

可用的 tensor 有哪些不同的类型?

TensorFlow 支持许多种不同的数据类型和 tensor shape ,更多细节请参看 ranks, shapes, and type reference

" class="reference-link">运行 TensorFlow 计算过程。

参看
运行 graph 的 API 文档.

请详细解释 feeding 和 placeholders?

Feeding 是 TensorFlow Session API 的一种机制,它允许你在运行时用不同的值替换一个或多个 tensor 的值。
Session.run() 的参数 feed_dict 是一个字典,
它将 Tensor 对象映射为 numpy 的数组(和一些其他类型)。
在执行 step 时,这些数组就是 tensor 的值。

你常会碰到某些 tensor 总是有值的,比如 inputs。 tf.placeholder() 操作(operation)允许你定义一种必须提供值的 tensor ,你也可以随意限定它们的 shape。关于如何使用 placelolders 和 feeding 为神经网络提供训练数据的例子,请参看初学者的 MNIST 教程

Session.run()Tensor.eval() 有什么区别?

如果 t 是一个 Tensor 对象, t.eval() 就是 sess.run(t)sess 是当前默认 session)的简写。
以下两段小程序是等效的:

  1. # 使用 `Session.run()`.
  2. sess = tf.Session()
  3. c = tf.constant(5.0)
  4. print sess.run(c)
  5. # 使用 `Tensor.eval()`.
  6. c = tf.constant(5.0)
  7. with tf.Session():
  8. print c.eval()

在第二个例子中, session 的作用就象 context manager , context manager 在 with 块的生存期,将 session 作为默认的 session。对简单应用的情形(如单元测试),context manager 的方法可以得到更简洁的代码; 如果你的代码要处理多个 graph 和 session ,更直白的方式可能是显式调用 Session.run()

Sessions 有生存期吗? 调用时产生的 tensors 呢?

Session 能够占有资源,例如 variablesqueues, 和
readers; 这些资源会使用相当大量的内存。 当调用Session.close() 关闭 session 后,这些资源(和相关的内存)就被释放了。

作为调用 Session.run() 过程的一部分所创建的 tensors, 会在调用时或调用结束前释放。

我可以在多个计算机上运行分布式的训练吗?

最初的 TensorFlow 开源版本支持单一计算机内的多设备(CPUs 和 GPUs)。
我们也正在致力于一个分布式的版本:如果你有兴趣,请告知我们,这样我们可以做相应的调整。

运行时会并行计算图的执行的各个部分(parts of graph execution)吗?

TensorFlow 运行时会在许多不同的层面(dimensions)并行图的执行(graph execution):

  • 在一个CPU中用多核或是一个GPU中用多线程来并行许多单独的操作(operation)。
  • 在 TensorFlow graph 中各个独立的节点可以在多个设备上并行,这样就提供了加速的可能。CIFAR-10 用多 GPU 训练.
  • Session API 允许并行执行多并发的 steps (如 调用 Session.run())。
    如果单一的 step 不使用你计算机中所有的资源,这种方法可以使运行时有更高的吞吐量。

TensorFlow 支持哪些客户端编程语言?

TensorFlow 被设计成为支持多种客户端语言。当前支持最好的客户端语言是 PythonC++ 客户端 API 提供了启动 graph 和运行 steps 的接口; 我们还有一个 用 C++ 建立 graph 的 API,此 API 是实验性的。

从社区的利益出发,我们想要支持更多的客户端语言。 TensorFlow 有一个 基于 C 的客户端 API,它使得用许多不同的语言创建客户端变得很容易。我们请大家在新语言绑定上做出努力。

TensorFlow 会利用我计算机上所有可用的设备(GPUs 和 CPUs)吗?

TensorFlow 支持多 GPU 和 CPU。 有关 TensorFlow 如何将操作(operations)分配到设备的细节请参看 TensorFlow 如何使用 GPUs 的文档,有关使用多 GPU 的示范实例请参看 CIFAR-10 教程

请注意, TensorFlow 只使用计算能力(compute capability)大于 3.5 的 GPU 设备。

当使用一个 reader 或 一个 queue 时,为什么 Session.run() 会挂起?

reader 类和 queue 类提供特殊的操作(operations),这些操作(operations)在有可用的输入(对有界队列则是空闲空间)前会 阻塞 。使用这些操作(operations)你可以创建复杂的输入流水线(input pipelines) ,不过,这会使 TensorFlow 的计算过程更复杂。有关如何使用这些操作(operations)的更多信息请参看 how-to 文档中的使用 QueueRunner 对象来控制 queues 和 readers

Variables

参看 Variables
变量作用域 的 how-to 文档,还有关于变量的 API 文档

变量的生存期是?

在某一 session 中,当你一开始运行 tf.Variable.initializer 操作(operation)时,变量就会被创建。此 session 关闭后它就被摧毁(destroyed)了。

并发读取或存入变量时会是什么情况?

变量可以进行并发的读和写操作(operation)。由于变量是并发(concurrently)更新的, 所以从一个变量中读出的值可能会改变。在不互斥的条件下,对一个变量的并发的许多赋值操作(operation)是默认允许运行的。在对一个变量赋值时,如果想要加锁,可以将 use_locking=True 传递给 Variable.assign()

Tensor shapes

参看
TensorShape API 文档.

在 Python 中我怎么判断一个 tensor 的 shape ?

在 TensorFlow 中,一个 tensor 具备静态和动态两种 shape 。静态的 shape 可以用 tf.Tensor.get_shape() 方法读出:这种 shape 是由此 tensor 在创建时使用的操作(operations)推导得出的,可能是 partially complete 的。如果静态 shape 没有完整定义(not fully defined)的话,则一个 tensor 的动态 shape 可通过求 tf.shape(t) 的值得到。

x.set_shape()x = tf.reshape(x) 有什么区别?

tf.Tensor.set_shape() 方法(method)会更新(updates)一个 Tensor 对象的静态 shape ,当静态 shape 信息不能够直接推导得出的时候,此方法常用来提供额外的 shape 信息。它不改变此 tensor 动态 shape 的信息。

tf.reshape() 操作(operation)会以不同的动态 shape 创建一个新的 tensor。

我怎么创建这样一个 graph ,它在批次大小可变(variable batch sizes)的情形下也可以正常运作?

如果能够创建一个 graph ,在批次大小可变(variable batch sizes)的情形下也可以正常运作将会是十分有用的,例如可以使用相同的代码完成(小)批量训练((mini-)batch training)和单例推导(single-instance inference)。这样生成的 graph 可以保存起来当作协议缓存(protocol buffer),也可以导入至其他的程序

创建一个可变大小的 graph 时,要记住最重要的事情是不要将批次大小(batch size)编码成为 Python 常数,而是用一个字符性(symbolic)的 Tensor 来表示。下面的提示可能会有用:

TensorBoard

我怎样视觉化一个 TensorFlow graph ?

参看 graph 的视觉化教程.

向 TensorBoard 发送数据的最简单的方法是什么?

给你的 TensorFlow graph 增加 summary 操作(ops),接着用 SummaryWriter 将这些 summaries 写入一个 log directory。然后用以下命令启动 TensorBoard 。

  1. `python tensorflow/tensorboard/tensorboard.py --logdir=path/to/log-directory`

更多细节请参看 Summaries 和 TensorBoard 教程

扩展 TensorFlow

参看有关向 TensorFlow 添加新操作(oprations) 的 how-to 文档。

我的数据是自定义格式,要怎样用 TensorFlow 来读取它?

有两种主要的操作(operation)来处理自定义格式的数据。

较简单的方法:用 Python 编写一段分词的代码(parsing code),将数据转换成为 numpy array,然后用此数据把一个 [tf.placeholder()]
(../api_docs/python/io_ops.md#placeholder) 传送给一个 tensor 。更多的细节参见 使用 placeholders 进行输入 的相关文档。这个方法比较容易实现,不过分词的部分会成为性能的瓶颈。

更高效的方法是添加一个用 C++ 编写的操作(op),用这个操作(operation)来对你的数据格式进行分词(parse)。
新数据格式处理指南中有更多相关步骤的信息。

我如何定义操作(operation)使得它能够接受可变数量的输入?

TensorFlow 的操作(operation)注册机制允许你定义几种输入:单独的 tensor,一列相同类型的 tensors (例如把一个可变长列表中的 tensors 相加), 一列不同类型的 tensors (例如将一个 tuple 中的 tensors 入队(enqueue))。有关怎样定义这些不同的输入类型的更多细节,请参看添加具有一列输入或输出的操作(op)的相关文档。

其他问题

TensorFlow 能使用 Python 3 吗?

我们只用 Python 2.7 进行了测试。我们了解对 Python 3 的兼容性来说,还需要有一些修改,欢迎大家朝这个方向多努力。

TensorFlow 的代码风格有什么规则?

TensorFlow Python API 遵循 PEP8 惯例。
* 特别的,我们使用 CamelCase 格式作为类名, snake_case 格式作为方程名, 方法名, 和属性名。我们也遵循
Google Python style guide

TensorFlow C++ 代码遵循 Google C++ style guide

(* 有一条例外: 我们使用 2 空格缩进而不是 4 空格缩进)

原文:Frequently Asked Questions 翻译:Terence Cooper 校对:Wiki