94

每次imdb_lstm.py从 Keras 框架 ( https://github.com/fchollet/keras/blob/master/examples/imdb_lstm.py ) 运行示例时,我都会得到不同的结果(测试准确性) 代码包含np.random.seed(1337)在顶部,在任何 keras 之前进口。它应该防止它为每次运行生成不同的数字。我错过了什么?

更新:如何复制:

  1. 安装 Keras ( http://keras.io/ )
  2. 执行https://github.com/fchollet/keras/blob/master/examples/imdb_lstm.py 几次。它将训练模型并输出测试精度。
    预期结果:每次运行的测试精度都相同。
    实际结果:每次运行的测试精度都不同。

UPDATE2:我在 Windows 8.1 上使用 MinGW/msys 运行它,模块版本:
theano 0.7.0
numpy 1.8.1
scipy 0.14.0c1

UPDATE3:我把问题缩小了一点。如果我使用 GPU 运行示例(设置 theano flag device=gpu0),那么我每次都会得到不同的测试精度,但是如果我在 CPU 上运行它,那么一切都会按预期工作。我的显卡:NVIDIA GeForce GT 635)

4

12 回答 12

71

您可以在 Keras 文档中找到答案:https ://keras.io/getting-started/faq/#how-can-i-obtain-reproducible-results-using-keras-during-development 。

简而言之,要绝对确定您将在一台计算机/笔记本电脑的 CPU 上使用您的 python 脚本获得可重现的结果,那么您必须执行以下操作:

  1. PYTHONHASHSEED环境变量设置为固定值
  2. python内置伪随机发生器设置为固定值
  3. numpy伪随机发生器设置为固定值
  4. tensorflow伪随机发生器设置为固定值
  5. 配置新的全局tensorflow会话

按照Keras顶部的链接,我正在使用的源代码如下:

# Seed value
# Apparently you may use different seed values at each stage
seed_value= 0

# 1. Set the `PYTHONHASHSEED` environment variable at a fixed value
import os
os.environ['PYTHONHASHSEED']=str(seed_value)

# 2. Set the `python` built-in pseudo-random generator at a fixed value
import random
random.seed(seed_value)

# 3. Set the `numpy` pseudo-random generator at a fixed value
import numpy as np
np.random.seed(seed_value)

# 4. Set the `tensorflow` pseudo-random generator at a fixed value
import tensorflow as tf
tf.random.set_seed(seed_value)
# for later versions: 
# tf.compat.v1.set_random_seed(seed_value)

# 5. Configure a new global `tensorflow` session
from keras import backend as K
session_conf = tf.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1)
sess = tf.Session(graph=tf.get_default_graph(), config=session_conf)
K.set_session(sess)
# for later versions:
# session_conf = tf.compat.v1.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1)
# sess = tf.compat.v1.Session(graph=tf.compat.v1.get_default_graph(), config=session_conf)
# tf.compat.v1.keras.backend.set_session(sess)

不用说,您不必完全指定您在 python 脚本中使用的任何seedrandom_stateat或/函数numpy,因为使用上面的源代码,我们将它们的伪随机生成器全局设置为固定值。scikit-learntensorflowkeras

于 2018-10-19T17:23:30.617 回答
13

Theano 的文档讨论了播种随机变量的困难,以及为什么他们使用自己的随机数生成器为每个图实例播种。

在不同的 {{{RandomOp}}} 实例之间共享一个随机数生成器使得无论图中的其他操作如何都难以产生相同的流,并保持 {{{RandomOps}}} 隔离。因此,图中的每个 {{{RandomOp}}} 实例都有自己的随机数生成器。该随机数生成器是函数的输入。在典型用法中,我们将使用函数输入({{{value}}}、{{{update}}})的新特性来传递和更新每个 {{{RandomOp}}} 的 rng。通过将 RNG 作为输入传递,可以使用访问函数输入的常规方法来访问每个 {{{RandomOp}}} 的 rng。在这种方法中,没有预先存在的机制来处理整个图的组合随机数状态。

