Keras LSTM - 为什么与"相同"模特&相同的重量?

时间:2017-09-08 15:03:18

标签: python machine-learning neural-network keras lstm

注意:在每个模型创建之前正确修复RNG状态,如评论中的评论几乎修复我的问题,因为3位小数内的结果是一致的,但是并非完全如此,所以在某处隐藏的随机性来源无法通过播种RNG来修复...可能有些lib使用时间milisecs或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的固有随机性。但我需要暂时将其修复用于实验目的(我甚至可以在一台机器上重现它!)。

3 个答案:

答案 0 :(得分:4)

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

import numpy as np
np.random.seed(1234)

# rest of your code

如果你想要输出中的随机因子而不是那么高的方差,我会建议你降低你的学习率或改变你的优化器(我会建议学习率相对较低的SGD优化器)。有关梯度下降优化的详细概述here

答案 1 :(得分:2)

  

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

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

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 ...

答案 2 :(得分:1)

我通过添加 os.environ['TF_DETERMINISTIC_OPS'] = '1'

解决了这个问题

这里有一个例子:

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