簡體   English   中英

如何使用 TensorFlow 獲得穩定結果,設置隨機種子

[英]How to get stable results with TensorFlow, setting random seed

我正在嘗試使用不同的參數多次運行神經網絡,以校准網絡參數(輟學概率、學習率 ed)。 但是我遇到的問題是,當我在循環中運行網絡時,在保持參數相同的情況下運行網絡仍然給我一個不同的解決方案,如下所示:

filename = create_results_file()
for i in range(3):
  g = tf.Graph()
  with g.as_default():
    accuracy_result, average_error = network.train_network(
        parameters, inputHeight, inputWidth, inputChannels, outputClasses)
    f, w = get_csv_writer(filename)
    w.writerow([accuracy_result, "did run %d" % i, average_error])
    f.close()

在設置網絡的層和誤差函數之前,我在 train_network 函數的開頭使用以下代碼:

np.random.seed(1)
tf.set_random_seed(1)

我也嘗試在 TensorFlow 圖創建之前添加此代碼,但我在結果輸出中不斷得到不同的解決方案。

我正在使用 AdamOptimizer 並使用tf.truncated_normal初始化網絡權重。 此外,我使用np.random.permutation來對每個時期的傳入圖像進行洗牌。

設置當前的 TensorFlow 隨機種子只會影響當前的默認圖。 由於您正在為您的訓練創建一個新圖並將其設置為默認值( with g.as_default(): ),您必須在with塊的范圍內設置隨機種子。

例如,您的循環應如下所示:

for i in range(3):
  g = tf.Graph()
  with g.as_default():
    tf.set_random_seed(1)
    accuracy_result, average_error = network.train_network(
        parameters, inputHeight, inputWidth, inputChannels, outputClasses)

請注意,這將為外部for循環的每次迭代使用相同的隨機種子。 如果您想在每次迭代中使用不同但仍具有確定性的種子,您可以使用tf.set_random_seed(i + 1)

可以通過提供圖形級或操作級種子來獲得確定性行為。 兩者都為我工作。 可以使用tf.set_random_seed放置圖形級種子。 操作級種子可以放置在例如變量初始化器中,如下所示:

myvar = tf.Variable(tf.truncated_normal(((10,10)), stddev=0.1, seed=0))

Tensorflow 2.0 兼容答案:對於大於 2.0 的 Tensorflow 版本,如果我們想設置全局隨機種子,使用的命令是tf.random.set_seed

如果我們從Tensorflow Version 1.x to 2.x遷移Tensorflow Version 1.x to 2.x ,我們可以使用命令tf.compat.v2.random.set_seed

請注意,在這種情況下, tf.function就像重新運行程序一樣。

要設置操作級別種子(如上所述),我們可以使用命令tf.random.uniform([1], seed=1)

有關更多詳細信息,請參閱此Tensorflow 頁面

請在您的代碼之前添加所有隨機種子函數:

tf.reset_default_graph()
tf.random.set_seed(0)
random.seed(0)
np.random.seed(0)

我認為,TensorFlow 中的某些模型正在使用 numpy 或 python 隨機函數。

由於 CuDNN 中的潛在實現問題,這些答案似乎都不起作用。

你可以通過添加一個額外的標志來獲得更多的確定性

os.environ['PYTHONHASHSEED']=str(SEED)
os.environ['TF_CUDNN_DETERMINISTIC'] = '1'  # new flag present in tf 2.0+
random.seed(SEED)
np.random.seed(SEED)
tf.set_random_seed(SEED)

但這仍然不是完全確定的。 要獲得更精確的解決方案,您需要使用此 nvidia repo 中概述的過程。

后端設置: cuda:10.1 , cudnn: 7 , tensorflow-gpu: 2.1.0 , keras: 2.2.4-tfvgg19自定義模型

在研究了基於 keras 的 GPU 訓練和大型神經網絡模型的 tensorflow 后端結果不穩定的問題后,我終於能夠獲得可重現(穩定)的結果,如下所示:

  1. 僅導入設置種子和初始化種子值所需的那些庫
