使用Python中的Keras和TensorFlow无法重现结果

时间:2017-10-19 18:48:37

标签: python python-3.x random tensorflow keras

我遇到了问题,我无法使用Keras和ThensorFlow重现我的结果。

好像最近在Keras documentation site上发布了针对此问题的解决方法,但不知何故,它对我不起作用。

我做错了什么?

我在MBP Retina上使用Jupyter笔记本(没有Nvidia GPU)。

# ** Workaround from Keras Documentation **

import numpy as np
import tensorflow as tf
import random as rn

# The below is necessary in Python 3.2.3 onwards to
# have reproducible behavior for certain hash-based operations.
# See these references for further details:
# https://docs.python.org/3.4/using/cmdline.html#envvar-PYTHONHASHSEED
# https://github.com/fchollet/keras/issues/2280#issuecomment-306959926

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

# The below is necessary for starting Numpy generated random numbers
# in a well-defined initial state.

np.random.seed(42)

# The below is necessary for starting core Python generated random numbers
# in a well-defined state.

rn.seed(12345)

# Force TensorFlow to use single thread.
# Multiple threads are a potential source of
# non-reproducible results.
# For further details, see: https://stackoverflow.com/questions/42022950/which-seeds-have-to-be-set-where-to-realize-100-reproducibility-of-training-res

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

from keras import backend as K

# The below tf.set_random_seed() will make random number generation
# in the TensorFlow backend have a well-defined initial state.
# For further details, see: https://www.tensorflow.org/api_docs/python/tf/set_random_seed

tf.set_random_seed(1234)

sess = tf.Session(graph=tf.get_default_graph(), config=session_conf)
K.set_session(sess)


# ** Workaround end **

# ** Start of my code **


# LSTM and CNN for sequence classification in the IMDB dataset
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from keras.layers.embeddings import Embedding
from keras.preprocessing import sequence
from sklearn import metrics
# fix random seed for reproducibility
#np.random.seed(7)

# ... importing data and so on ...

# create the model
embedding_vecor_length = 32
neurons = 91
epochs = 1
model = Sequential()
model.add(Embedding(top_words, embedding_vecor_length, input_length=max_review_length))
model.add(LSTM(neurons))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='mean_squared_logarithmic_error', optimizer='adam', metrics=['accuracy'])
print(model.summary())
model.fit(X_train, y_train, epochs=epochs, batch_size=64)
# Final evaluation of the model
scores = model.evaluate(X_test, y_test, verbose=0)
print("Accuracy: %.2f%%" % (scores[1]*100))

使用过的Python版本:

Python 3.6.3 |Anaconda custom (x86_64)| (default, Oct  6 2017, 12:04:38) 
[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)]

解决方法已包含在代码中(无效)。

每次我做训练时,我都会得到不同的结果。

重置Jupyter笔记本的内核时,第一次对应第一次,第二次对应第二次。

因此,重置后我会在第一次运行时获得0.7782,第二次运行时会0.7732等。

但是每次运行时没有内核重置的结果总是不同的。

我会对任何建议都有帮助!

4 个答案:

答案 0 :(得分:4)

我有完全相同的问题,并设法通过每次运行模型时关闭并重新启动tensorflow会话来解决它。在你的情况下,它应该是这样的:

#START A NEW TF SESSION
np.random.seed(0)
tf.set_random_seed(0)
sess = tf.Session(graph=tf.get_default_graph())
K.set_session(sess)

embedding_vecor_length = 32
neurons = 91
epochs = 1
model = Sequential()
model.add(Embedding(top_words, embedding_vecor_length, input_length=max_review_length))
model.add(LSTM(neurons))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='mean_squared_logarithmic_error', optimizer='adam', metrics=['accuracy'])
print(model.summary())
model.fit(X_train, y_train, epochs=epochs, batch_size=64)
# Final evaluation of the model
scores = model.evaluate(X_test, y_test, verbose=0)
print("Accuracy: %.2f%%" % (scores[1]*100))

#CLOSE TF SESSION
K.clear_session()

我运行了以下代码,并使用GPU和tensorflow后端获得了可重现的结果:

print datetime.now()
for i in range(10):
    np.random.seed(0)
    tf.set_random_seed(0)
    sess = tf.Session(graph=tf.get_default_graph())
    K.set_session(sess)

    n_classes = 3
    n_epochs = 20
    batch_size = 128

    task = Input(shape = x.shape[1:])
    h = Dense(100, activation='relu', name='shared')(task)
    h1= Dense(100, activation='relu', name='single1')(h)
    output1 = Dense(n_classes, activation='softmax')(h1)

    model = Model(task, output1)
    model.compile(loss='categorical_crossentropy', optimizer='Adam')
    model.fit(x_train, y_train_onehot, batch_size = batch_size, epochs=n_epochs, verbose=0)
print(model.evaluate(x=x_test, y=y_test_onehot, batch_size=batch_size, verbose=0))
K.clear_session()

获得此输出:

2017-10-23 11:27:14.494482
0.489712882132
0.489712893813
0.489712892765
0.489712854426
0.489712882132
0.489712864011
0.486303713004
0.489712903398
0.489712892765
0.489712903398

我的理解是,如果你不关闭你的tf会话(你是通过在一个新的内核中运行它),你会继续采样相同的#34;种子"分配。

答案 1 :(得分:0)

不确定TensorFlow / Keras中的错误。将Keras后端设置为CNTK时,结果是可重现的。

我什至尝试了从1.2.1到1.13.1的多个版本的TensorFlow。所有TensorFlow版本的结果都与多次运行不一致,即使设置了随机种子也是如此。

答案 2 :(得分:0)

以下是我的答案,它使用带有Tensorflow的Keras作为后端。在嵌套的for循环中,通常在其中循环访问您希望为模型开发探索的各种参数,然后在上一个for loop之后立即添加此函数。

for...
   for...
      reset_keras()
      .
      .
      .

其中重置功能定义为

def reset_keras():
    sess = tf.keras.backend.get_session()
    tf.keras.backend.clear_session()
    sess.close()
    sess = tf.keras.backend.get_session()
    np.random.seed(1)
    tf.set_random_seed(2)

PS:上面的函数实际上还避免了您的nvidia GPU建立过多的内存(这种情况在多次迭代之后发生),从而使其最终变得非常缓慢...因此,该函数可恢复GPU的性能并将结果保持可重复性。

答案 3 :(得分:0)

最有效的方法是每次在新控制台中进行培训。除此之外,我还设置了以下参数:

RANDOM_STATE = 42

os.environ['PYTHONHASHSEED'] = str(RANDOM_STATE)
random.seed(RANDOM_STATE)
np.random.seed(RANDOM_STATE)
tf.set_random_seed(RANDOM_STATE)

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)

intra_op_parallelism 也可能是一个更大的值