2017-10-19 19 views
4

J'ai le problème, que je ne suis pas capable de reproduire mes résultats avec Keras et ThensorFlow.Résultats non reproductibles avec Keras et TensorFlow en Python

Il semble qu'il y ait eu récemment une solution de contournement publiée sur le Keras documentation site pour ce problème, mais de toute façon cela ne fonctionne pas pour moi.

Qu'est-ce que je fais mal? J'utilise un bloc-notes Jupyter sur un MBP Retina (sans GPU Nvidia).

# ** 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 3.6.3 | Anaconda personnalisé (x86_64) | (par défaut, 6 oct. 2017, 12:04:38) [GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)]

La solution de contournement est déjà incluse dans le code (sans effet).

Avec chaque fois que je fais la partie d'entraînement, j'obtiens des résultats différents.

Lors de la réinitialisation du noyau du bloc-notes Jupyter, la première fois correspond à la première fois et la deuxième fois à la deuxième heure.

Donc, après la réinitialisation je toujours obtenir par exemple 0,7782 à la première manche, 0,7732 dans la deuxième manche, etc.

Mais les résultats sans remise à zéro du noyau sont toujours différents à chaque fois que je le lance.

Je serais utile pour toute suggestion!

+0

Pouvez-vous ajouter 'np.random.get_state()' et 'rn.getstate()' à la sortie? Utilisez-vous GPU ou CPU? Pouvez-vous essayer le script dans 'python'? – Maxim

Répondre

1

J'ai eu exactement le même problème et j'ai réussi à le résoudre en fermant et en redémarrant la session tensorflow chaque fois que j'exécute le modèle. Dans votre cas, il devrait ressembler à ceci:

#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() 

J'ai couru le code suivant et avait des résultats reproductibles en utilisant le GPU et backend 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() 

Et obtenu cette sortie:

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 

Ce que j'ai compris est que si vous ne fermez pas votre session tf (vous le faites en cours d'exécution dans un nouveau noyau) vous continuez à échantillonner la même distribution "semée".

+0

On dirait qu'il y a encore des différences dans le score, même s'il est proche. En ce moment j'ai besoin de faire un classement en fonction de la probabilité, donc même les petites différences comptent (donc je suis passé au backend Theano à cet effet). Mais merci! Je vais essayer quels résultats je reçois. –