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

Pav*_*nok 62 python numpy theano keras

每次我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

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

Poe*_*dit 31

您可以在Keras docs找到答案: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)
Run Code Online (Sandbox Code Playgroud)

这是不用说,你不必指定任何seedrandom_statenumpy,scikit-learntensorflow/ keras你正在使用完全相同在你的python脚本的功能,因为与源代码上面我们在一个固定值全局设置自己的伪随机生成.

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

Pab*_*rre 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
Run Code Online (Sandbox Code Playgroud)

  • 但是为了播种它们,我们需要访问keras将使用的theano的随机对象.是否可以通过keras API进行? (10认同)

kep*_*ler 12

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

  1. 设置numpy.random.seed;
  2. 使用PYTHONHASHSEED=0的Python 3.

然后你必须通过调用你的Keras代码解决有关cuDNN的@ user2805751注意到的问题,并附加以下内容THEANO_FLAGS:

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

最后,您必须根据此评论修补您的Theano安装,其中基本上包括:

  1. *_dev20其常规版本替换所有对运算符的调用theano/sandbox/cuda/opt.py.

这应该会为同一种子获得相同的结果.

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


use*_*623 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)
Run Code Online (Sandbox Code Playgroud)


Aad*_*Ura 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)
Run Code Online (Sandbox Code Playgroud)


小智 5

这对我有用:

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)
Run Code Online (Sandbox Code Playgroud)