2 votes

Le nombre d'étapes ne correspond pas lors de l'utilisation de tf.estimator.Estimator

Je suis en train de comprendre le cadre d'estimateurs TensorFlow. J'ai enfin du code pour un modèle qui s'entraîne. J'utilise un autoencodeur MNIST simple pour mes tests. J'ai deux questions. La première question est pourquoi le nombre d'étapes rapporté par l'entraînement est différent du nombre d'étapes que je spécifie dans la méthode train() de l'estimateur? La deuxième est comment utiliser les crochets d'entraînement pour des choses comme des évaluations périodiques, une sortie de perte tous les X pas, etc.? Les docs semblent dire d'utiliser des crochets d'entraînement, mais je ne semble pas trouver d'exemples concrets sur comment les utiliser.

Voici mon code:

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import time
import shutil
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt

from IPython import display
from tensorflow.examples.tutorials.mnist import input_data

data = input_data.read_data_sets('.')
display.clear_output()

def _model_fn(features, labels, mode=None, params=None):
    # define inputs
    image = tf.feature_column.numeric_column('images', shape=(784, ))
    inputs = tf.feature_column.input_layer(features, [image, ])
    # encoder
    e1 = tf.layers.dense(inputs, 512, activation=tf.nn.relu)
    e2 = tf.layers.dense(e1, 256, activation=tf.nn.relu)
    # decoder
    d1 = tf.layers.dense(e2, 512, activation=tf.nn.relu)
    model = tf.layers.dense(d1, 784, activation=tf.nn.relu)
    # training ops
    loss = tf.losses.mean_squared_error(labels, model)
    train = tf.train.AdamOptimizer().minimize(loss, global_step=tf.train.get_global_step())
    if mode == tf.estimator.ModeKeys.TRAIN:
        return tf.estimator.EstimatorSpec(mode=mode,
                                          loss=loss,
                                          train_op=train)

_train_input_fn = tf.estimator.inputs.numpy_input_fn({'images': data.train.images},
                                                     y=np.array(data.train.images),
                                                     batch_size=100,
                                                     shuffle=True)

shutil.rmtree("logs", ignore_errors=True)
tf.logging.set_verbosity(tf.logging.INFO)
estimator = tf.estimator.Estimator(_model_fn, 
                                   model_dir="logs", 
                                   config=tf.contrib.learn.RunConfig(save_checkpoints_steps=1000),
                                   params={})
estimator.train(_train_input_fn, steps=1000)

Et voici la sortie que j'obtiens (remarquez comment l'entraînement s'arrête à 550 étapes alors que le code appelle explicitement pour 1000)

