簡介
上一篇筆記:Tensorflow學習筆記1:Get Started 我們談到Tensorflow是基於圖(Graph)的計算系統。而圖的節點則是由操作(Operation)來構成的,而圖的各個節點之間則是由張量(Tensor)作為邊來連接在一起的。所以Tensorflow的計算過程就是一個Tensor流圖。Tensorflow的圖則是必須在一個Session中來計算。這篇筆記來大致介紹一下Session、Graph、Operation和Tensor。
Session
Session提供了Operation執行和Tensor求值的環境。如下面所示,
import tensorflow as tf # Build a graph. a = tf.constant([1.0, 2.0]) b = tf.constant([3.0, 4.0]) c = a * b # Launch the graph in a session. sess = tf.Session() # Evaluate the tensor 'c'. print sess.run(c) sess.close() # result: [3., 8.]
一個Session可能會擁有一些資源,例如Variable或者Queue。當我們不再需要該session的時候,需要將這些資源進行釋放。有兩種方式,
- 調用session.close()方法;
- 使用with tf.Session()創建上下文(Context)來執行,當上下文退出時自動釋放。
上面的例子可以寫成,
import tensorflow as tf # Build a graph. a = tf.constant([1.0, 2.0]) b = tf.constant([3.0, 4.0]) c = a * b with tf.Session() as sess: print sess.run(c)
Session類的構造函數如下所示:
tf.Session.__init__(target='', graph=None, config=None)
如果在創建Session時沒有指定Graph,則該Session會加載默認Graph。如果在一個進程中創建了多個Graph,則需要創建不同的Session來加載每個Graph,而每個Graph則可以加載在多個Session中進行計算。
執行Operation或者求值Tensor有兩種方式:
-
調用Session.run()方法: 該方法的定義如下所示,參數fetches便是一個或者多個Operation或者Tensor。
tf.Session.run(fetches, feed_dict=None)
-
調用Operation.run()或則Tensor.eval()方法: 這兩個方法都接收參數session,用於指定在哪個session中計算。但該參數是可選的,默認為None,此時表示在進程默認session中計算。
那如何設置一個Session為默認的Session呢?有兩種方式:
1. 在with語句中定義的Session,在該上下文中便成為默認session;上面的例子可以修改成:
import tensorflow as tf # Build a graph. a = tf.constant([1.0, 2.0]) b = tf.constant([3.0, 4.0]) c = a * b with tf.Session(): print c.eval()
2. 在with語句中調用Session.as_default()方法。 上面的例子可以修改成:
import tensorflow as tf # Build a graph. a = tf.constant([1.0, 2.0]) b = tf.constant([3.0, 4.0]) c = a * b sess = tf.Session() with sess.as_default(): print c.eval() sess.close()
Graph
Tensorflow中使用tf.Graph類表示可計算的圖。圖是由操作Operation和張量Tensor來構成,其中Operation表示圖的節點(即計算單元),而Tensor則表示圖的邊(即Operation之間流動的數據單元)。
tf.Graph.__init__()
創建一個新的空Graph
在Tensorflow中,始終存在一個默認的Graph。如果要將Operation添加到默認Graph中,只需要調用定義Operation的函數(例如tf.add())。如果我們需要定義多個Graph,則需要在with語句中調用Graph.as_default()方法將某個graph設置成默認Graph,於是with語句塊中調用的Operation或Tensor將會添加到該Graph中。
例如,
import tensorflow as tf g1 = tf.Graph() with g1.as_default(): c1 = tf.constant([1.0]) with tf.Graph().as_default() as g2: c2 = tf.constant([2.0]) with tf.Session(graph=g1) as sess1: print sess1.run(c1) with tf.Session(graph=g2) as sess2: print sess2.run(c2) # result: # [ 1.0 ] # [ 2.0 ]
如果將上面例子的sess1.run(c1)和sess2.run(c2)中的c1和c2交換一下位置,運行會報錯。因為sess1加載的g1中沒有c2這個Tensor,同樣地,sess2加載的g2中也沒有c1這個Tensor。
Operation
一個Operation就是Tensorflow Graph中的一個計算節點。其接收零個或者多個Tensor對象作為輸入,然后產生零個或者多個Tensor對象作為輸出。Operation對象的創建是通過直接調用Python operation方法(例如tf.matmul())或者Graph.create_op()。
例如c = tf.matmul(a, b)
表示創建了一個類型為MatMul的Operation,該Operation接收Tensor a和Tensor b作為輸入,而產生Tensor c作為輸出。
當一個Graph加載到一個Session中,則可以調用Session.run(op)來執行op,或者調用op.run()來執行(op.run()是tf.get_default_session().run()的縮寫)。
Tensor
Tensor表示的是Operation的輸出結果。不過,Tensor只是一個符號句柄,其並沒有保存Operation輸出結果的值。通過調用Session.run(tensor)或者tensor.eval()方可獲取該Tensor的值。
關於Tensorflow的圖計算過程
我們通過下面的代碼來看一下Tensorflow的圖計算過程:
import tensorflow as tf a = tf.constant(1) b = tf.constant(2) c = tf.constant(3) d = tf.constant(4) add1 = tf.add(a, b) mul1 = tf.mul(b, c) add2 = tf.add(c, d) output = tf.add(add1, mul1) with tf.Session() as sess: print sess.run(output)
# result: 9
上面的代碼構成的Graph如下圖所示,
當Session加載Graph的時候,Graph里面的計算節點都不會被觸發執行。當運行sess.run(output)的時候,會沿着指定的Tensor output來進圖路徑往回觸發相對應的節點進行計算(圖中紅色線表示的那部分)。當我們需要output的值時,觸發Operation tf.add(add1, mul1)被執行,而該節點則需要Tensor add1和Tensor mul1的值,則往回觸發Operation tf.add(a, b)和Operation tf.mul(b, c)。以此類推。
所以在計算Graph時,並不一定是Graph中的所有節點都被計算了,而是指定的計算節點或者該節點的輸出結果被需要時。
(done)