如何使用TensorFlow获得稳定的结果,设置随机种子


75

我正在尝试使用不同的参数多次运行神经网络,以便校准网络参数(辍学概率,学习率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随机播放每个时期的传入图像。


Answers:


47

设置当前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)


4
我相信我的set_random_seed(1)已经在g.as_default()块中了,因为它是train_network代码中的第一行。尽管如此,我还是尝试像您的示例中那样放置代码,但是我仍然得到不稳定的结果:>准确性标签错误> 0.9805确实对run0 2.96916> 0.9807做了对run1 2.96494> 0.9804确实对了run2 2.95215
Waanders

我有同样的问题。tensorflow 0.12.1按指定设置随机种子我发现每次运行的概率输出都有细微的差别。
路加福音

5
原因将取决于您的功能,但是精度计算中的细微差异很可能是由于ops之类的不确定并行减少引起的tf.reduce_sum()。(这些操作将浮点加法视为可交换的,而实际上并非如此,并且归约顺序的更改会导致结果中的细微错误……。)
mrry

@mrry,我遇到了类似的错误DropoutWrapper。当我保持keep_prob=1,我得到一致的结果。但是,不同的运行给带来不同的价值keep_prob=0.8。可能是什么原因?我已将其移至stackoverflow.com/questions/42156296
martianwars

15

确定性行为可以通过提供图形级或操作级种子来获得。两者都为我工作。可以使用tf.set_random_seed放置图级种子。可以将操作级别的种子放置在例如变量初始化器中,例如:

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

13

Tensorflow 2.0兼容答案:对于大于2.0的Tensorflow版本,如果我们要设置全局随机种子,则使用的命令为tf.random.set_seed

如果要从迁移Tensorflow Version 1.x to 2.x,则可以使用以下命令, tf.compat.v2.random.set_seed

注意 tf.function在这种情况下行为类似于重新运行程序。

要设置“操作级别种子”(如上所示),我们可以使用以下命令, tf.random.uniform([1], seed=1)

有关更多详细信息,请参阅此Tensorflow页面


7

由于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存储库中概述的过程。


7

请在代码之前添加所有随机种子函数:

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

我认为,TensorFlow中的某些模型正在使用numpy或python random函数。


0

我正在使用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次,我会得到相同的结果。我相信发生这种情况是因为,在运行1get_mlp_model_compiled()中,我的种子没有使用TensorFlow的内部计数器。在第2次运行中,它将使用种子,所有后续运行也将使用种子,因此在第2次运行后,结果将相同。

我的某些信息可能有误,请随时纠正我。

要了解正在发生的事情,您应该阅读这些文档,它们不那么长且有点易于理解。


-1

此答案是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)

使用TF_CUDNN_DETERMINISTIC破坏笔记本电脑与tf 2.3.0不确定原因。这使我直接在代码中调试了2天!不要使用这个。
Kaushal20年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.