INFO:tensorflow:Using config: {'_task_type': None, '_task_id': 0, '_cluster_spec': , '_master': '', '_num_ps_replicas': 0, '_num_worker_replicas': 0, '_environment': 'local', '_is_chief': True, '_evaluation_master': '', '_tf_config': gpu_options {
  per_process_gpu_memory_fraction: 1
}
, '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_secs': None, '_session_config': None, '_save_checkpoints_steps': 1000, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_model_dir': 'logs'}
INFO:tensorflow:Create CheckpointSaverHook.
INFO:tensorflow:Saving checkpoints for 1 into logs/model.ckpt.
INFO:tensorflow:loss = 0.102862, step = 1
INFO:tensorflow:global_step/sec: 41.8119
INFO:tensorflow:loss = 0.0191228, step = 101 (2.393 sec)
INFO:tensorflow:global_step/sec: 39.9923
INFO:tensorflow:loss = 0.0141014, step = 201 (2.500 sec)
INFO:tensorflow:global_step/sec: 40.9806
INFO:tensorflow:loss = 0.0116138, step = 301 (2.440 sec)
INFO:tensorflow:global_step/sec: 40.0043
INFO:tensorflow:loss = 0.00998991, step = 401 (2.500 sec)
INFO:tensorflow:global_step/sec: 39.2571
INFO:tensorflow:loss = 0.0124132, step = 501 (2.548 sec)
INFO:tensorflow:Saving checkpoints for 550 into logs/model.ckpt.
INFO:tensorflow:Loss for final step: 0.00940801.

Mise à jour #1 J'ai trouvé la réponse à la première question. La raison pour laquelle l'entraînement s'est arrêté à l'étape 550 était parce que numpy_input_fn() par défaut à num_epochs=1. Je cherche toujours de l'aide avec les crochets d'entraînement cependant.

0 votes

Pour une validation périodique, je choisirais ValidationMonitor pour le moment. Il est obsolète car il utilise une classe parente plus ancienne, donc vous pouvez recevoir des avertissements, mais il n'y a pas encore de remplacement basé sur SessionRunHook pour ValidationMonitor. N'hésitez pas à ajouter des emojis au bogue.

0 votes

Il semble que cela devrait être possible de créer une sous-classe de SessionRunHook et de lui faire exécuter des opérations que vous voulez à certaines étapes en copiant/collant du code de l'implémentation de la classe StepCounterHook. Je pense que je vais aller dans cette direction, mais je souhaite que les choses soient mieux documentées et je souhaite que les sous-classes existantes pour les hooks de session soient plus utiles.

0 votes

Oui, les choses pourraient certainement être améliorées. Si vous créez quelque chose que vous aimez, cela pourrait constituer une belle demande de tirage... vous voudrez peut-être ping @ispirmustafa pour coordonner.

2voto

Pratik Kumar Points 1400

L'estimateur peut être exécuté dans 3 modes.

  1. Formation
  2. évaluer
  3. prédire

Votre code actuel est configuré pour s'exécuter uniquement en mode d'entraînement. Si vous souhaitez inclure l'étape d'évaluation, vous devez apporter quelques modifications à la fonction modèle d'abord :

def _model_fn(features, labels, mode=None, params=None):
    # définir les entrées
    image = tf.feature_column.numeric_column('images', shape=(784, ))
    inputs = tf.feature_column.input_layer(features, [image, ])
    # encodeur
    e1 = tf.layers.dense(inputs, 512, activation=tf.nn.relu)
    e2 = tf.layers.dense(e1, 256, activation=tf.nn.relu)
    # décodeur
    d1 = tf.layers.dense(e2, 512, activation=tf.nn.relu)
    model = tf.layers.dense(d1, 784, activation=tf.nn.relu)
    # opérations d'entraînement
    loss = tf.losses.mean_squared_error(labels, model)
    train = tf.train.AdamOptimizer().minimize(loss, global_step=tf.train.get_global_step())
    if mode == tf.estimator.ModeKeys.TRAIN:
        return tf.estimator.EstimatorSpec(mode=mode,
                                          loss=loss,
                                          train_op=train)

    prec, prec_update_op = tf.metrics.precision(labels=labels,predictions=model), name='precision_op')
    recall, recall_update_op = tf.metrics.recall(labels=labels, predictions=model, name='recall_op')

    metrics={'recall':(recall, recall_update_op), \
               'precision':(prec, prec_update_op)}

    if mode==tf.estimator.ModeKeys.EVAL:
          return tf.estimator.EstimatorSpec(mode, loss=loss, eval_metric_ops=metrics)

Maintenant pour effectuer l'évaluation et afficher la sortie de la perte toutes les 10 étapes.

configuration = tf.estimator.RunConfig(
  model_dir = 'logs',
  keep_checkpoint_max=5,
  save_checkpoints_steps=1500,
  log_step_count_steps=10)  # définir la fréquence de journalisation des étapes pour la fonction de perte

estimator = tf.estimator.Estimator(model_fn = _model_fn, params = {}, config=configuration)

train_spec = tf.estimator.TrainSpec(input_fn=_train_input_fn, steps=5000) 
eval_spec = tf.estimator.EvalSpec(input_fn=_train_input_fn, steps=100, throttle_secs=600)

tf.estimator.train_and_evaluate(classifier, train_spec, eval_spec)

Remarque :

  1. après chaque nouveau point de contrôle enregistré (c'est-à-dire à chaque 1500 étapes), une évaluation est effectuée pendant 100 étapes, puis la formation reprend.
  2. Le log_step_count_steps affiche la sortie de la perte toutes les X étapes.
  3. L'argument throttle_secs définit le nombre minimum de secondes entre deux étapes d'évaluation consécutives. Si un nouveau point de contrôle est stocké avant ce nombre de secondes, alors l'évaluation est sautée.

Le code ci-dessus formera et évaluera sur le même jeu de données, si vous voulez le faire sur un jeu de données différent, passez sa fonctin d'entrée adaptée à l'argument input_fn à tf.estimator.EvalSpec

0voto

OGCheeze Points 39

Il semble que vous ayez parcouru toutes vos données en 550 étapes. Le paramètre par défaut 'num_epochs' de numpy_input_fn est de 1 donc vous ne pouvez exécuter vos données qu'une seule fois. https://www.tensorflow.org/api_docs/python/tf/estimator/inputs/numpy_input_fn

Par conséquent, vous devriez soit définir num_epochs sur None pour satisfaire vos étapes.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X