[英]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-tf
和vgg19
自定義模型
在研究了基於 keras 的 GPU 訓練和大型神經網絡模型的 tensorflow 后端結果不穩定的問題后,我終於能夠獲得可重現(穩定)的結果,如下所示:
import tensorflow as tf
import os
import numpy as np
import random
SEED = 0
def set_seeds(seed=SEED):
os.environ['PYTHONHASHSEED'] = str(seed)
random.seed(seed)
tf.random.set_seed(seed)
np.random.seed(seed)
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)
我正在使用 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,
)
這是我的理解:
tf.random.set_seed(1)
設置種子時,您會讓這些進程使用它,如果設置了種子並且進程不更改,結果將相同。tf.random.set_seed(1)
更改為低於線model = get_mlp_model_compiled()
我的結果會發生變化,我相信這是因為get_mlp_model_compiled()
使用隨機性並且沒有使用我想要的種子.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.