TensorFlow使用数据流图将计算表示为独立的指令之间的依赖关系。这可生成低级别的编程模型,在该模型中,您首先定义数据流图,而后建立TensorFlow会话,以便在一组本地和远程设备上运行图的各个部分。python
若是您计划直接使用低级别编程模型,,本指南将是您最实用的参考资源。较高阶的API(例如tf.estimator.Estimator和Keras)会向最终用户隐去图和会话的细节内容,但若是您但愿理解这些API的实现方式,本指南仍会对你有所帮助。算法
数据流是一种用于并行计算的经常使用编程模型。在数据流图中,节点表示计算单元,边表示计算使用或产生的数据。例如,在TensorFlow图中,tf.matmul操做对应于单个节点,该节点具备两个传入边(要相乘的矩阵)和一个传出边(乘法的结果)。编程
在执行您的程序时,数据流能够为TensorFlow提供多项优点:c#
tf.Graph包含两类相关信息:api
大多数TensorFlow程序都以数据流图构建阶段开始。在此阶段,您会调用TensorFlow API函数,这些函数能够构建新的tf.Operation(节点)和tf.Tensor(边)对象并将它们添加到tf.Graph实例中。TensorFlow提供了默认图,此图是同一上下文中的全部API函数的明确参数。例如:数组
大多数程序仅依赖默认图。尽管如此,请参阅处理多个图了解更加高级的用例。高阶API(好比 tf.estimator.Estimator API)可替您管理默认图,而且还具备其它功能,例如建立不一样的图以用于训练和评估。浏览器
注意:调用 TensorFlow API 中的大多数函数只会将操做和张量添加到默认图中,而不会执行实际计算。您应编写这些函数,直到拥有表示整个计算(例如执行梯度降低法的一步)的 tf.Tensor
或 tf.Operation
,而后将该对象传递给 tf.Session
以执行计算。更多详情请参阅“在 tf.Session
中执行图”部分。缓存
tf.Graph 对象会定义一个命名空间(为其包含的 tf.Operation对象)。TensorFlow会自动为您的图中的每一个指令选择一个惟一名称,但您也能够指定描述性名称,使您的程序阅读和调试起来更轻松。TensorFlow API提供两种方法来覆盖操做名称:服务器
1 c_0 = tf.constant(0, name="c") # => operation named "c" 2 3 # Already-used names will be "uniquified". 4 c_1 = tf.constant(2, name="c") # => operation named "c_1" 5 6 # Name scopes add a prefix to all operations created in the same context. 7 with tf.name_scope("outer"): 8 c_2 = tf.constant(2, name="c") # => operation named "outer/c" 9 10 # Name scopes nest like paths in a hierarchical file system. 11 with tf.name_scope("inner"): 12 c_3 = tf.constant(3, name="c") # => operation named "outer/inner/c" 13 14 # Exiting a name scope context will return to the previous prefix. 15 c_4 = tf.constant(4, name="c") # => operation named "outer/c_1" 16 17 # Already-used name scopes will be "uniquified". 18 with tf.name_scope("inner"): 19 c_5 = tf.constant(5, name="c") # => operation named "outer/inner_1/c"
图可视化工具使用名称范围来为指令分组并下降图的视觉复杂性。更多信息请参阅可视化您的图网络
请注意,tf.Tensor对象以输出张量的 tf.Operation明确命名。张量名称的形式为 “<OP_NAME>:<i>”,其中:
若是您但愿TensorFlow程序使用多台不一样的设备,则可使用 tf.device函数轻松地请求在特定上下文中建立的全部操做放置到同一设备(或同一类型的设备)上。
设备规范具备如下形式:
1 /job:<JOB_NAME>/task:<TASK_INDEX>/device:<DEVICE_TYPE>:<DEVICE_INDEX>
其中:
您无需指定设备规范的每一个部分。例如,若是您在单个GPU的单机器配置中运行,您可使用 tf.device 将一些操做固定到CPU和GPU上:
1 # Operations created outside either context will run on the "best possible" 2 # device. For example, if you have a GPU and a CPU available, and the operation 3 # has a GPU implementation, TensorFlow will choose the GPU. 4 weights = tf.random_normal(...) 5 6 with tf.device("/device:CPU:0"): 7 # Operations created in this context will be pinned to the CPU. 8 img = tf.decode_jpeg(tf.read_file("img.jpg")) 9 10 with tf.device("/device:GPU:0"): 11 # Operations created in this context will be pinned to the GPU. 12 result = tf.matmul(weights, img)
若是您在典型的分布式配置中部署TensorFlow,您能够指定做业名称和任务ID,以便将变量放到参数服务器做业(“/job:ps”)中的任务上,并将其它操做放置到工做器做业(“job/worker”)中的任务上:
1 with tf.device("/job:ps/task:0"): 2 weights_1 = tf.Variable(tf.truncated_normal([784, 100])) 3 biases_1 = tf.Variable(tf.zeroes([100])) 4 5 with tf.device("/job:ps/task:1"): 6 weights_2 = tf.Variable(tf.truncated_normal([100, 10])) 7 biases_2 = tf.Variable(tf.zeroes([10])) 8 9 with tf.device("/job:worker"): 10 layer_1 = tf.matmul(train_batch, weights_1) + biases_1 11 layer_2 = tf.matmul(train_batch, weights_2) + biases_2
借助 tf.device,您能够高度灵活地选择单个操做或TensorFlow图地各个区域的放置方式。在不少状况下,简单的启发法具备良好的效果。例如,tf.train.replica_device_setter API可与tf.device 结合使用,以针对数据分布式训练放置操做。例如,如下代码段展现了 tf.train.replica_device_setter如何将不一样放置策略应用于 tf.Variable对象和其它操做:
1 with tf.device(tf.train.replica_device_setter(ps_tasks=3)): 2 # tf.Variable objects are, by default, placed on tasks in "/job:ps" in a 3 # round-robin fashion. 4 w_0 = tf.Variable(...) # placed on "/job:ps/task:0" 5 b_0 = tf.Variable(...) # placed on "/job:ps/task:1" 6 w_1 = tf.Variable(...) # placed on "/job:ps/task:2" 7 b_1 = tf.Variable(...) # placed on "/job:ps/task:0" 8 9 input_data = tf.placeholder(tf.float32) # placed on "/job:worker" 10 layer_0 = tf.matmul(input_data, w_0) + b_0 # placed on "/job:worker" 11 layer_1 = tf.matmul(layer_0, w_1) + b_1 # placed on "/job:worker"
许多TensorFlow操做都会接受一个或多个 tf.Tensor对象做为参数。例如,tf.matmul 接受两个tf.Tensor对象,tf.add_n 接受一个具备n个 tfTensor对象的列表。为了方便起见,这些函数将接受类张量对象来取代tf.Tensor,并将它明确转换为tf.Tensor(经过tf.convert_to_tensor 方法)。类张量对象包括如下类型的元素:
您可使用 tf.register_tensor_conversion_function 注册其它类张量类型。
注意:默认状况下,每次您使用同一个类张量对象时,TensorFlow 将建立新的 tf.Tensor
。若是类张量对象很大(例如包含一组训练样本的 numpy.ndarray
),且您屡次使用该对象,则可能会耗尽内存。要避免出现此问题,请在类张量对象上手动调用 tf.convert_to_tensor
一次,并使用返回的 tf.Tensor
。
TensorFlow 使用tf.Session 类来表示客户端程序(一般为Python程序,但也提供了其它语言的相似接口)与C++运行时之间的链接。tf.Session对象使得咱们可以访问本地机器中的设备和使用分布式TensorFlow运行时的远程设备。它还能够缓存关于 tf.Graph的信息,使您可以屡次高效地运行同一计算。
若是您使用的是低阶TensorFlow API,您能够为当前默认图建立一个tf.Session,以下所示:
1 # Create a default in-process session. 2 with tf.Session() as sess: 3 # ... 4 5 # Create a remote session. 6 with tf.Session("grpc://example.org:2222"): 7 # ...
因为tf.Session拥有物理资源(例如GPU和网络链接),所以一般(在with代码块中)用做上下文管理器,并在您退出代码时自动关闭会话。您也能够在不使用 with 代码块的状况下建立会话,但应在完成会话时明确调用 tf.Session.close 以便释放资源。
注意:较高阶的 API(例如 tf.train.MonitoredTrainingSession
或 tf.estimator.Estimator
)将为您建立和管理 tf.Session
。这些 API 接受可选的 target
和 config
参数(直接接受,或做为 tf.estimator.RunConfig
对象的一部分),并具备相同的含义,以下所示。
tf.Session.init 接受三个可选参数:
tf.Session.run方法是运行 tf.Operation或评估 tf.Tensor的主要机制。您能够将一个或多个 tf.Operation或 tf.Tensor对象传递到 tf.Session.run,TensorFlow将执行计算结果所须要的操做。
tf.Session.run 要求您指定一组fetch,这些fetch能够肯定返回值,而且多是 tf.Operation、tf.Tensor或类张量类型,例如tf.Variable。这些fetch决定了必须执行哪些子图(属于总体tf.Graph)以生成结果:该子图包含fetch列表中指定的全部操做,以及其输出用于计算fetch值的全部操做。例如,如下代码段说明了 tf.Session.run 的不一样参数如何致使执行不一样的子图:
1 x = tf.constant([[37.0, -23.0], [1.0, 4.0]]) 2 w = tf.Variable(tf.random_uniform([2, 2])) 3 y = tf.matmul(x, w) 4 output = tf.nn.softmax(y) 5 init_op = w.initializer 6 7 with tf.Session() as sess: 8 # Run the initializer on `w`. 9 sess.run(init_op) 10 11 # Evaluate `output`. `sess.run(output)` will return a NumPy array containing 12 # the result of the computation. 13 print(sess.run(output)) 14 15 # Evaluate `y` and `output`. Note that `y` will only be computed once, and its 16 # result used both to return `y_val` and as an input to the `tf.nn.softmax()` 17 # op. Both `y_val` and `output_val` will be NumPy arrays. 18 y_val, output_val = sess.run([y, output])
tf.Session.run 也能够选择接受feed字典,该字典是从 tf.Tensor对象(一般是 tf.placeholder张量)到在执行时会替换这些张量的值(一般是Python标量、列表或Numpy数组)的映射。例如:
1 # Define a placeholder that expects a vector of three floating-point values, 2 # and a computation that depends on it. 3 x = tf.placeholder(tf.float32, shape=[3]) 4 y = tf.square(x) 5 6 with tf.Session() as sess: 7 # Feeding a value changes the result that is returned when you evaluate `y`. 8 print(sess.run(y, {x: [1.0, 2.0, 3.0]})) # => "[1.0, 4.0, 9.0]" 9 print(sess.run(y, {x: [0.0, 0.0, 5.0]})) # => "[0.0, 0.0, 25.0]" 10 11 # Raises <a href="../api_docs/python/tf/errors/InvalidArgumentError"><code>tf.errors.InvalidArgumentError</code></a>, because you must feed a value for 12 # a `tf.placeholder()` when evaluating a tensor that depends on it. 13 sess.run(y) 14 15 # Raises `ValueError`, because the shape of `37.0` does not match the shape 16 # of placeholder `x`. 17 sess.run(y, {x: 37.0})
tf.Session.run也接受可选的options参数(容许您指定和调用相关的选项)和可选的 run_metadata 参数(容许您收集和执行有关的元数据)。例如,您能够同时使用这些选项来收集与执行有关的跟踪信息:
1 y = tf.matmul([[37.0, -23.0], [1.0, 4.0]], tf.random_uniform([2, 2])) 2 3 with tf.Session() as sess: 4 # Define options for the `sess.run()` call. 5 options = tf.RunOptions() 6 options.output_partition_graphs = True 7 options.trace_level = tf.RunOptions.FULL_TRACE 8 9 # Define a container for the returned metadata. 10 metadata = tf.RunMetadata() 11 12 sess.run(y, options=options, run_metadata=metadata) 13 14 # Print the subgraphs that executed on each device. 15 print(metadata.partition_graphs) 16 17 # Print the timings of each operation that executed. 18 print(metadata.step_stats)
TensorFlow包含可帮您理解图中代码的工具。图可视化工具是TensorBoard的一个组件,可在浏览器中可视化图的结构。要建立可视化图表,最简单的方法是传递tf.Graph(在建立 tf.summary.FileWriter时):
1 # Build your graph. 2 x = tf.constant([[37.0, -23.0], [1.0, 4.0]]) 3 w = tf.Variable(tf.random_uniform([2, 2])) 4 y = tf.matmul(x, w) 5 # ... 6 loss = ... 7 train_op = tf.train.AdagradOptimizer(0.01).minimize(loss) 8 9 with tf.Session() as sess: 10 # `sess.graph` provides access to the graph used in a <a href="../api_docs/python/tf/Session"><code>tf.Session</code></a>. 11 writer = tf.summary.FileWriter("/tmp/log/...", sess.graph) 12 13 # Perform your computation... 14 for i in range(1000): 15 sess.run(train_op) 16 # ... 17 18 writer.close()
注意:若是您使用的是 tf.estimator.Estimator
,图(以及任何汇总)将自动记录到您在建立 Estimator 时指定的 model_dir
中。
随后,您能够在 tensorboard中打开日志并转到“图"标签,查看图结构的概要可视化图表。请注意,典型的TensorFlow图(尤为是具备自动计算的梯度的训练图)包含的节点太多,没法一次性完成直观的展现。图可视化工具使用名称范围来将相关指令分组到”超级节点“中。您能够点击任意超级节点上的橙色”+“按钮以展开内部的子图。
要详细了解如何使用TensorBoard可视化TensorFlow应用,请参阅TensorBoard指南。
注意:训练模型时,整理代码的一种经常使用方法是使用一个图训练模型,而后使用另外一个图对训练过的模型进行评估或推理。在许多状况下,推理图与训练图不一样:例如,丢弃和批次标准化等技术在每种情形下使用不一样的操做。此外,默认状况下,tf.train.Saver
等实用程序使用 tf.Variable
对象的名称(此类对象的名称基于底层 tf.Operation
)来识别已保存检查点中的每一个变量。采用这种方式编程时,您可使用彻底独立的 Python 进程来构建和执行图,或者在同一进程中使用多个图。此部分介绍了如何在同一进程中使用多个图。
如上所述,TensorFlow提供了一个”默认图“,此图明确传递给同一上下文中的全部API函数。对于许多应用而言,单个图便以足够。可是,TensorFlow还提供了操做默认图的方法,在更高级的用例中,这些方法可能有用。例如:
您能够安装另外一个 tf.Graph做为默认图(使用 tf.Graph.as_default 上下文管理器):
1 g_1 = tf.Graph() 2 with g_1.as_default(): 3 # Operations created in this scope will be added to `g_1`. 4 c = tf.constant("Node in g_1") 5 6 # Sessions created in this scope will run operations from `g_1`. 7 sess_1 = tf.Session() 8 9 g_2 = tf.Graph() 10 with g_2.as_default(): 11 # Operations created in this scope will be added to `g_2`. 12 d = tf.constant("Node in g_2") 13 14 # Alternatively, you can pass a graph when constructing a <a href="../api_docs/python/tf/Session"><code>tf.Session</code></a>: 15 # `sess_2` will run operations from `g_2`. 16 sess_2 = tf.Session(graph=g_2) 17 18 assert c.graph is g_1 19 assert sess_1.graph is g_1 20 21 assert d.graph is g_2 22 assert sess_2.graph is g_2
要检查当前的默认图,请调用 tf.get_default_graph,它会返回一个tf.Graph对象:
1 # Print all of the operations in the default graph. 2 g = tf.get_default_graph() 3 print(g.get_operations())