2017-01-24 3 views
2

J'ai fait un petit changement au tutoriel Tensorflow MNIST. Code d'origine (fully_connected_feed.py, lignes 194-202):Changement de données entre les appels dans Tensorflow

checkpoint_file = os.path.join(FLAGS.log_dir, 'model.ckpt') 
saver.save(sess, checkpoint_file, global_step=global_step) 
#Evaluate against the training set. 
print('Training Data Eval:') 
do_eval(sess, 
     eval_correct, 
     images_placeholder, 
     labels_placeholder, 
     data_sets.train) 

J'ai simplement ajouté une évaluation:

checkpoint_file = os.path.join(FLAGS.log_dir, 'model.ckpt') 
saver.save(sess, checkpoint_file, global_step=global_step) 
print('Something strange:') 
do_eval(sess, eval_correct, images_placeholder,labels_placeholder, 
     data_sets.train) 
#Evaluate against the training set. 
print('Training Data Eval:') 
do_eval(sess, 
     eval_correct, 
     images_placeholder, 
     labels_placeholder, 
     data_sets.train) 

Les résultats de cette évaluation sont proches, mais pas mêmes (les chiffres varient du lancement au lancement):

Something strange: 
    Num examples: 55000 Num correct: 49218 Precision @ 1: 0.8949 
Training Data Eval: 
    Num examples: 55000 Num correct: 49324 Precision @ 1: 0.8968 

Comment est-ce possible? UPD: Lien ajouté à tensorflow github: https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/tutorials/mnist

+0

Aucune idée sur le flux tensor, mais cela ne devrait pas arriver généralement. Est-ce que do_eval a des effets secondaires non intentionnels? Avez-vous vérifié la documentation? –

+0

Je ne sais pas d'où ces effets secondaires pourraient provenir. Le code do_eval n'a d'appel qu'à la méthode evaluation() de mnist.py, et cette méthode n'apporte aucune modification aux tenseurs. –

+0

Cela semble plutôt bizarre. Je ne suis pas très familier avec tensorflow spécifiquement, mais je ne vois pas de quelle façon cela pourrait être considéré comme un comportement sain (je suppose que do_eval devrait juste passer les échantillons et calculer la précision sans changer le net). –

Répondre

3

La fonction do_eval() en fait a un effet secondaire, parce que data_sets.train est un stateful DataSet object qui contient un élément _index_in_epoch courant, qui est avancé sur chaque appel à DataSet.next_batch() (c.-à fill_feed_dict()).

À lui seul, ce fait ne devrait pas être suffisant pour donner des résultats non-déterministe, mais il y a deux autres détails sur DataSet.next_batch() qui conduisent à la non-déterminisme:

  1. Chaque fois qu'une nouvelle époque est démarré, les exemples sont randomly shuffled. Lorsque l'ensemble de données est reaches the end of an epoch, l'ensemble de données est réinitialisé au début et les derniers exemples num_examples % batch_size sont ignorés. Grâce au remaniement aléatoire, un sous-lot aléatoire d'exemples est mis au rebut à chaque fois, conduisant aux résultats non déterministes.

Compte tenu de la façon dont le code est structuré (avec le DataSet partagé entre la formation et les tests), il est difficile de rendre le code déterministe. La classe DataSet est peu documentée, mais ce comportement est surprenant, donc je considérerais filing a GitHub issue à propos de ce problème.

+2

Merci beaucoup! Et j'ai trouvé un moyen de rendre les calculs déterministes - il suffit de définir batch_size égal au nombre d'exemples dans l'ensemble de données. De cause, c'est utile seulement pour le débogage. –