TensorFlow核心概念之計算圖

什么是計算圖

??什么計算圖呢?計算圖跟圖計算不一樣,圖計算是對基于圖數據的計算的統稱。而計算圖是對一系列計算和數據流轉編排之后形成的有向無環圖的描述。搞過大數據的應該都對大數據的調度及依賴任務編排比較熟悉,我們會將前后依賴的任務進配置,設置個任務間的依賴關系,然后形成了一個關于各種數據加工和依賴任務的有向無環圖(DAG),在這個有向無環圖中,圖中的頂點(Vertex、Node)是一個個用于執行某種計算的任務,頂點直接的關系(Relationship也就是邊,Edge)有的是數據流轉,有的是任務依賴。其實TensorFlow中的計算圖也基本上類似與這種有DAG圖。
??通常一個機器學習任務的核心是定義模型和求解參數,在對模型定義和參數求解過程進行抽象之后,在確定了數據的流轉方式、數據的計算方式以及各種計算之間的相互依賴關系之后,就可以確定一個唯一的計算執行邏輯,然后將這個計算執行邏輯用圖表示,最后我們稱這個有向無環圖為計算圖。
??TensorFlow中的計算圖由點(nodes)和邊(edges)組成,節點表示算子,邊表示算子間的依賴或數據(一般是張量)的傳遞方向,其中實線表示有數據傳遞依賴,傳遞的數據即為張量;而虛線通常表示控制依賴,即執行先后順序,不存在數據傳遞依賴。所有的節點都通過邊連接,其中入度為0的節點沒有前置依賴,可以立即執行;入度大于0的節點,要等待其前置依賴的所有節點執行結束之后才能執行。下圖就是TensorFlow中一個簡單的計算圖示例:

Compute Graph

??計算圖創建好了之后,TensorFlow就會需要啟動Session去執行計算圖,在TensorFlow中,一個Session可以執行多個計算圖,每個計算圖之間的執行相互獨立。計算圖的執行參考了拓撲排序的思想,關于拓撲排序,如果有不清楚的,可以參考我的另外一篇文章——直觀理解:拓撲排序。計算圖G的執行大體可以分為如下4個步驟:

  • a. 以節點id(node_id)作為key、入度(in_degree)作為value創建哈希表map,并將計算圖G中的所有節點(nodes)加入map中。
  • b. 為計算圖G創建一個可執行節點隊列queue,將map中入度為0的節點加入queue,并從map中刪除這些節點。
  • c. 依次執行queue中的每一個節點,執行成功之后將此節點輸出指向的節點的入度減1,更新map中對應節點的入度。
  • d. 重復步驟b和c,直至queue為空。

??TensorFlow在發展過程中一共提供了三種計算圖的構建方式,分別是靜態計算圖、動態計算圖和AutoGraph。其中靜態計算圖的構建是TensorFlow在1.0提供的基礎功能,但是原生的靜態圖構建這個功能在TensorFlow2.0之后被棄用,但為了保持對1.0版本的兼容,TensorFlow2.0在compat包中提供了兼容1.0版本的靜態圖構建方式。關于三種計算圖的構建方式的優劣及不同,我們在后面按章節進行詳細講解。

靜態計算圖

??TensorFlow1.0是采用靜態計算圖的方式來構建計算圖,需先用TensorFlow中的各種算子創建計算圖,然后開啟一個Session來顯式地執行計算圖。TensorFlow2.0為了保證對TensorFlow1.0項目的兼容性,在tf.compat.v1子模塊中保留了對TensorFlow1.0提供的靜態計算圖構建方式的支持。但是在TensorFlow2.0中,這種靜態圖的構建方式已經不被推薦,后面漸漸可能會被舍棄。下面我們以兼容包里的靜態計算圖構建方式來展示靜態計算圖的構建方式。代碼如下:

import tensorflow as tf

#定義靜態計算圖g
g = tf.compat.v1.Graph()
with g.as_default():
    #placeholder為占位符,會話執行的時候會填充具體的對象內容
    x = tf.compat.v1.placeholder(name='x', shape=[], dtype=tf.string)
    y = tf.compat.v1.placeholder(name='y', shape=[], dtype=tf.string)
    z = tf.strings.join([x, y], name="join", separator=" ")

#開啟一個session,執行計算圖g
result = None
with tf.compat.v1.Session(graph=g) as sess:
    # fetches的結果非常像一個函數的返回值,而feed_dict中的占位符相當于函數的參數序列。
    result = sess.run(fetches=z, feed_dict={x:"Hello", y:"World!"})

#打印計算結果
tf.print(result)

結果如下:

b'Hello World!'

動態計算圖

