當前位置: 首頁>>代碼示例 >>用法及示例精選 >>正文


Python tf.config.experimental.enable_op_determinism用法及代碼示例


將 TensorFlow 操作配置為確定性地運行。

用法

tf.config.experimental.enable_op_determinism()

啟用操作確定性後,TensorFlow 操作將是確定性的。這意味著,如果一個運算在同一硬件上使用相同的輸入多次運行,則每次都將具有完全相同的輸出。這對於調試模型很有用。請注意,確定性通常是以降低性能為代價的,因此當啟用操作確定性時,您的模型可能會運行得更慢。

如果您希望 TensorFlow 程序確定性地運行,請將以下代碼放在程序開頭附近。

tf.keras.utils.set_random_seed(1)
tf.config.experimental.enable_op_determinism()

調用 tf.keras.utils.set_random_seed 設置 Python 種子、NumPy 種子和 TensorFlow 種子。設置這些種子是必要的,以確保您的程序生成的任何隨機數也是確定性的。

默認情況下,操作確定性未啟用,因此操作在使用相同輸入運行時可能會返回不同的結果。這些差異通常是由於在操作中使用異步線程不確定地更改浮點數相加的順序造成的。大多數這些不確定性情況發生在 GPU 上,GPU 有數千個用於運行操作的硬件線程。啟用確定性會指示此類操作使用不同的算法,該算法不會以不確定的方式使用線程。

不確定性的另一個潛在來源是基於tf.data 的數據處理。通常,由於在 Dataset.map 生成輸入或以非確定性順序運行有狀態操作等方法中使用並行性,這可能會引入不確定性。啟用確定性將消除這些非確定性的來源。

啟用確定性可能會使您的模型或 tf.data 數據處理速度變慢。例如,當 map 函數具有隨機操作或其他有狀態操作時,Dataset.map 可能會變慢幾個數量級。有關更多詳細信息,請參閱下麵的“確定性和 tf.data”部分。在未來的 TensorFlow 版本中,我們計劃提高確定性的性能,尤其是對於常見場景,例如 Dataset.map

某些操作會引發UnimplementedError,因為它們還沒有確定性的實現。此外,由於錯誤,某些操作可能是不確定的,不會引發 UnimplementedError 。如果您遇到此類操作,請提出問題。

下麵是一個啟用確定性的示例。 tf.nn.softmax_cross_entropy_with_logits op 運行多次,並且每次顯示的輸出都相同。如果未啟用確定性,則此示例在 GPU 上運行時可能會失敗,因為默認情況下 tf.nn.softmax_cross_entropy_with_logits 在 GPU 上使用非確定性算法。

labels = tf.random.normal((1, 10000))
logits = tf.random.normal((1, 10000))
output = tf.nn.softmax_cross_entropy_with_logits(labels=labels,
                                                 logits=logits)
for _ in range(5):
  output2 = tf.nn.softmax_cross_entropy_with_logits(labels=labels,
                                                    logits=logits)
  tf.debugging.assert_equal(output, output2)

編寫確定性模型

您可以通過啟用操作確定性來使您的模型具有確定性。這意味著您可以訓練模型並使用完全相同的可訓練變量完成每次運行。這也意味著您的previously-trained 模型的推論在每次運行時都將完全相同。通常,可以通過簡單地設置種子並啟用操作確定性來使模型具有確定性,如上麵的示例所示。但是,為了保證您的模型確定性地運行,您必須滿足以下所有要求:

  • 如上所述,調用 tf.config.experimental.enable_op_determinism()
  • 如上所述,可重複地重置您正在使用的任何偽隨機數生成器 (PRNG),例如通過在 TensorFlow、Python 和 NumPy 中設置默認 PRNG 的種子。請注意,某些較新的 NumPy 類(如 numpy.random.default_rng)會忽略全局 NumPy 種子,因此如果使用種子,則必須將種子顯式傳遞給此類類。
  • 在每次運行中使用相同的硬件配置。
  • 在每次運行中使用相同的軟件環境(操作係統、檢查點、CUDA 和 TensorFlow 的版本、環境變量等)。請注意,不同版本的 TensorFlow 無法保證確定性。
  • 不要在 TensorFlow 之外使用不確定的構造,例如從 /dev/random 讀取或以影響 TensorFlow 行為的方式使用多個線程/進程。
  • 確保您的輸入管道是確定性的。如果您使用 tf.data ,這是自動完成的(以犧牲性能為代價)。有關詳細信息,請參閱下麵的“確定性和 tf.data”。
  • 不要使用 tf.compat.v1.Sessiontf.distribute.experimental.ParameterServerStrategy ,這會引入不確定性。除了 ops(包括 tf.data ops),這些是 TensorFlow 中唯一已知的潛在不確定性來源(如果您發現更多,請提出問題)。請注意,tf.compat.v1.Session 是使用 TF1 API 所必需的,因此在使用 TF1 API 時無法保證確定性。
  • 不要使用不確定的自定義操作。

