Tensorflow團隊早早就放出了風聲,Tensorflow 2.0就快來了,這是一個重要的里程碑版本,重點放在簡單和易用性上。我對Tensorflow 2.0的到來充滿期待,因此翻譯了這篇Tensorflow團隊釋出的文件:Effective TensorFlow 2.0: Best Practices and What’s Changed。原文地址:https://medium.com/tensorflow/effective-tensorflow-2-0-best-practices-and-whats-changed-a0ca48767aff ,略有刪減。點選閱讀原文可以跳轉到該文章,需要翻牆哦!
在最近的一篇文章中,我們提到,TensorFlow 2.0經過重新設計,重點關注開發人員的工作效率、簡單性和易用性。
要深入瞭解所改變的內容及應用最佳實踐,請檢視新的Effective TensorFlow 2.0指南(釋出在GitHub上)。本文簡要概述那份指南里的內容。如果您對這些主題感興趣,請前往指南瞭解更多資訊!
主要變化概述
TensorFlow 2.0中有許多變化可以提高使用者的工作效率,包括刪除冗餘API、使API更加一致(統一的RNN、統一的優化器),以及Python執行時更好地整合Eager執行。
許多RFC(如果您對它們感到陌生,請檢視它們!)已經解釋了制定TensorFlow 2.0的變化和思考。本指南展現了在TensorFlow 2.0中開發應該是什麼樣的。前提假設您對TensorFlow 1.x有一定的瞭解。
API清理
許多API在TF 2.0中消失或改變位置,有些則被替換為等效的2.0版本 -- tf.summary、tf.keras.metrics和tf.keras.optimizers。自動替換為新方法的最簡單方法是使用v2升級指令碼。
Eager執行
TensorFlow 1.X要求使用者呼叫tf.* API手動將抽象語法樹(圖)拼接在一起。 然後,使用者需要通過將一組輸出張量和輸入張量傳遞給 session.run() 函式呼叫來手動編譯抽象語法樹。相比之下,TensorFlow 2.0立即執行(就像Python通常做的那樣),在tf 2.0中,圖形和會話感覺更像實現細節。
減少全域性變數
TensorFlow 1.X嚴重依賴於隱式全域性名稱空間。呼叫 tf.Variable() 時,它會被放入預設圖形中,它會保留在那裡,即使忘記了指向它的Python變數。然後,您可以恢復該 tf.Variable ,但前提是您知道它已建立的名稱。如果變數的建立不由您掌控,這就很難做到。結果,各種機制激增,試圖幫助使用者再次找到他們的變數。
TensorFlow 2.0取消了所有這些機制(Variables 2.0 RFC),啟用預設機制:跟蹤變數! 如果您失去了對 tf.Variable 的追蹤,就會被垃圾回收。
函式,而不是會話
session.run() 呼叫幾乎就像一個函式呼叫:指定輸入和要呼叫的函式,然後返回一組輸出。在TensorFlow 2.0中,您可以使用 tf.function() 來修飾Python函式以將其標記為JIT編譯,使得TensorFlow將其作為單個圖執行(Functions 2.0 RFC)。
這種機制允許TensorFlow 2.0獲得圖形模式的所有好處:
- 效能:可以優化函式(節點修剪、核心融合等)
- 可移植性:函式可以匯出/重新匯入(SavedModel 2.0 RFC),允許使用者重用和共享模組化TensorFlow函式。
憑藉自由分發Python和TensorFlow程式碼的能力,您可以充分利用Python的表現力。但是,行動式TensorFlow在沒有Python直譯器上下文時執行 - 移動、C++和JS。為了幫助使用者避免在新增@tf.function時重寫程式碼,* AutoGraph *會將部分Python構造轉換為他們的TensorFlow等價物。
TensorFlow 2.0約定建議
將程式碼重構為更小的函式
TensorFlow 1.X中的常見使用模式是“水槽”策略,其中所有可能的計算的合集被預先排列,然後通過 session.run() 評估選擇的張量。在TensorFlow 2.0中,使用者應將其程式碼重構為較小的函式,這些函式根據需要呼叫。通常,沒有必要用 tf.function 來修飾這些較小的函式,僅使用 tf.function 來修飾高階計算 - 例如,訓練的一個步驟或模型的正向傳遞。
使用Keras圖層和模型來管理變數
Keras模型和圖層提供方便的變數和 trainable_variables 屬性,以遞迴方式收集所有關聯變數,這樣可以輕鬆地將變數本地管理到它們的使用位置。
Keras層/模型繼承自tf.train.Checkpointable並與@ tf.function整合,這使得直接獲得檢查點或從Keras物件匯出SavedModel成為可能。您不一定要使用Keras's.fit()API來進行這些整合。
組合tf.data.Datasets和@tf.function
迭代載入到記憶體的訓練資料時,可以隨意使用常規的Python迭代。否則,tf.data.Dataset是從磁碟傳輸訓練資料的最佳方式。資料集是可迭代的(不是迭代器),在Eager模式下和其他Python迭代一樣工作。您可以通過將程式碼包裝在tf.function()中來充分利用資料集非同步預取/流特性,它會將Python迭代替換為使用AutoGraph的等效圖形操作。
@tf.function
def train(model, dataset, optimizer):
for x, y in dataset:
with tf.GradientTape() as tape:
prediction = model(x)
loss = loss_fn(prediction, y)
gradients = tape.gradients(loss, model.trainable_variables)
optimizer.apply_gradients(gradients, model.trainable_variables)
複製程式碼
如果您使用 Keras.fit() API,則無需考慮資料集迭代。
model.compile(optimizer=optimizer, loss=loss_fn)
model.fit(dataset)
複製程式碼
利用AutoGraph和Python控制流程
AutoGraph提供了一種將依賴於資料的控制流轉換為等價圖形模式的方法,如 tf.cond 和 tf.while_loop 。
資料相關控制流通常出現在序列模型。tf.keras.layers.RNN 封裝了RNN單元格,允許您靜態或動態地展開迴圈。處於演示目的,您可以重新實現動態展開,如下所示:
class DynamicRNN(tf.keras.Model):
def __init__(self, rnn_cell):
super(DynamicRNN, self).__init__(self)
self.cell = rnn_cell
def call(self, input_data):
# [batch, time, features] -> [time, batch, features]
input_data = tf.transpose(input_data, [1, 0, 2])
outputs = tf.TensorArray(tf.float32, input_data.shape[0])
state = self.cell.zero_state(input_data.shape[1], dtype=tf.float32)
for i in tf.range(input_data.shape[0]):
output, state = self.cell(input_data[i], state)
outputs = outputs.write(i, output)
return tf.transpose(outputs.stack(), [1, 0, 2]), state
複製程式碼
使用tf.metrics聚合資料並用tf.summary來記錄日誌
最後,一套完整的 tf.summary 符號即將推出。您可以使用以下命令訪問 tf.summary 的2.0版本:
from tensorflow.python.ops import summary_ops_v2
複製程式碼
下一步
本文提供了Effective TF 2.0指南的簡要(如果您對這些主題感興趣,請到那裡瞭解更多!)要了解有關TensorFlow 2.0的更多資訊,我們還推薦這些近期文章: