简体   繁体   English

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

[英]How to get reproducible results in keras

I get different results (test accuracy) every time I run the imdb_lstm.py example from Keras framework ( https://github.com/fchollet/keras/blob/master/examples/imdb_lstm.py ) The code contains np.random.seed(1337) in the top, before any keras imports.每次我从imdb_lstm.py框架 ( https://github.com/fchollet/keras/blob/master/examples/imdb_lstm.py ) 运行imdb_lstm.py示例时,我都会得到不同的结果(测试准确性),代码包含np.random.seed(1337)在顶部,在任何 keras 导入之前。 It should prevent it from generating different numbers for every run.它应该防止它为每次运行生成不同的数字。 What am I missing?我错过了什么?

UPDATE: How to repro:更新:如何重现:

  1. Install Keras ( http://keras.io/ )安装 Keras ( http://keras.io/ )
  2. Execute https://github.com/fchollet/keras/blob/master/examples/imdb_lstm.py a few times.执行https://github.com/fchollet/keras/blob/master/examples/imdb_lstm.py几次。 It will train the model and output test accuracy.它将训练模型并输出测试精度。
    Expected result: Test accuracy is the same on every run.预期结果:每次运行的测试准确度都相同。
    Actual result: Test accuracy is different on every run.实际结果:每次运行的测试精度都不同。

UPDATE2: I'm running it on Windows 8.1 with MinGW/msys, module versions: UPDATE2:我在 Windows 8.1 上使用 MinGW/msys 运行它,模块版本:
theano 0.7.0西诺 0.7.0
numpy 1.8.1麻木 1.8.1
scipy 0.14.0c1 scipy 0.14.0c1

UPDATE3: I narrowed the problem down a bit. UPDATE3:我把问题缩小了一点。 If I run the example with GPU (set theano flag device=gpu0) then I get different test accuracy every time, but if I run it on CPU then everything works as expected.如果我使用 GPU 运行示例(设置 theano 标志 device=gpu0),那么我每次都会获得不同的测试准确度,但是如果我在 CPU 上运行它,那么一切都会按预期进行。 My graphics card: NVIDIA GeForce GT 635)我的显卡:NVIDIA GeForce GT 635)

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

In short, to be absolutely sure that you will get reproducible results with your python script on one computer's/laptop's CPU then you will have to do the following:简而言之,要绝对确定您将在一台计算机/笔记本电脑的 CPU 上使用您的 python 脚本获得可重现的结果,那么您必须执行以下操作:

  1. Set the PYTHONHASHSEED environment variable at a fixed valuePYTHONHASHSEED环境变量设置为固定值
  2. Set the python built-in pseudo-random generator at a fixed valuepython内置的伪随机生成器设置为固定值
  3. Set the numpy pseudo-random generator at a fixed valuenumpy伪随机生成器设置为固定值
  4. Set the tensorflow pseudo-random generator at a fixed valuetensorflow伪随机生成器设置为固定值
  5. Configure a new global tensorflow session配置一个新的全局tensorflow会话

Following the Keras link at the top, the source code I am using is the following:按照顶部的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)

It is needless to say that you do not have to to specify any seed or random_state at the numpy , scikit-learn or tensorflow / keras functions that you are using in your python script exactly because with the source code above we set globally their pseudo-random generators at a fixed value.不用说,您不必在 Python 脚本中使用的numpyscikit-learntensorflow / keras函数中指定任何seedrandom_state正是因为使用上面的源代码我们全局设置了它们的伪固定值的随机生成器。

Theano's documentation talks about the difficulties of seeding random variables and why they seed each graph instance with its own random number generator. Theano 的文档讨论了播种随机变量的困难以及为什么他们用自己的随机数生成器播种每个图实例。

