您好,登錄后才能下訂單哦!
Autograph的機制的原理是什么,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
當我們使用@tf.function裝飾一個函數的時候,后面到底發生了什么呢?
例如我們寫下如下代碼。
后面什么都沒有發生。僅僅是在Python堆棧中記錄了這樣一個函數的簽名。
當我們第一次調用這個被@tf.function裝飾的函數時,后面到底發生了什么?
例如我們寫下如下代碼。
發生了2件事情。
第一件事情是創建計算圖。
即創建一個靜態計算圖,跟蹤執行一遍函數體中的Python代碼,確定各個變量的Tensor類型,并根據執行順序將算子添加到計算圖中。
在這個過程中,如果開啟了autograph=True(默認開啟),會將Python控制流轉換成TensorFlow圖內控制流。
主要是將if語句轉換成 tf.cond算子表達,將while和for循環語句轉換成tf.while_loop算子表達,并在必要的時候添加tf.control_dependencies指定執行順序依賴關系。
相當于在 tensorflow1.0執行了類似下面的語句。
第二件事情是執行計算圖。
相當于在 tensorflow1.0中執行了下面的語句:
因此我們先看到的是第一個步驟的結果:即Python調用標準輸出流打印"tracing"語句。
然后看到第二個步驟的結果:TensorFlow調用標準輸出流打印1,2,3。
當我們再次用相同的輸入參數類型調用這個被@tf.function裝飾的函數時,后面到底發生了什么?
例如我們寫下如下代碼。
只會發生一件事情,那就是上面步驟的第二步,執行計算圖。
所以這一次我們沒有看到打印"tracing"的結果。
當我們再次用不同的的輸入參數類型調用這個被@tf.function裝飾的函數時,后面到底發生了什么?
例如我們寫下如下代碼。
由于輸入參數的類型已經發生變化,已經創建的計算圖不能夠再次使用。
需要重新做2件事情:創建新的計算圖、執行計算圖。
所以我們又會先看到的是第一個步驟的結果:即Python調用標準輸出流打印"tracing"語句。
然后再看到第二個步驟的結果:TensorFlow調用標準輸出流打印1,2,3。
需要注意的是,如果調用被@tf.function裝飾的函數時輸入的參數不是Tensor類型,則每次都會重新創建計算圖。
例如我們寫下如下代碼。兩次都會重新創建計算圖。因此,一般建議調用@tf.function時應傳入Tensor類型。
了解了以上Autograph的機制原理,我們也就能夠理解Autograph編碼規范的3條建議了。
1,被@tf.function修飾的函數應盡量使用TensorFlow中的函數而不是Python中的其他函數。
解釋:Python中的函數僅僅會在跟蹤執行函數以創建靜態圖的階段使用,普通Python函數是無法嵌入到靜態計算圖中的,所以在計算圖構建好之后再次調用的時候,這些Python函數并沒有被計算,而TensorFlow中的函數則可以嵌入到計算圖中。使用普通的Python函數會導致被@tf.function修飾前【eager執行】和被@tf.function修飾后【靜態圖執行】的輸出不一致。
2,避免在@tf.function修飾的函數內部定義tf.Variable。
解釋:如果函數內部定義了tf.Variable,那么在【eager執行】時,這種創建tf.Variable的行為在每次函數調用時候都會發生。但是在【靜態圖執行】時,這種創建tf.Variable的行為只會發生在第一步跟蹤Python代碼邏輯創建計算圖時,這會導致被@tf.function修飾前【eager執行】和被@tf.function修飾后【靜態圖執行】的輸出不一致。實際上,TensorFlow在這種情況下一般會報錯。
3,被@tf.function修飾的函數不可修改該函數外部的Python列表或字典等結構類型變量。
解釋:靜態計算圖是被編譯成C++代碼在TensorFlow內核中執行的。Python中的列表和字典等數據結構變量是無法嵌入到計算圖中,它們僅僅能夠在創建計算圖時被讀取,在執行計算圖時是無法修改Python中的列表或字典這樣的數據結構變量的。
關于Autograph的機制的原理是什么問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。