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.
0 votes
Tout d'abord, je vais essayer de mettre en place ma propre évaluation périodique et la poster comme réponse ici.
0 votes
@MadWombat As-tu réussi à le faire fonctionner? Si oui, pourrais-tu répondre à ta question avec tes résultats?
0 votes
@Maxime Non, je ne l'ai pas fait. Je vois quelques façons de le faire, mais le travail réel a pris le dessus. Je mettrai à jour une fois que j'aurai quelque chose qui fonctionne. De plus, il semble que le crochet par défaut "journaliser un message tous les 100 pas" soit codé en dur et ne puisse pas être supprimé ou modifié. C'est vraiment agaçant et j'ai l'intention de signaler un bug à TF.