Sharing a random number generator between different {{{RandomOp}}} instances makes it difficult to producing the same stream regardless of other ops in graph, and to keep {{{RandomOps}}} isolated.在不同的 {{{RandomOp}}} 实例之间共享一个随机数生成器使得无论图中的其他操作如何都难以产生相同的流,并且很难保持 {{{RandomOps}}} 的隔离。 Therefore, each {{{RandomOp}}} instance in a graph will have its very own random number generator.因此,图中的每个 {{{RandomOp}}} 实例都有自己的随机数生成器。 That random number generator is an input to the function.该随机数生成器是该函数的输入。 In typical usage, we will use the new features of function inputs ({{{value}}}, {{{update}}}) to pass and update the rng for each {{{RandomOp}}}.在典型用法中,我们将使用函数输入的新特征({{{value}}},{{{update}}})来传递和更新每个 {{{RandomOp}}} 的 rng。 By passing RNGs as inputs, it is possible to use the normal methods of accessing function inputs to access each {{{RandomOp}}}'s rng.通过将 RNG 作为输入传递,可以使用访问函数输入的正常方法来访问每个 {{{RandomOp}}} 的 rng。 In this approach it there is no pre-existing mechanism to work with the combined random number state of an entire graph.在这种方法中,没有预先存在的机制来处理整个图的组合随机数状态。 So the proposal is to provide the missing functionality (the last three requirements) via auxiliary functions: {{{seed, getstate, setstate}}}.所以提议是通过辅助函数提供缺失的功能(最后三个要求):{{{seed, getstate, setstate}}}。

They also provide examples on how to seed all the random number generators.他们还提供了有关如何为所有随机数生成器播种的 示例

You can also seed all of the random variables allocated by a RandomStreams object by that object's seed method.您还可以通过该对象的种子方法为 RandomStreams 对象分配的所有随机变量做种子。 This seed will be used to seed a temporary random number generator, that will in turn generate seeds for each of the random variables.该种子将用于为临时随机数生成器提供种子,该生成器将依次为每个随机变量生成种子。

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

I finally got reproducible results with my code.我终于用我的代码得到了可重现的结果。 It's a combination of answers I saw around the web.这是我在网上看到的答案的组合。 The first thing is doing what @alex says:第一件事就是按照@alex 所说的去做:

  1. Set numpy.random.seed ;设置numpy.random.seed
  2. Use PYTHONHASHSEED=0 for Python 3.对 Python 3 使用PYTHONHASHSEED=0

Then you have to solve the issue noted by @user2805751 regarding cuDNN by calling your Keras code with the following additional THEANO_FLAGS :然后,您必须通过使用以下附加THEANO_FLAGS调用您的 Keras 代码来解决 @user2805751 指出的有关 cuDNN 的问题:

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

And finally, you have to patch your Theano installation as per this comment , which basically consists in:最后,你必须按照这个评论修补你的 Theano 安装,它基本上包括:

  1. replacing all calls to *_dev20 operator by its regular version in theano/sandbox/cuda/opt.py .theano/sandbox/cuda/opt.py常规版本替换对*_dev20运算符的所有调用。

This should get you the same results for the same seed.对于相同的种子,这应该会得到相同的结果。

Note that there might be a slowdown.请注意,可能会出现放缓。 I saw a running time increase of about 10%.我看到运行时间增加了大约 10%。

The problem is now solved in Tensorflow 2.0 !这个问题现在在 Tensorflow 2.0 中解决了! I had the same issue with TF 1.x (see If Keras results are not reproducible, what's the best practice for comparing models and choosing hyper parameters? ) but我对 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)

In Tensorflow 2.0 you can set random seed like this :在 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)

This works for me:这对我有用:

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)

I have trained and tested Sequential() kind of neural networks using Keras.我已经使用 Keras 训练和测试了Sequential()类型的神经网络。 I performed non linear regression on noisy speech data.我对嘈杂的语音数据进行了非线性回归。 I used the following code to generate random seed :我使用以下代码生成随机种子:

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

I get the exact same results of val_loss each time I train and test on the same data.每次训练和测试相同的数据时,我都会得到完全相同的val_loss结果。