有關確定性的其他詳細信息

為了使有狀態操作具有確定性,每次運行操作時係統的狀態都必須相同。例如,tf.Variable.sparse_read 的輸出(顯然)取決於變量值和 indices 函數參數。啟用確定性後,有狀態操作的副作用是確定性的。

TensorFlow 的隨機操作,例如 tf.random.normal ,如果啟用了確定性並且尚未設置種子,則會引發 RuntimeError。但是,嘗試使用 Python 或 NumPy 生成不確定的隨機數不會引發此類錯誤。確保您記得設置 Python 和 NumPy 種子。調用tf.keras.utils.set_random_seed 是設置所有三個種子的簡單方法。

請注意,延遲、內存消耗、吞吐量和其他性能特征不是通過啟用操作確定性來確定的。隻有操作輸出和副作用是確定性的。此外,由於內存消耗是不確定的,模型可能會因內存不足而不確定地引發 tf.errors.ResourceExhaustedError。

確定性和 tf.data

啟用確定性操作使tf.data 在幾個方掩碼有確定性:

  1. 對於具有 deterministic 參數的數據集方法,例如 Dataset.mapDataset.batch ,無論其設置如何,deterministic 參數都會被覆蓋為 True
  2. tf.data.Option.experimental_deterministic 選項被覆蓋為 True 而不管其設置如何。
  3. Dataset.mapDataset.interleave 中,如果 map 或 interleave 函數具有狀態隨機操作或其他狀態操作,則該函數將串行運行而不是並行運行。這意味著 mapinterleavenum_parallel_calls 參數被有效地忽略。
  4. 如果作為輸入管道的一部分運行的任何函數具有某些有狀態操作,則使用 Dataset.prefetch 進行預取將被禁用。同樣,如果輸入管道中的任何函數具有此類有狀態操作,則任何具有 num_parallel_calls 參數的數據集方法都將被串行運行。 tf.random.normal 等傳統隨機操作不會導致此類數據集發生更改,但大多數其他有狀態操作會。

不幸的是,由於 (3),當在Dataset.map 中使用有狀態操作時,由於不再並行運行 map 函數,性能會大大降低。 Dataset.map 中使用的有狀態操作的一個常見示例是隨機操作,例如 tf.random.normal ,它們通常用於失真。解決此問題的一種方法是改用無狀態隨機操作。或者,您可以將所有隨機操作提升到自己單獨的 Dataset.map 調用中,使原始 Dataset.map 調用無狀態,從而避免序列化其執行的需要。

(4) 也可能導致性能下降,但發生頻率低於 (3),因為傳統隨機操作不會導致 (4) 生效。但是,與 (3) 不同的是,當用戶定義的函數中存在非隨機狀態操作時,每個 mapinterleave 數據集都會受到影響,而不僅僅是帶有函數的 mapinterleave 數據集有狀態操作。此外,prefetch 數據集和任何帶有 num_parallel_calls 參數的數據集也會受到影響。

相關用法


注:本文由純淨天空篩選整理自tensorflow.org大神的英文原創作品 tf.config.experimental.enable_op_determinism。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。