??動態計算圖,也稱之為Eager Execution,其和靜態計算圖最大的區別在于,動態計算圖無需顯式的定義計算圖,然后開啟個session來執行,在動態計算圖中,默認開啟session,所有的算子定義之后立即執行。示例代碼如下:

# 動態計算圖在每個算子構建后立即執行
x = tf.constant("Hello")
tf.print("x:", x)
y = tf.constant("World!")
tf.print("y:", y)

result = tf.strings.join([x, y], separator=" ")
tf.print("result:", result)

結果如下:

x: "Hello"
y: "World!"
result: "Hello World!"

另外,從模塊化和函數化編程的角度出發,也可以將上述的動態計算圖進行函數化封裝,從而將計算圖的輸入和輸出封裝在一個函數里面,示例代碼如下:

# 將x,y及result的輸入輸出關系封裝成函數
def str_join(x,y):
    tf.print("x:", x)
    tf.print("y:", y)
    return tf.strings.join([x, y], separator=" ")

result = str_join(tf.constant("Hello"), tf.constant("World!"))
tf.print("result:", result)

結果如下:

x: "Hello"
y: "World!"
result: "Hello World!"

AutoGraph

??使用動態計算圖(Eager Execution)的好處是方便代碼調試,因為所有的中間過程可以在寫代碼過程中立即執行并顯示結果。但是動態計算圖的運行效率相對較低,因為Eager Execution會有許多次Python進程和TensorFlow的C++進程之間的通信。而靜態計算圖構建完成之后幾乎全部在TensorFlow內核上使用C++代碼執行,無需與Python進程頻繁進行交互通信,因而效率更高。此外靜態圖會對計算步驟進行一定的優化,省略和結果無關的計算步驟。鑒于此,TensorFlow2.0提供了tf.function讓算子從 Eager Execution 切換到靜態計算圖執行。可以使用@tf.function注解將普通Python函數轉換成對應的TensorFlow計算圖,而調用該函數就相當于在TensorFlow1.0中開啟一個Session執行計算圖。這種使用tf.function構建靜態圖的方式就叫做 Autograph。
??在TensorFlow2.0中,如果采用Autograph的方式使用計算圖,第一步需要定義函數,第二步調用函數。無需顯示定義計算圖,然后顯式地開啟session去執行計算圖,執行計算圖變得跟Python中函數的定義和調用一樣簡單。下面用代碼來展示采用Autograph的計算圖執行方式,代碼如下:

import tensorflow as tf

# 使用autograph構建靜態圖
@tf.function
def str_join(x, y):
    tf.print("x:", x)
    tf.print("y:", y)
    return tf.strings.join([x, y], separator=" ")

# 調用函數@tf.function裝飾的函數,執行計算圖
result = str_join(tf.constant("Hello"), tf.constant("World!"))
tf.print("result:", result)

結果如下:

hello world
tf.Tensor(b'hello world', shape=(), dtype=string)

三種計算圖對比

??靜態計算圖,動態計算圖和AutoGraph在執行效率和編程體驗兩方面各有取舍。原始的使用靜態計算圖需要嚴格分兩步,第一步定義計算圖,第二步在會話中執行計算圖。而在TensorFlow2.0中,在兼容原始靜態圖構建方式的同時,新推出了采用Autograph的方式使用計算圖,使得計算圖的定義和使用分別變成了定義函數和調用函數,兼顧效率的同時,極大的提升了編程體驗和效率。關于三種計算圖的比較,分別從定義、執行和效率三個方面做了簡單的總結:

  • 定義:靜態計算圖需要嚴格遵循先定義,后使用的原則,定義過程比較麻煩;而動態計算圖和AutoGraph的計算圖定義更接近普通的Python任務編程,定義過程比較簡單。
  • 執行:靜態計算圖需要顯示開啟session后執行,比較麻煩;動態計算圖無需顯示執行,可以即刻執行并查看中間結果;AutoGraph調用函數即可執行,簡單易用,調用后會在后臺會按照靜態圖一樣的方式執行。
  • 效率:靜態計算圖后臺有優化策略,效率最高;AutoGraph裝飾后的函數也按靜態圖的方式去執行;動態計算圖由于Eager Execution,C++內核和Python內核需要進行頻繁的交互,效率最低。
TensorFlow系列文章:
  1. TensorFlow核心概念之Tensor(1):張量創建
  2. TensorFlow核心概念之Tensor(2):索引切片
  3. TensorFlow核心概念之Tensor(3):變換拆合
  4. TensorFlow核心概念之Tensor(4):張量運算
  5. TensorFlow核心概念之計算圖
  6. TensorFlow核心概念之Autograph
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,572評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,071評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,409評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,569評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,360評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,895評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,979評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,123評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,643評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,559評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,742評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,250評論 5 356
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,981評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,363評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,622評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,354評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,707評論 2 370

推薦閱讀更多精彩內容