I would like to add something to the previous answers.我想在以前的答案中添加一些内容。 If you use python 3 and you want to get reproducible results for every run, you have to如果您使用python 3并且希望每次运行都获得可重现的结果,则必须

  1. set numpy.random.seed in the beginning of your code在代码的开头设置 numpy.random.seed
  2. give PYTHONHASHSEED=0 as a parameter to the python interpreter将 PYTHONHASHSEED=0 作为参数提供给 python 解释器

It is easier that it seems.看起来更容易。 Putting only this, it works:只放这个,它的工作原理:

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() 

The KEY of the question, VERY IMPORTANT, is to call the function reset_seeds() every time before running the model.问题的关键,非常重要,是每次运行模型之前调用函数 reset_seeds()。 Doing that you will obtain reproducible results as I check in the Google Collab.当我在 Google 协作中检查时,这样做您将获得可重复的结果。

I agree with the previous comment, but reproducible results sometimes needs the same environment(eg installed packages, machine characteristics and so on).我同意之前的评论,但可重现的结果有时需要相同的环境(例如已安装的包、机器特性等)。 So that, I recommend to copy your environment to other place in case to have reproducible results.因此,我建议将您的环境复制到其他地方,以防得到可重现的结果。 Try to use one of the next technologies:尝试使用以下技术之一:

  1. Docker .码头工人 If you have a Linux this very easy to move your environment to other place.如果您有 Linux,这很容易将您的环境移动到其他地方。 Also you can try to use DockerHub .您也可以尝试使用DockerHub
  2. Binder .粘合剂 This is a cloud platform for reproducing scientific experiments.这是一个复制科学实验的云平台。
  3. Everware .永远软件 This is yet another cloud platform for "reusable science".这是“可重用科学”的又一个云平台。 See the project repository on Github.请参阅 Github 上的项目存储库

The Conference Paper: Non-Random Weight Initialisation in Deep Learning Networks for Repeatable Determinism, publication date Jun 5, 2019 presented at 10th IEEE International Conference Dependable Systems, Services and Technologies (DESSERT-19) at Leeds Beckett University (LBU), United Kingdom, UK, Ireland and the Ukrainian section of IEEE June 5-7, 2019会议论文:用于可重复确定性的深度学习网络中的非随机权重初始化,发表日期 2019 年 6 月 5 日,发表于英国利兹贝克特大学 (LBU) 的第 10 届 IEEE 国际可靠系统、服务和技术会议 (DESSERT-19) 、英国、爱尔兰和 IEEE 乌克兰部分 2019 年 6 月 5-7 日

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

shows how to get repeatable results by enforcing critical regions of code.展示了如何通过强制执行代码的关键区域来获得可重复的结果。

it has been extended to a Journal Paper: Repeatable Determinism using Non-Random Weight Initialisations in Smart City Applications of Deep Learning publication in The Journal of Reliable Intelligent Environments in a Smart Cities special edition, and uses glorot xavier limts and achieve the same accuracy with perceptron layers but grow the weight in to a linear order which may have an advantage for rule extraction in perceptron layers.它已扩展为期刊论文:在智能城市应用的深度学习中使用非随机权重初始化的可重复确定性发表在智能城市特别版的可靠智能环境期刊中,并使用 glorot xavier 限制并达到与感知器层,但将权重增加到线性顺序,这可能有利于感知器层中的规则提取。

Unlike what has been said before, only Tensorflow seed has an effect on random generation of weights (latest version Tensorflow 2.6.0 and Keras 2.6.0)与之前所说的不同,只有 Tensorflow 种子对权重的随机生成有影响(最新版本 Tensorflow 2.6.0 和 Keras 2.6.0)

Here is a small test you can run to check the influence of each seed (with np being numpy, tf being tensorflow and random the Python random library):这是一个小测试,您可以运行它来检查每个种子的影响(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())

We notice that variables a , b , c have no effect on the results.我们注意到变量abc对结果没有影响。 Only d has an effect on the results.只有d对结果有影响。

So, in the latest versions of Tensorflow, only tensorflow random seed has an influence on the random choice of weights.因此,在最新版本的 Tensorflow 中,只有 tensorflow 随机种子对权重的随机选择有影响

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM