繁体   English   中英

Keras LSTM - 为什么“相同”模型和相同权重的结果不同?

[英]Keras LSTM - why different results with “same” model & same weights?

注意:在每个模型创建之前正确修复 RNG 状态,如评论中的评论中所述实际上解决了我的问题,因为小数点后 3 位内的结果是一致的,但它们并非完全如此,因此在某处存在未修复的隐藏随机源播种 RNG ......可能有些库使用时间毫秒或 smth ......如果有人对此有想法,知道会很酷,所以我会等待而不是关闭问题:) )

我创建了一个Keras LSTM 模型(用于预测一些时间序列数据,不重要的是什么),并且每次我尝试重新创建一个相同的模型(从 json 加载相同的模式配置,从文件加载相同的权重,编译相同的 args函数),我在相同的训练和测试数据上得到了截然不同的结果 为什么?

代码大致是这样的:

# fix random
import random
random.seed(42)

# make model & compile
model = Sequential([
    LSTM(50, input_shape=(None, 1), return_sequences=True),
    LSTM(100, return_sequences=False),
    Dense(1),
    Activation("linear")
])
model.compile(loss="mse", optimizer="rmsprop")

# save it and its initial random weights
model_json = model.to_json()
model.save_weights("model.h5")

# fit and predict
model.fit(x_train, y_train, epochs=3)
r = model.predict(x_test)

# create new "identical" model
model2 = model_from_json(model_json)
model2.load_weights("model.h5")
model2.compile(loss="mse", optimizer="rmsprop")

# fit and predict "identical" model
model2.fit(x_train, y_train, epochs=3)
r2 = model2.predict(x_test)

# ...different results :(

我知道模型具有初始随机权重,因此我将它们保存并重新加载。 我也很偏执,假设有一些我可能不知道的“隐藏”参数,所以我将模型序列化为 json 并重新加载,而不是手动重新创建一个相同的参数(尝试过,同样的事情)。 我还修复了随机数生成器。

这是我第一次使用 Keras,而且我也是一般神经网络的初学者。 但这让我发疯...... wtf 可能会有所不同?!


关于修复随机数生成器:我使用 TensorFlow 后端运行 Keras,并且在开始时我有这些代码行来尝试修复 RNG 以用于实验目的:

import random
random.seed(42)
import numpy
numpy.random.seed(42)
from tensorflow import set_random_seed
set_random_seed(42)

...但他们仍然没有解决随机性。

而且我知道目标是让我的模型表现出非随机性,尽管NN 具有固有的随机性。 但是为了实验目的我需要暂时修复这个问题(我什至可以在一台机器上重现它!)。

机器学习算法通常是非确定性的 这意味着每次运行它们时,结果都应该有所不同。 这与权重的随机初始化有关。 如果您想让结果可重复,您必须消除表格中的随机性。 一个简单的方法是使用随机种子

import numpy as np
import tensorflow as tf

np.random.seed(1234)
tf.random.set_seed(1234)

# rest of your code

如果您想要随机因子但输出中的方差不那么大,我建议您降低学习率或更改优化器(我建议使用学习率相对较低的 SGD 优化器)。 梯度下降优化清凉的概述,请点击这里


关于 TensorFlow 随机生成器的一个说明是,除了全局种子(即tf.random.set_seed() )之外,它们还使用内部计数器,因此如果您运行

tf.random.set_seed(1234)
print(tf.random.uniform([1]).numpy())
print(tf.random.uniform([1]).numpy())

您将分别获得0.53803930.3253647 但是,如果您重新运行相同的代码段,您将再次获得相同的两个数字。

可以在 此处找到有关 TensorFlow 中随机种子如何工作的详细说明。


对于较新的 TF 版本,也请注意这一点: TensorFlow 2.2 附带一个操作系统环境变量TF_DETERMINISTIC_OPS ,如果设置为'1' ,将确保仅使用确定性 GPU 操作。

此代码适用于使用 tensorflow 后端的 keras

这是因为权重是使用随机数初始化的,因此每次都会得到不同的结果。 这是预期的行为。 要获得可重复的结果,您需要将随机种子设置为。 下面的示例设置操作级和图形级种子有关更多信息,请查看此处

import tensorflow as tf
import random as rn

os.environ['PYTHONHASHSEED'] = '0'

# Setting the seed for numpy-generated random numbers
np.random.seed(37)

# Setting the seed for python random numbers
rn.seed(1254)

# Setting the graph-level random seed.
tf.set_random_seed(89)

from keras import backend as K

session_conf = tf.ConfigProto(
      intra_op_parallelism_threads=1,
      inter_op_parallelism_threads=1)

#Force Tensorflow to use a single thread
sess = tf.Session(graph=tf.get_default_graph(), config=session_conf)

K.set_session(sess)

# Rest of the code follows from here on ...

我通过添加os.environ['TF_DETERMINISTIC_OPS'] = '1'解决了这个问题

这里有一个例子:

import os
os.environ['TF_DETERMINISTIC_OPS'] = '1'
#rest of the code
# tf version 2.3.1

暂无
暂无

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

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