即使设置了随机种子,为什么在Keras中仍无法获得可重复的结果? [英] Why can't I get reproducible results in Keras even though I set the random seeds?

查看:172
本文介绍了即使设置了随机种子,为什么在Keras中仍无法获得可重复的结果?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用Mac OSX上的Keras训练有关伪数据的MobileNet体系结构.我同时设置了nump.randomtensorflow.set_random_seed,但是由于某些原因,我无法获得可重复的结果:每次重新运行代码时,都会得到不同的结果.为什么?这不是由于GPU,因为我在具有Radeon显卡的MacBook Pro 2017上运行,因此Tensorflow没有利用它.该代码运行

I'm training a MobileNet architecture on dummy data with Keras, on Mac OSX. I set both nump.random and tensorflow.set_random_seed, but for some reasons I can't get reproducible results: each time I rerun the code, I get different results. Why? This is not due to the GPU, because I'm running on a MacBook Pro 2017 which has a Radeon graphics card, thus Tensorflow doesn't take advantage of it. The code is run with

python Keras_test.py

所以这不是状态问题(我不使用Jupyter或IPython:每次运行代码时都应重置环境).

so it's not a problem of state (I'm not using Jupyter or IPython: the environment should be reset each time I run the code).

编辑:我通过在导入Keras之前 移动所有种子的设置来更改代码.结果仍然不确定,但是结果的方差比以前小得多.这很奇怪.

EDIT: I changed my code by moving the setting of all seeds before importing Keras. The results are still not deterministic, however the variance in results is much smaller than it was before. This is very bizarre.

当前模型非常小(就深度神经网络而言)并不微不足道,它不需要GPU即可运行,并且可以在现代笔记本电脑上进行几分钟的训练,所以重复我的实验就可以在任何人的范围内进行抵达.我邀请您这样做:我非常有兴趣了解系统之间的差异程度.

The current model is very small (as far as deep neural network go) without being trivial, it doesn't need a GPU to run and it trains in a few minutes on a modern laptop, so repeating my experiments is within anyone's reach. I invite you to do it: I'd be very interested in learning about the level of variation from a system to another.

import numpy as np
# random seeds must be set before importing keras & tensorflow
my_seed = 512
np.random.seed(my_seed)
import random 
random.seed(my_seed)
import tensorflow as tf
tf.set_random_seed(my_seed)

# now we can import keras
import keras.utils
from keras.applications import MobileNet
from keras.callbacks import ModelCheckpoint
from keras.optimizers import Adam
import os

height = 224
width = 224
channels = 3
epochs = 10
num_classes = 10



# Generate dummy data
batch_size = 32  
n_train = 256
n_test = 64
x_train = np.random.random((n_train, height, width, channels))
y_train = keras.utils.to_categorical(np.random.randint(num_classes, size=(n_train, 1)), num_classes=num_classes)
x_test = np.random.random((n_test, height, width, channels))
y_test = keras.utils.to_categorical(np.random.randint(num_classes, size=(n_test, 1)), num_classes=num_classes)
# Get input shape
input_shape = x_train.shape[1:]

# Instantiate model 
model = MobileNet(weights=None,
                  input_shape=input_shape,
                  classes=num_classes)

model.compile(loss='categorical_crossentropy',
              optimizer='adam',
              metrics=['accuracy'])
# Viewing Model Configuration
model.summary()

# Model file name
filepath = 'model_epoch_{epoch:02d}_loss_{loss:0.2f}_val_{val_loss:.2f}.hdf5'

# Define save_best_only checkpointer
checkpointer = ModelCheckpoint(filepath=filepath,
                             monitor='val_acc',
                             verbose=1,
                             save_best_only=True)

# Let's fit!
model.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=epochs,
          validation_data=(x_test, y_test),
          callbacks=[checkpointer])

一如既往,这是我的Python,Keras& Tensorflow版本:

As always, here are my Python, Keras & Tensorflow versions:

python -c 'import keras; import tensorflow; import sys; print(sys.version, 'keras.__version__', 'tensorflow.__version__')'
/anaconda2/lib/python2.7/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
  from ._conv import register_converters as _register_converters
Using TensorFlow backend.
('2.7.15 |Anaconda, Inc.| (default, May  1 2018, 18:37:05) \n[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)]', '2.1.6', '1.8.0')

这是多次运行此代码获得的一些结果:如您所见,该代码使用描述性文件名保存了10个时间段内的最佳模型(最佳验证准确性),因此,比较不同运行过程中的文件名可以判断变异性结果.

Here are some results obtained running this code multiple times: as you can see, the code saves the best model (best validation accuracy) out of 10 epochs with a descriptive filename, so comparing filenames across different runs allows to judge the variability in results.

model_epoch_01_loss_2.39_val_3.28.hdf5
model_epoch_01_loss_2.39_val_3.54.hdf5
model_epoch_01_loss_2.40_val_3.47.hdf5
model_epoch_01_loss_2.41_val_3.08.hdf5

推荐答案

您可以在Keras文档中找到答案:

You can find the answer at Keras docs: https://keras.io/getting-started/faq/#how-can-i-obtain-reproducible-results-using-keras-during-development.

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

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:

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

在顶部的Keras链接之后,我使用的源代码如下:

Following the Keras link at the top, the source code I am using is the following:

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

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

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

# 3. Set `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脚本中使用的numpyscikit-learntensorflow/keras函数中指定任何seedrandom_state正是因为上面的源代码中,我们将其伪随机数发生器全局设置为固定值.

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.

这篇关于即使设置了随机种子,为什么在Keras中仍无法获得可重复的结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