他们还提供了有关如何为所有随机数生成器播种的示例。

您还可以通过该对象的种子方法播种由 RandomStreams 对象分配的所有随机变量。该种子将用于为临时随机数生成器播种,该生成器将依次为每个随机变量生成种子。

>>> srng.seed(902340)  # seeds rv_u and rv_n with different seeds each
于 2015-09-21T03:45:27.923 回答
12

我终于用我的代码得到了可重现的结果。这是我在网上看到的答案的组合。第一件事就是按照@alex 所说的去做:

  1. 设置numpy.random.seed
  2. 用于PYTHONHASHSEED=0Python 3。

然后你必须通过调用你的 Keras 代码来解决 @user2805751 提到的关于 cuDNN 的问题THEANO_FLAGS

  1. dnn.conv.algo_bwd_filter=deterministic,dnn.conv.algo_bwd_data=deterministic

最后,您必须根据此评论修补您的 Theano 安装,主要包括:

  1. *_dev20将所有对operator 的调用替换为theano/sandbox/cuda/opt.py.

这应该为您提供相同种子的相同结果。

请注意,可能会放缓。我看到运行时间增加了大约 10%。

于 2016-10-20T10:05:08.103 回答
9

这个问题现在在 Tensorflow 2.0 中得到了解决!我在使用 TF 1.x 时遇到了同样的问题(请参阅 如果 Keras 结果不可重现,比较模型和选择超参数的最佳做法是什么?)但是

import os
####*IMPORANT*: Have to do this line *before* importing tensorflow
os.environ['PYTHONHASHSEED']=str(1)

import tensorflow as tf
import tensorflow.keras as keras
import tensorflow.keras.layers 
import random
import pandas as pd
import numpy as np

def reset_random_seeds():
   os.environ['PYTHONHASHSEED']=str(1)
   tf.random.set_seed(1)
   np.random.seed(1)
   random.seed(1)

#make some random data
reset_random_seeds()
NUM_ROWS = 1000
NUM_FEATURES = 10
random_data = np.random.normal(size=(NUM_ROWS, NUM_FEATURES))
df = pd.DataFrame(data=random_data, columns=['x_' + str(ii) for ii in range(NUM_FEATURES)])
y = df.sum(axis=1) + np.random.normal(size=(NUM_ROWS))

def run(x, y):
    reset_random_seeds()

    model = keras.Sequential([
            keras.layers.Dense(40, input_dim=df.shape[1], activation='relu'),
            keras.layers.Dense(20, activation='relu'),
            keras.layers.Dense(10, activation='relu'),
            keras.layers.Dense(1, activation='linear')
        ])
    NUM_EPOCHS = 500
    model.compile(optimizer='adam', loss='mean_squared_error')
    model.fit(x, y, epochs=NUM_EPOCHS, verbose=0)
    predictions = model.predict(x).flatten()
    loss = model.evaluate(x,  y) #This prints out the loss by side-effect

#With Tensorflow 2.0 this is now reproducible! 
run(df, y)
run(df, y)
run(df, y)
于 2019-11-27T18:03:28.080 回答
6

在 Tensorflow 2.0 中,您可以像这样设置随机种子:

import tensorflow as tf
tf.random.set_seed(221)


from tensorflow import keras
from tensorflow.keras import layers


model = keras.Sequential( [ 
layers.Dense(2,name = 'one'),
layers.Dense(3,activation = 'sigmoid', name = 'two'),
layers.Dense(2,name = 'three')])

x = tf.random.uniform((12,12))
model(x)
于 2020-06-17T14:19:59.773 回答
4

这对我有用:

SEED = 123456
import os
import random as rn
import numpy as np
from tensorflow import set_random_seed

os.environ['PYTHONHASHSEED']=str(SEED)
np.random.seed(SEED)
set_random_seed(SEED)
rn.seed(SEED)
于 2019-06-14T23:40:46.947 回答
2

