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())