如何在keras中获得可复制的结果


78

每次我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标志device = gpu0),则每次都会获得不同的测试准确性,但是如果我在CPU上运行,那么一切都会按预期进行。我的显卡:NVIDIA GeForce GT 635)


我无法在ubuntu 14.04
Padraic Cunningham

theano -> 0.6.0numpy -> '1.9.2'scipy -> '0.15.1'
帕德里克·坎宁安

也许问题是我使用Windows。numpy.random.uniform工作正常,始终产生相同的结果。
Pavel Surmenok 2015年

4
GPU的代码必须SIMD大量使用类似指令。这可能导致随机生成器以随机顺序被调用。此外,GPU还是一个自治实体,它可以使用自己的随机生成器。毕竟,在GPU上运行您想要的任何代码并不容易。
u354356007's

2
您使用了哪个CUDA版本?您安装了cuDNN吗?我相信后者会牺牲一些速度,从而导致GPU上的不确定行为。(应该是轻微的,我认为这与在backrprop上计算原子操作有关,但是每次都不会获得相同的值。)
user2805751 2015年

Answers:


48

您可以在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)

这是不用说,你不必指定任何seedrandom_statenumpyscikit-learntensorflow/keras功能您正在使用您的python脚本正是因为与源代码上面我们在全球建立自己的伪随机生成的一个固定值。


2
对于更高版本的tensorflow,如果遇到错误,请使用tf.random.set_random_seed(seed_value)
Kalpit

13

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

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

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

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

>>> srng.seed(902340)  # seeds rv_u and rv_n with different seeds each

11
但是为了播种它们,我们需要访问keras将使用的theano随机对象。是否可以通过keras API进行操作?
最高

12

我的代码终于得到了可复制的结果。这是我在网上看到的答案的组合。首先要做的是@alex说的:

  1. 设置numpy.random.seed;
  2. 使用PYTHONHASHSEED=0的Python 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%。


4

现在在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)

2

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

  1. 在代码开头设置numpy.random.seed
  2. 给PYTHONHASHSEED = 0作为python解释器的参数

2

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

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

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


1
您使用过GPU吗?什么后端:Theano或TensorFlow?
Pavel Surmenok

我在Theano后端使用了CPU。
tauseef_CuriousGuy

1
得到它了。CPU也适合我。我只有在GPU上运行时才有问题。
Pavel Surmenok

2

这对我有用:

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)

0

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

  1. 泊坞窗。如果您使用的是Linux,那么将环境轻松转移到其他地方非常容易。您也可以尝试使用DockerHub
  2. 活页夹。这是一个用于复制科学实验的云平台。
  3. 永恒软件。这是用于“可重用科学”的另一个云平台。请参阅Github上的项目存储库

我的问题是,即使我在同一环境下进行两次训练,也无法获得可重复的结果。
Pavel Surmenok

0

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

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

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

它已扩展为期刊论文:《智慧城市中可靠的智能环境期刊》特刊中的《深度学习在智慧城市中使用非随机权重初始化的可重复确定性》,并使用glorot xavier limt并在相同精度下达到了感知器层,但是权重以线性顺序增长,这对于感知器层中的规则提取可能具有优势。


0

在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)
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.