TensorFlow 1.10+ estimador personalizado que se detiene pronto con train_and_evaluate

Supongamos que está entrenando un tf.estimator.Estimator personalizado con tf.estimator.train_and_evaluate utilizando un conjunto de datos de validación en una configuración similar a la de @ simlmx :

 classifier = tf.estimator.Estimator( model_fn=model_fn, model_dir=model_dir, params=params) train_spec = tf.estimator.TrainSpec( input_fn = training_data_input_fn, ) eval_spec = tf.estimator.EvalSpec( input_fn = validation_data_input_fn, ) tf.estimator.train_and_evaluate( classifier, train_spec, eval_spec ) 

A menudo, uno usa un conjunto de datos de validación para interrumpir el entrenamiento para evitar el ajuste excesivo cuando la pérdida continúa mejorando para el conjunto de datos de entrenamiento pero no para el conjunto de datos de validación.

Actualmente, tf.estimator.EvalSpec permite especificar después de cuántos steps (por defecto, 100) para evaluar el modelo.

¿Cómo puede uno (si es posible no usar tf.contrib funciones tf.contrib ) designar terminar el entrenamiento después de n número de llamadas de evaluación ( n * steps ) donde la pérdida de evaluación no mejora y luego guardar el “mejor” modelo / punto de control (determinado por el conjunto de datos de validación) ) a un nombre de archivo único (por ejemplo, best_validation.checkpoint )

Entiendo tu confusión ahora. La documentación para los estados de stop_if_no_decrease_hook (énfasis mío):

max_steps_without_decrease: int, número máximo de pasos de entrenamiento sin disminución en la métrica dada.

dir_ eval: Si está configurado, directorio que contiene archivos de resumen con métricas eval. Por defecto, se utilizará estimator.eval_dir ().

Mirando a través del código del gancho (versión 1.11) , sin embargo, encontrará:

 def stop_if_no_metric_improvement_fn(): """Returns `True` if metric does not improve within max steps.""" eval_results = read_eval_metrics(eval_dir) #<<<<<<<<<<<<<<<<<<<<<<< best_val = None best_val_step = None for step, metrics in eval_results.items(): #<<<<<<<<<<<<<<<<<<<<<<< if step < min_steps: continue val = metrics[metric_name] if best_val is None or is_lhs_better(val, best_val): best_val = val best_val_step = step if step - best_val_step >= max_steps_without_improvement: #<<<<< tf_logging.info( 'No %s in metric "%s" for %s steps, which is greater than or equal ' 'to max steps (%s) configured for early stopping.', increase_or_decrease, metric_name, step - best_val_step, max_steps_without_improvement) return True return False 

Lo que hace el código es cargar los resultados de la evaluación (producidos con los parámetros de EvalSpec ) y extraer los resultados de la evaluación y el paso global_step (o cualquier otro paso personalizado que utilice para contar) asociado con el registro de evaluación específico.

Esta es la fuente de los training steps forman parte de la documentación: la detención temprana no se activa de acuerdo con el número de evaluaciones que no mejoran, sino del número de evals que no mejoran en un cierto rango de pasos (que IMHO es un contador de bits). -intuitivo).

Entonces, para resumir: , el gancho de parada temprana utiliza los resultados de la evaluación para decidir cuándo es el momento de cortar la capacitación, pero debe pasar la cantidad de pasos de capacitación que desea monitorear y tener en cuenta cuántas evaluaciones se realizarán. en ese número de pasos.

Ejemplos con números para aclarar más con suerte.

Supongamos que está entrenando indefinidamente durante una evaluación cada 1k pasos. Los detalles de cómo se ejecuta la evaluación no son relevantes, siempre que se ejecuten cada 1k pasos que produzcan una métrica que queremos monitorear.

Si configura el gancho como hook = tf.contrib.estimator.stop_if_no_decrease_hook(my_estimator, 'my_metric_to_monitor', 10000) el gancho considerará que las evaluaciones suceden en un rango de 10k pasos.

Ya que estás ejecutando 1 evaluación cada 1k pasos, esto se reduce a una parada temprana si hay una secuencia de 10 evals consecutivos sin ninguna mejora. Si luego decide volver a ejecutar con evals cada 2k pasos, el gancho solo considerará una secuencia de 5 evals consecutivos sin mejorar.

Manteniendo el mejor modelo.

En primer lugar, una nota importante: esto no tiene nada que ver con la interrupción temprana , el problema de mantener una copia del mejor modelo a través de la capacitación y el de detener la capacitación una vez que el rendimiento comienza a degradarse no tienen relación alguna.

Mantener el mejor modelo se puede hacer muy fácilmente definiendo un tf.estimator.BestExporter en su EvalSpec (fragmento extraído del enlace):

  serving_input_receiver_fn = ... # define your serving_input_receiver_fn exporter = tf.estimator.BestExporter( name="best_exporter", serving_input_receiver_fn=serving_input_receiver_fn, exports_to_keep=5) # this will keep the 5 best checkpoints eval_spec = [tf.estimator.EvalSpec( input_fn=eval_input_fn, steps=100, exporters=exporter, start_delay_secs=0, throttle_secs=5)] 

Si no sabes cómo definir el serving_input_fn un vistazo aquí

Esto te permite mantener los mejores 5 modelos SavedModel que SavedModel , almacenados como SavedModel s (que es la forma preferida de almacenar modelos en este momento).