graph即tf.Graph()
,session即tf.Session()
,不少人常常將二者混淆,其實兩者徹底不是同一個東西。python
TensorFlow是一種符號式編程框架,首先要構造一個圖(graph),而後在這個圖上作運算。打個比方,graph就像一條生產線,session就像生產者。生產線具備一系列的加工步驟(加減乘除等運算),生產者把原料投進去,就能獲得產品。不一樣生產者均可以使用這條生產線,只要他們的加工步驟是同樣的就行。一樣的,一個graph能夠供多個session使用,而一個session不必定須要使用graph的所有,能夠只使用其中的一部分。編程
g = tf.Graph() a = tf.constant(2) b = tf.constant(3) x = tf.add(a, b)
上面就定義了一個graph。tensorflow會默認給咱們創建一個graph,因此g = tf.Graph()
這句實際上是能夠省略的。上面的graph包含3個操做,即op,但凡是op,都須要經過session運行以後,才能獲得結果。若是你直接執行print(a)
,那麼輸出結果是:安全
Tensor("a:0", shape=(), dtype=int32)
是一個張量(Tensor)。若是你執行print(tf.Session().run(a))
,才能獲得2.session
你能夠定義多個graph,例如一個graph實現z = x + y,另外一個graph實現u = 2 * v框架
g1 = tf.Graph() g2 = tf.Graph() with g1.as_default(): x = tf.constant(2) y = tf.constant(3) z = tf.add(x, y) with g2.as_default(): v = tf.constant(4) u = tf.mul(2, v)
但一般不建議這麼作,緣由以下:函數
事實上,你能夠把全部的op都定義在一個graph中:翻譯
x = tf.constant(2) y = tf.constant(3) z = tf.add(x, y) v = tf.constant(4) u = tf.mul(2, v)
從上面graph的定義能夠看到,x/y/z是一波,u/v是另外一波,兩者沒有任何交集。這至關於在一個graph裏有兩個獨立的subgraph。當你要計算z = x + y時,執行tf.Session().run(z)
;當你想計算u = 2 * v,就執行tf.Session().run(u)
,兩者徹底獨立。但更重要的是,兩者在同一個session上運行,系統會均衡地給兩個subgraph分配合適的計算資源。code
一般咱們會顯示地定義一個session來運行graph:orm
x = tf.constant(2) y = tf.constant(3) z = tf.add(x, y) with tf.Session() as sess: result = sess.run(z) print(result)
輸出結果是5。內存
tensorflow是一個符號式編程的框架,首先要定義一個graph,而後用一個session來運行這個graph獲得結果。graph就是由一系列op構成的。上面的tf.constant()
,tf.add()
,tf.mul()
都是op,都要現用session運行,才能獲得結果。
不少人會覺得tf.Variable()
也是op,其實不是的。tensorflow裏,首字母大寫的類,首字母小寫的纔是op。tf.Variable()
就是一個類,不過它包含了各類op,好比你定義了x = tf.Variable([2, 3], name = 'vector')
,那麼x就具備以下op:
tf.Variable()
必須先初始化,再作運算,不然會報錯。下面的寫法就不是很安全,容易致使錯誤:
W = tf.Variable(tf.truncated_normal([700, 10])) U = tf.Variable(2 * W)
要把W賦值給U,必須現把W初始化。但不少人每每忘記初始化,從而出錯。保險起見,應該按照下面這樣寫:
W = tf.Variable(tf.truncated_normal([700, 10])) U = tf.Variable(2 * W.intialized_value())
placeholder,翻譯過來就是佔位符。其實它相似於函數裏的自變量。好比z = x + y,那麼x和y就能夠定義成佔位符。佔位符,顧名思義,就這是佔一個位子,平時不用關心它們的值,當你作運算的時候,你再把你的數據灌進去就好了。是否是和自變量很像?看下面的代碼:
a = tf.placeholder(tf.float32, shape=[3]) # a是一個3維向量 b = tf.constant([5, 5, 5], tf.float32) c = a + b with tf.Session() as sess: print sess.run(c, feed_dict = {a: [1, 2, 3]}) # 把[1, 2, 3]灌到a裏去
輸出結果是[6, 7, 8]。上面代碼中出現了feed_dict
的概念,其實就是用[1, 2, 3]代替a的意思。至關於在本輪計算中,自變量a的取值爲[1, 2, 3]。其實不只僅是tf.placeholder
才能夠用feed_dict
,不少op均可以。只要tf.Graph.is_feedable(tensor)
返回值是True,那麼這個tensor就可用用feed_dict來灌入數據。
tf.constant()
是直接定義在graph裏的,它是graph的一部分,會隨着graph一塊兒加載。若是經過tf.constant()
定義了一個維度很高的張量,那麼graph佔用的內存就會變大,加載也會變慢。而tf.placeholder
就沒有這個問題,因此若是數據維度很高的話,定義成tf.placeholder
是更好的選擇。