import tensorflow as tf
import os
import numpy as np
import random

SEED = 0
  1. 為所有可能具有隨機行為的庫初始化種子的函數
def set_seeds(seed=SEED):
    os.environ['PYTHONHASHSEED'] = str(seed)
    random.seed(seed)
    tf.random.set_seed(seed)
    np.random.seed(seed)
  1. 激活Tensorflow確定性行為
def set_global_determinism(seed=SEED):
    set_seeds(seed=seed)

    os.environ['TF_DETERMINISTIC_OPS'] = '1'
    os.environ['TF_CUDNN_DETERMINISTIC'] = '1'
    
    tf.config.threading.set_inter_op_parallelism_threads(1)
    tf.config.threading.set_intra_op_parallelism_threads(1)

# Call the above function with seed value
set_global_determinism(seed=SEED)

重要說明:

  • 請在執行任何其他代碼之前調用上面的代碼
  • 由於代碼是確定性的,模型訓練可能會變慢,因此需要權衡
  • 我用不同數量的 epochs 和不同的設置(包括帶有 shuffle=True 的 model.fit())進行了多次實驗,上面的代碼給了我可重復的結果。

參考資料:

  1. https://suneeta-mall.github.io/2019/12/22/Reproducible-ml-tensorflow.html
  2. https://keras.io/getting_started/faq/#how-can-i-obtain-reproducible-results-using-keras-during-development
  3. https://www.tensorflow.org/api_docs/python/tf/config/threading/set_inter_op_parallelism_threads
  4. https://www.tensorflow.org/api_docs/python/tf/random/set_seed?version=nightly

我正在使用 TensorFlow 2 (2.2.0) 並且我正在 JupyterLab 中運行代碼。 我已經在 macOS Catalina 和 Google Colab 中對此進行了測試,結果相同。 我會在Tensorflow 支持的回答中添加一些內容。

當我使用 model.fit() 方法進行一些訓練時,我會在一個單元格中進行訓練。 我在其他單元格中做一些其他的事情。 這是我在提到的單元格中運行的代碼:

# To have same results always place this on top of the cell
tf.random.set_seed(1)

(x_train, y_train), (x_test, y_test) = load_data_onehot_grayscale()
model = get_mlp_model_compiled() # Creates the model, compiles it and returns it

history = model.fit(x=x_train, y=y_train,
                    epochs=30,
                    callbacks=get_mlp_model_callbacks(),
                    validation_split=.1,
                   )

這是我的理解:

  1. TensorFlow 有一些隨機過程發生在不同階段(初始化、混洗等),每次這些過程發生時,TensorFlow 都會使用一個隨機函數。 當您使用tf.random.set_seed(1)設置種子時,您會讓這些進程使用它,如果設置了種子並且進程不更改,結果將相同。
  2. 現在,在上面的代碼中,如果我將tf.random.set_seed(1)更改為低於線model = get_mlp_model_compiled()我的結果會發生變化,我相信這是因為get_mlp_model_compiled()使用隨機性並且沒有使用我想要的種子.
  3. 關於第 2 點的警告:如果我連續運行單元格 3 次,我會得到相同的結果。 我相信這是因為在運行 nº1 時get_mlp_model_compiled()沒有使用 TensorFlow 的內部計數器和我的種子。 在運行 nº2 中,它將使用種子,所有后續運行也將使用種子,因此運行 nº2 后結果將相同。

我可能有一些信息錯誤,請隨時糾正我。

要了解發生了什么,您應該閱讀docs ,它們不是那么長且易於理解。

這個答案是對Luke 的答案和 TF v2.2.0 的補充

import numpy as np
import os
import random
import tensorflow as tf # 2.2.0

SEED = 42
os.environ['PYTHONHASHSEED']=str(SEED)
os.environ['TF_CUDNN_DETERMINISTIC'] = '1'  # TF 2.1
random.seed(SEED)
np.random.seed(SEED)
tf.random.set_seed(SEED)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM