[譯]高效的TensorFlow 2.0:應用最佳實踐以及有什麼變化

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.condtf.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的更多信息,我們還推薦這些近期文章:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章