Autograph的機(jī)制的原理是什么,針對(duì)這個(gè)問題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡單易行的方法。
創(chuàng)新互聯(lián)建站是一家專業(yè)提供鹽田企業(yè)網(wǎng)站建設(shè),專注與成都網(wǎng)站建設(shè)、成都網(wǎng)站制作、H5開發(fā)、小程序制作等業(yè)務(wù)。10年已為鹽田眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站建設(shè)公司優(yōu)惠進(jìn)行中。
當(dāng)我們使用@tf.function裝飾一個(gè)函數(shù)的時(shí)候,后面到底發(fā)生了什么呢?
例如我們寫下如下代碼。
后面什么都沒有發(fā)生。僅僅是在Python堆棧中記錄了這樣一個(gè)函數(shù)的簽名。
當(dāng)我們第一次調(diào)用這個(gè)被@tf.function裝飾的函數(shù)時(shí),后面到底發(fā)生了什么?
例如我們寫下如下代碼。
發(fā)生了2件事情。
第一件事情是創(chuàng)建計(jì)算圖。
即創(chuàng)建一個(gè)靜態(tài)計(jì)算圖,跟蹤執(zhí)行一遍函數(shù)體中的Python代碼,確定各個(gè)變量的Tensor類型,并根據(jù)執(zhí)行順序?qū)⑺阕犹砑拥接?jì)算圖中。
在這個(gè)過程中,如果開啟了autograph=True(默認(rèn)開啟),會(huì)將Python控制流轉(zhuǎn)換成TensorFlow圖內(nèi)控制流。
主要是將if語句轉(zhuǎn)換成 tf.cond算子表達(dá),將while和for循環(huán)語句轉(zhuǎn)換成tf.while_loop算子表達(dá),并在必要的時(shí)候添加tf.control_dependencies指定執(zhí)行順序依賴關(guān)系。
相當(dāng)于在 tensorflow1.0執(zhí)行了類似下面的語句。
第二件事情是執(zhí)行計(jì)算圖。
相當(dāng)于在 tensorflow1.0中執(zhí)行了下面的語句:
因此我們先看到的是第一個(gè)步驟的結(jié)果:即Python調(diào)用標(biāo)準(zhǔn)輸出流打印"tracing"語句。
然后看到第二個(gè)步驟的結(jié)果:TensorFlow調(diào)用標(biāo)準(zhǔn)輸出流打印1,2,3。
當(dāng)我們再次用相同的輸入?yún)?shù)類型調(diào)用這個(gè)被@tf.function裝飾的函數(shù)時(shí),后面到底發(fā)生了什么?
例如我們寫下如下代碼。
只會(huì)發(fā)生一件事情,那就是上面步驟的第二步,執(zhí)行計(jì)算圖。
所以這一次我們沒有看到打印"tracing"的結(jié)果。
當(dāng)我們再次用不同的的輸入?yún)?shù)類型調(diào)用這個(gè)被@tf.function裝飾的函數(shù)時(shí),后面到底發(fā)生了什么?
例如我們寫下如下代碼。
由于輸入?yún)?shù)的類型已經(jīng)發(fā)生變化,已經(jīng)創(chuàng)建的計(jì)算圖不能夠再次使用。
需要重新做2件事情:創(chuàng)建新的計(jì)算圖、執(zhí)行計(jì)算圖。
所以我們又會(huì)先看到的是第一個(gè)步驟的結(jié)果:即Python調(diào)用標(biāo)準(zhǔn)輸出流打印"tracing"語句。
然后再看到第二個(gè)步驟的結(jié)果:TensorFlow調(diào)用標(biāo)準(zhǔn)輸出流打印1,2,3。
需要注意的是,如果調(diào)用被@tf.function裝飾的函數(shù)時(shí)輸入的參數(shù)不是Tensor類型,則每次都會(huì)重新創(chuàng)建計(jì)算圖。
例如我們寫下如下代碼。兩次都會(huì)重新創(chuàng)建計(jì)算圖。因此,一般建議調(diào)用@tf.function時(shí)應(yīng)傳入Tensor類型。
了解了以上Autograph的機(jī)制原理,我們也就能夠理解Autograph編碼規(guī)范的3條建議了。
1,被@tf.function修飾的函數(shù)應(yīng)盡量使用TensorFlow中的函數(shù)而不是Python中的其他函數(shù)。
解釋:Python中的函數(shù)僅僅會(huì)在跟蹤執(zhí)行函數(shù)以創(chuàng)建靜態(tài)圖的階段使用,普通Python函數(shù)是無法嵌入到靜態(tài)計(jì)算圖中的,所以在計(jì)算圖構(gòu)建好之后再次調(diào)用的時(shí)候,這些Python函數(shù)并沒有被計(jì)算,而TensorFlow中的函數(shù)則可以嵌入到計(jì)算圖中。使用普通的Python函數(shù)會(huì)導(dǎo)致被@tf.function修飾前【eager執(zhí)行】和被@tf.function修飾后【靜態(tài)圖執(zhí)行】的輸出不一致。
2,避免在@tf.function修飾的函數(shù)內(nèi)部定義tf.Variable。
解釋:如果函數(shù)內(nèi)部定義了tf.Variable,那么在【eager執(zhí)行】時(shí),這種創(chuàng)建tf.Variable的行為在每次函數(shù)調(diào)用時(shí)候都會(huì)發(fā)生。但是在【靜態(tài)圖執(zhí)行】時(shí),這種創(chuàng)建tf.Variable的行為只會(huì)發(fā)生在第一步跟蹤Python代碼邏輯創(chuàng)建計(jì)算圖時(shí),這會(huì)導(dǎo)致被@tf.function修飾前【eager執(zhí)行】和被@tf.function修飾后【靜態(tài)圖執(zhí)行】的輸出不一致。實(shí)際上,TensorFlow在這種情況下一般會(huì)報(bào)錯(cuò)。
3,被@tf.function修飾的函數(shù)不可修改該函數(shù)外部的Python列表或字典等結(jié)構(gòu)類型變量。
解釋:靜態(tài)計(jì)算圖是被編譯成C++代碼在TensorFlow內(nèi)核中執(zhí)行的。Python中的列表和字典等數(shù)據(jù)結(jié)構(gòu)變量是無法嵌入到計(jì)算圖中,它們僅僅能夠在創(chuàng)建計(jì)算圖時(shí)被讀取,在執(zhí)行計(jì)算圖時(shí)是無法修改Python中的列表或字典這樣的數(shù)據(jù)結(jié)構(gòu)變量的。
關(guān)于Autograph的機(jī)制的原理是什么問題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識(shí)。