0
本文作者: 岑大師 | 2017-11-02 02:03 |
雷鋒網(wǎng)按:Google的TensorFlow是AI學(xué)習(xí)者中使用率最高、名氣也最大的深度學(xué)習(xí)框架,但由于TensorFlow最早是基于Google的需求開發(fā)的,在實際使用上也會存在如文檔亂、調(diào)試難等諸多缺點,而且開發(fā)時間比較早未能及時對一些新的需求進行反應(yīng)(據(jù)雷鋒網(wǎng)了解,由于缺乏類似PyTroch、DyNet的動態(tài)圖功能,Lecun就不止一次吐槽過TensorFlow是“過時的深度學(xué)習(xí)框架”(yesterday deep learning framework)),而針對用戶的需求,Google也在對TensorFlow不斷改進。在10月31日,Google為TensorFlow引入了動態(tài)圖機制Eager Execution,而Google Brain Team的工程師Asim Shankar和Wolff Dobson也在Google官方博客發(fā)文詳細闡述了這一功能帶來的變化,雷鋒網(wǎng)摘編如下:
今天,我們?yōu)?TensorFlow 引入了“Eager Execution”,它是一個命令式、由運行定義的接口,一旦從 Python 被調(diào)用可立即執(zhí)行操作,這使得 TensorFlow 的入門學(xué)習(xí)變的更簡單,也使得研發(fā)工作變得更直觀。
Eager Execution 的優(yōu)點包括:
可以在即時的運行錯誤下進行快速調(diào)試,與 Python 工具進行整合
通過易于使用的 Python 控制流支持動態(tài)模型
為自定義和高階梯度提供強大支持
適用于幾乎目前所有的 TensorFlow 操作
目前 Eager Execution 仍處于試用階段,因此我們也在尋求來自社區(qū)的反饋以指導(dǎo)我們的方向。
同時Google還舉了一些使用 Eager Execution 的直觀例子,例如使用兩個矩陣相乘的代碼是這樣編寫的:
import tensorflow as tf
import tensorflow.contrib.eager as tfe
tfe.enable_eager_execution()
x = [[2.]]
m = tf.matmul(x, x)
使用 print 或者 Python 調(diào)試器檢查中間結(jié)果也非常直接。
print(m)
# The 1x1 matrix [[4.]]
大多數(shù) TensorFlow 用戶對自動微分感興趣。因為每次調(diào)用期間可能會產(chǎn)生不同的運算,因此我們將所有的正向運算錄到一個“磁帶”上,并在計算梯度時進行反向運算。計算了梯度之后,這個“磁帶”就沒用了。
這一API與 autograd 包非常類似,例子如下:
def square(x):
return tf.multiply(x, x)
grad = tfe.gradients_function(square)
print(square(3.)) # [9.]
print(grad(3.)) # [6.]
在這里,gradients_function 先調(diào)用了一個預(yù)先定義的 Python 函數(shù) square() 作為參數(shù),并返回一個 Python 可調(diào)用函數(shù) grad 來計算相對于輸入的 square() 的偏導(dǎo)數(shù)。如以上例子中當輸入為 3.0 時, square() 的計算結(jié)果為9,而 grad(3.0) 為對 square() 進行偏導(dǎo),其計算結(jié)果為 6。
同樣,我們也可以調(diào)用 gradient_function 計算 square 的二階導(dǎo)數(shù)。
此外,用戶也可能需要為運算或函數(shù)自定義梯度。這一功能可能有用,例如,它可以為一系列運算提供了更高效或者數(shù)值更穩(wěn)定的梯度。
以下是一個自定義梯度的例子。我們先來看函數(shù) log(1 + e^x),它通常用于計算交叉熵和對數(shù)似然。
def log1pexp(x):
return tf.log(1 + tf.exp(x))grad_log1pexp = tfe.gradients_function(log1pexp)
# The gradient computation works fine at x = 0.
print(grad_log1pexp(0.)
)# [0.5]
# However it returns a `nan` at x = 100 due to numerical instability.print(grad_log1pexp(100.))
# [nan]
上述例子中,當 x=0 時,梯度計算表現(xiàn)良好。然而由于數(shù)值的不穩(wěn)定性,當 x=100 時則會返回 `nan` 。使用上述函數(shù)的自定義梯度可用于分析簡化梯度表達式。
Eager execution 使開發(fā)和調(diào)試互動性更強,但是 TensorFlow graphs 在分布式訓(xùn)練、性能優(yōu)化和生產(chǎn)部署中也有著諸多優(yōu)勢。
當啟用 eager execution 時,執(zhí)行運算的代碼同時還可以構(gòu)建一個描述 eager execution 未啟用狀況的計算圖。要將模型轉(zhuǎn)換成圖形,只需在新的 Python 進程中運行同樣的代碼即可。這一做法可以從檢查點保存和修復(fù)模型變量值,這允許我們在 eager(命令式)和 graph(聲明式)編程之間輕松轉(zhuǎn)換。通過這種方式可以輕松地將啟用 eager execution 開發(fā)出的模型導(dǎo)出到生產(chǎn)部署中。
在不久的將來,我們將提供工具來選擇性地將模型的某些部分轉(zhuǎn)換為圖形。這樣就可以融合部分計算(如自定義RNN單元的內(nèi)部),以實現(xiàn)高性能并同時保持 eager execution 的靈活性和可讀性。
新功能勢必帶來代碼編寫上的變化。Google還很貼心地給出了幾個Tips:
與TensorFlow一樣,我們建議,如果您還沒有從隊列切換到使用tf.data進行輸入處理,請抓緊時間進行切換,它更容易使用,也會更快。 有關(guān)幫助參閱相關(guān)博客文章和文檔頁面。
使用面向?qū)ο髮?,如tf.layer.Conv2D()或Keras層;;它們可以直接存儲變量。
你可以為大多數(shù)模型編寫代碼,無論是執(zhí)行和圖形構(gòu)建都是一樣的。 但也有一些例外,例如使用Python控制流來改變基于輸入的計算的動態(tài)模型。
一旦你調(diào)用了tfe.enable_eager_execution(),它就不能關(guān)閉。 要獲取圖形行為,請啟動一個新的Python會話。
更多內(nèi)容可參閱Google博客。
雷峰網(wǎng)原創(chuàng)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見轉(zhuǎn)載須知。