它看起来更容易。仅此而已,它可以工作:

import numpy as np
import tensorflow as tf
import random as python_random

def reset_seeds():
   np.random.seed(123) 
   python_random.seed(123)
   tf.random.set_seed(1234)

reset_seeds() 

问题的关键,非常重要,是在每次运行模型之前调用函数 reset_seeds() 。当我在 Google Collab 中检查时,这样做您将获得可重现的结果。

于 2020-11-18T14:55:13.217 回答
2

我想在之前的答案中添加一些内容。如果您使用python 3并且希望每次运行都获得可重现的结果,则必须

  1. 在代码开头设置 numpy.random.seed
  2. 将 PYTHONHASHSEED=0 作为参数提供给 python 解释器
于 2016-08-15T06:57:53.947 回答
2

我已经Sequential()使用 Keras 训练和测试了一种神经网络。我对嘈杂的语音数据进行了非线性回归。我使用以下代码生成随机种子:

import numpy as np
seed = 7
np.random.seed(seed)

val_loss每次对相同数据进行训练和测试时,我都会得到完全相同的结果。

于 2016-07-14T10:17:14.887 回答
0

与之前所说的不同,只有 Tensorflow 种子对权重的随机生成有影响(最新版本的 Tensorflow 2.6.0 和 Keras 2.6.0)

这是一个小测试,您可以运行它来检查每个种子的影响(np 是 numpy,tf 是 tensorflow 和随机 Python 随机库):

# Testing how seeds influence results
# -----------------------------------

print("Seed specification")

my_seed = 36
# To vary python hash, numpy random, python random and tensorflow random seeds
a, b, c, d = 0, 0, 0, 0

os.environ['PYTHONHASHSEED'] = str(my_seed+a) # Has no effect
np.random.seed(my_seed+b) # Has no effect
random.seed(my_seed+c) # Has no effect
tf.random.set_seed(my_seed+d) # Has an effect

print("Making ML model")

keras.mixed_precision.set_global_policy('float64')

model = keras.Sequential([
    layers.Dense(2, input_shape=input_shape),#, activation='relu'),
    layers.Dense(output_nb, activation=None),
    ])
#
weights_save = model.get_weights()

print("Some weights:", weights_save[0].flatten())

我们注意到变量a, b,c对结果没有影响。只d对结果有影响。

所以,在最新版本的 Tensorflow 中,只有 tensorflow 随机种子对权重的随机选择有影响

于 2021-10-18T13:20:55.437 回答
0

我同意前面的评论,但可重现的结果有时需要相同的环境(例如安装的包、机器特性等)。因此,我建议将您的环境复制到其他地方,以防得到可重现的结果。尝试使用以下技术之一:

  1. 码头工人。如果你有一个 Linux 这很容易将你的环境移动到其他地方。您也可以尝试使用DockerHub
  2. 粘合剂。这是一个复制科学实验的云平台。
  3. 永件。这是另一个“可重复使用科学”的云平台。请参阅Github 上的项目存储库。
于 2016-04-27T11:44:02.840 回答
0

会议论文:用于可重复确定性的深度学习网络中的非随机权重初始化,出版日期 2019 年 6 月 5 日在英国利兹贝克特大学 (LBU) 举行的第 10 届 IEEE 国际会议可靠系统、服务和技术 (DESSERT-19) 上发表、英国、爱尔兰和 IEEE 乌克兰分部 2019 年 6 月 5-7 日

https://ieeexplore.ieee.org/document/8770007

展示了如何通过强制执行代码的关键区域来获得可重复的结果。

它已扩展为期刊论文:Repeatable Determinism using Non-Random Weight Initialisations in Smart City Applications of Deep Learning 发表于 The Journal of Reliable Intelligent Environments in a Smart Cities 特别版,并使用 glorot xavier limts 并达到与感知器层,但将权重增加到线性顺序,这可能有利于感知器层中的规则提取。

于 2020-01-11T13:33:27.977 回答