【tensorflow2.0】三種計算圖


有三種計算圖的構建方式:靜態計算圖,動態計算圖,以及Autograph.

在TensorFlow1.0時代,采用的是靜態計算圖,需要先使用TensorFlow的各種算子創建計算圖,然后再開啟一個會話Session,顯式執行計算圖。

而在TensorFlow2.0時代,采用的是動態計算圖,即每使用一個算子后,該算子會被動態加入到隱含的默認計算圖中立即執行得到結果,而無需開啟Session。

使用動態計算圖即Eager Excution的好處是方便調試程序,它會讓TensorFlow代碼的表現和Python原生代碼的表現一樣,寫起來就像寫numpy一樣,各種日志打印,控制流全部都是可以使用的。

使用動態計算圖的缺點是運行效率相對會低一些。因為使用動態圖會有許多次Python進程和TensorFlow的C++進程之間的通信。而靜態計算圖構建完成之后幾乎全部在TensorFlow內核上使用C++代碼執行,效率更高。此外靜態圖會對計算步驟進行一定的優化,剪去和結果無關的計算步驟。

如果需要在TensorFlow2.0中使用靜態圖,可以使用@tf.function裝飾器將普通Python函數轉換成對應的TensorFlow計算圖構建代碼。運行該函數就相當於在TensorFlow1.0中用Session執行代碼。使用tf.function構建靜態圖的方式叫做 Autograph.

一,計算圖簡介

計算圖由節點(nodes)和線(edges)組成。

節點表示操作符Operator,或者稱之為算子,線表示計算間的依賴。

實線表示有數據傳遞依賴,傳遞的數據即張量。

虛線通常可以表示控制依賴,即執行先后順序。

二,靜態計算圖

在TensorFlow1.0中,使用靜態計算圖分兩步,第一步定義計算圖,第二步在會話中執行計算圖。

TensorFlow 1.0靜態計算圖范例

import tensorflow as tf
 
# 定義計算圖
g = tf.Graph()
with g.as_default():
    #placeholder為占位符,執行會話時候指定填充對象
    x = tf.placeholder(name='x', shape=[], dtype=tf.string)  
    y = tf.placeholder(name='y', shape=[], dtype=tf.string)
    z = tf.string_join([x,y],name = 'join',separator=' ')
 
# 執行計算圖
with tf.Session(graph = g) as sess:
    print(sess.run(fetches = z,feed_dict = {x:"hello",y:"world"}))

TensorFlow2.0 懷舊版靜態計算圖

TensorFlow2.0為了確保對老版本tensorflow項目的兼容性,在tf.compat.v1子模塊中保留了對TensorFlow1.0那種靜態計算圖構建風格的支持。

可稱之為懷舊版靜態計算圖,已經不推薦使用了

import tensorflow as tf
 
g = tf.compat.v1.Graph()
with g.as_default():
    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 = " ")
 
with tf.compat.v1.Session(graph = g) as sess:
    # fetches的結果非常像一個函數的返回值,而feed_dict中的占位符相當於函數的參數序列。
    result = sess.run(fetches = z,feed_dict = {x:"hello",y:"world"})
    print(result)

b'hello world'

三,動態計算圖

在TensorFlow2.0中,使用的是動態計算圖和Autograph.

在TensorFlow1.0中,使用靜態計算圖分兩步,第一步定義計算圖,第二步在會話中執行計算圖。

動態計算圖已經不區分計算圖的定義和執行了,而是定義后立即執行。因此稱之為 Eager Excution.

Eager這個英文單詞的原意是"迫不及待的",也就是立即執行的意思。

# 動態計算圖在每個算子處都進行構建,構建后立即執行
 
x = tf.constant("hello")
y = tf.constant("world")
z = tf.strings.join([x,y],separator=" ")
 
tf.print(z)

hello world

# 可以將動態計算圖代碼的輸入和輸出關系封裝成函數
 
def strjoin(x,y):
    z =  tf.strings.join([x,y],separator = " ")
    tf.print(z)
    return z
 
result = strjoin(tf.constant("hello"),tf.constant("world"))
print(result)

hello world

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

四,TensorFlow2.0的Autograph

動態計算圖運行效率相對較低。

可以用@tf.function裝飾器將普通Python函數轉換成和TensorFlow1.0對應的靜態計算圖構建代碼。

在TensorFlow1.0中,使用計算圖分兩步,第一步定義計算圖,第二步在會話中執行計算圖。

在TensorFlow2.0中,如果采用Autograph的方式使用計算圖,第一步定義計算圖變成了定義函數,第二步執行計算圖變成了調用函數。

不需要使用會話了,一些都像原始的Python語法一樣自然。

實踐中,我們一般會先用動態計算圖調試代碼,然后在需要提高性能的的地方利用@tf.function切換成Autograph獲得更高的效率。

當然,@tf.function的使用需要遵循一定的規范,我們后面章節將重點介紹。

import tensorflow as tf
 
# 使用autograph構建靜態圖
 
@tf.function
def strjoin(x,y):
    z =  tf.strings.join([x,y],separator = " ")
    tf.print(z)
    return z
 
result = strjoin(tf.constant("hello"),tf.constant("world"))
print(result)
hello world
tf.Tensor(b'hello world', shape=(), dtype=string)

import datetime
 
# 創建日志
stamp = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
logdir = './data/autograph/%s' % stamp
writer = tf.summary.create_file_writer(logdir)
 
# 開啟autograph跟蹤
tf.summary.trace_on(graph=True, profiler=True) 
 
# 執行autograph
result = strjoin("hello","world")
 
# 將計算圖信息寫入日志
with writer.as_default():
    tf.summary.trace_export(
        name="autograph",
        step=0,
        profiler_outdir=logdir)
# 啟動 tensorboard在jupyter中的魔法命令
%load_ext tensorboard
# 啟動tensorboard
%tensorboard --logdir ./data/autograph/

 

 

參考:

開源電子書地址:https://lyhue1991.github.io/eat_tensorflow2_in_30_days/

GitHub 項目地址:https://github.com/lyhue1991/eat_tensorflow2_in_30_days

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM