ChatGPT解决这个技术问题 Extra ChatGPT

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

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

更新:如何复制:

安装 Keras (http://keras.io/) 执行 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 flag device=gpu0),那么我每次都会得到不同的测试精度,但是如果我在 CPU 上运行它,那么一切都会按预期工作。我的显卡:NVIDIA GeForce GT 635)

我无法在 ubuntu 14.04 上复制运行代码
theano -> 0.6.0numpy -> '1.9.2'scipy -> '0.15.1'
也许问题是我使用Windows。 numpy.random.uniform 工作正常,总是产生相同的结果。
GPU 代码必须大量使用类似 SIMD 的指令。这可能会导致以随机顺序调用随机生成器。 GPU 也是一个自治实体,它可以使用自己的随机生成器。毕竟,在 GPU 上运行任何你想要的代码都不是一件容易的事。
您使用的是哪个 CUDA 版本?你安装了 cuDNN 吗?我相信后者会为速度做出一些牺牲,从而导致 gpu 上的非确定性行为。 (应该是轻微的,我认为这与在 backrprop 上计算的原子操作有关,但你不会每次都得到相同的值。)

O
Outcast

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

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

将PYTHONHASHSEED环境变量设置为固定值 将python内置伪随机生成器设置为固定值 将numpy伪随机生成器设置为固定值 将tensorflow伪随机生成器设置为固定值 配置新的全局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)

不用说,您不必在 Python 脚本中使用的 numpyscikit-learntensorflow/keras 函数中指定任何 seedrandom_state,因为上面的源代码我们将它们的伪随机生成器全局设置为固定值。


对于更高版本的 tensorflow,如果遇到错误,请使用 tf.random.set_random_seed(seed_value)
谢谢,这对我有用!只是为了确定:运行脚本后我需要做些什么来“将随机性恢复正常”吗?还是设置 seed_values 仅具有“一次性效果”?
嘿@Frank,我认为如果你设置这样的种子值它不会恢复正常,除非你重新启动内核等(或自己设置不同的种子值等)。
@Outcast 在您发送 First, you need to set the PYTHONHASHSEED environment variable to 0 before the program starts (not within the program itself) 的 Keras 文档的链接上。您的答案设置不是PYTHONHASHSEED“程序本身”(os.environ['PYTHONHASHSEED']=str(seed_value))吗?
P
PabTorre

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

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

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

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

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

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

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

设置 numpy.random.seed;对 Python 3 使用 PYTHONHASHSEED=0。

然后,您必须通过使用以下附加 THEANO_FLAGS 调用您的 Keras 代码来解决 @user2805751 指出的关于 cuDNN 的问题:

dnn.conv.algo_bwd_filter=确定性,dnn.conv.algo_bwd_data=确定性

最后,您必须按照 this comment 修补您的 Theano 安装,主要包括:

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

这应该为您提供相同种子的相同结果。

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


u
user2543623

这个问题现在在 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)

A
Aaditya Ura

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

V
Victor Villacorta

这对我有用:

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)

O
Oscar Monge

它看起来更容易。仅此而已,它可以工作:

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 中检查时,这样做您将获得可重现的结果。


这种方法几乎对我有用。我必须将 os.environ["PYTHONHASHSEED"] = str(seed_value) 添加到函数体的开头,然后它才起作用。
A
Alex

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

在代码开头设置 numpy.random.seed 将 PYTHONHASHSEED=0 作为参数提供给 python 解释器


A
Autonomous

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

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

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


你用过GPU吗?什么后端:Theano 或 TensorFlow?
我将 CPU 与 Theano 后端一起使用。
知道了。 CPU对我来说也很好用。我只有在 GPU 上运行时才会遇到问题。
Y
Yelaman

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

码头工人。如果你有一个 Linux 这很容易将你的环境移动到其他地方。您也可以尝试使用 DockerHub。粘合剂。这是一个复制科学实验的云平台。永件。这是另一个“可重复使用科学”的云平台。请参阅 Github 上的项目存储库。


我的问题是,当我进行两次训练时,即使在相同的环境中,我也无法获得可重复的结果。
R
Richard Rudd-Orthner

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

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

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

它已扩展为期刊论文:Repeatable Determinism using Non-Random Weight Initialisations in Smart City Applications of Deep Learning 发表于 The Journal of Reliable Intelligent Environments in a Smart Cities 特别版,并使用 glorot xavier limts 并达到与感知器层,但将权重增加到线性顺序,这可能有利于感知器层中的规则提取。


T
Taha

与之前所说的不同,只有 Tensorflow 种子对权重的随机生成有影响(最新版本的 Tensorflow 2.6.0 和 Keras 2.6.0)

这是一个小测试,您可以运行它来检查每个种子的影响(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())

我们注意到变量 abc 对结果没有影响。只有 d 对结果有影响。

所以,在最新版本的 Tensorflow 中,只有 tensorflow 随机种子对权重的随机选择有影响。