如何在keras中获得可重现的结果

时间:2015-09-06 02:41:12

标签: python numpy theano keras

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

更新:如何重新制作:

  1. 安装Keras(http://keras.io/
  2. 执行https://github.com/fchollet/keras/blob/master/examples/imdb_lstm.py几次。它将训练模型并输出测试精度 预期结果:每次运行的测试精度都相同 实际结果:每次运行的测试精度都不同。
  3. UPDATE2:我在Windows 8.1上使用MinGW / msys运行它,模块版本:
    theano 0.7.0
    numpy 1.8.1
    scipy 0.14.0c1

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

11 个答案:

答案 0 :(得分:14)

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

不用说,您不必在seedrandom_statenumpy / {{上指定任何scikit-learntensorflow 1}}在您的python脚本中使用的函数正是因为上面的源代码将它们的伪随机生成器全局设置为固定值。

答案 1 :(得分:13)

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

  

在不同{{{RandomOp}}}之间共享随机数生成器   实例使得无论如何都难以生成相同的流   其他操作在图表中,并保持{{{RandomOps}}}孤立。   因此,图表中的每个{{{RandomOp}}}实例都具有其实例   自己的随机数发生器。该随机数生成器是输入   到功能。在典型用法中,我们将使用的新功能   函数输入({{{value}}},{{{update}}})来传递和更新rng   每个{{{RandomOp}}}。通过传递RNG作为输入,有可能   使用访问功能输入的常规方法来访问每个   {{{RandomOp}}}的问题。在这种方法中,它没有预先存在   使用整个组合随机数状态的机制   图形。所以提议是提供缺少的功能(   最后三个要求)通过辅助功能:{{{seed,getstate,   setstate这}}}

他们还提供examples如何为所有随机数生成器播种。

  

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

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

答案 2 :(得分:11)

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

  1. 设置numpy.random.seed;
  2. 对Python 3使用PYTHONHASHSEED=0
  3. 然后,您必须通过使用以下附加THEANO_FLAGS调用您的Keras代码来解决@ user2805751关于cuDNN的问题:

    1. dnn.conv.algo_bwd_filter=deterministic,dnn.conv.algo_bwd_data=deterministic
    2. 最后,您必须根据this comment修补您的Theano安装,其基本包括:

      1. 将所有对*_dev20运算符的调用替换为theano/sandbox/cuda/opt.py中的常规版本。
      2. 这可以为同一种子获得相同的结果。

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

答案 3 :(得分:1)

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

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

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

答案 4 :(得分:1)

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

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

答案 5 :(得分:1)

现在在Tensorflow 2.0中解决了问题!我对TF 1.x有同样的问题(请参阅If Keras results are not reproducible, what's the best practice for comparing models and choosing hyper parameters?),但

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)

答案 6 :(得分:0)

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

  1. Docker。如果你有Linux,这很容易将你的环境转移到其他地方。您也可以尝试使用DockerHub
  2. Binder。这是一个用于复制科学实验的云平台。
  3. Everware。这是可重用科学的另一个云平台"。请参阅Github上的project repository

答案 7 :(得分:0)

这对我有用:

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)

答案 8 :(得分:0)

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

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

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

它已扩展到期刊论文:在深度学习的智能城市应用中使用非随机权重初始化的可重复确定性 出版于《智能城市中的可靠智能环境期刊》特别版中,它使用glorot xavier limts并在感知器层上达到相同的精度,但权重增加到线性顺序,这可能对感知器层中的规则提取具有优势。 / p>

答案 9 :(得分: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)

答案 10 :(得分:0)

看起来似乎更容易。只放这个,就可以了:

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中签入时,您将获得可重复的结果。