Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/es-419/guide/keras/custom_callback.ipynb
25118 views
Kernel: Python 3
#@title Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.

Cómo escribir sus propias retrollamadas

Introducción

Una retrollamada es una poderosa herramienta que permite personalizar el comportamiento de un modelo Keras durante el entrenamiento, la evaluación o la inferencia. Los ejemplos incluyen tf.keras.callbacks.TensorBoard para visualizar el progreso del entrenamiento y los resultados con TensorBoard, o tf.keras.callbacks.ModelCheckpoint para guardar periódicamente su modelo durante el entrenamiento.

En esta guía, aprenderá qué es una retrollamada de Keras, qué puede hacer y cómo puede crear la suya propia. Le ofrecemos algunas demostraciones de aplicaciones de retrollamadas sencillas para que pueda familiarizarse con ellas.

Preparación

import tensorflow as tf from tensorflow import keras

Resumen de retrollamadas de Keras

Todas las retrollamadas subclasifican la clase keras.callbacks.Callback, y anulan un conjunto de métodos llamados en varias etapas del entrenamiento, la prueba y la predicción. Las retrollamadas son útiles para obtener una visión de los estados internos y las estadísticas del modelo durante el entrenamiento.

Puede transferir una lista de retrollamadas (como argumento de palabra clave callbacks) a los siguientes métodos del modelo:

  • keras.Model.fit()

  • keras.Model.evaluate()

  • keras.Model.predict()

Un resumen de los métodos de retrollamadas

Métodos globales

on_(train|test|predict)_begin(self, logs=None)

Se llama al principio de fit/evaluate/predict.

on_(train|test|predict)_end(self, logs=None)

Se llama al final de fit/evaluate/predict.

Métodos de entrenamiento, prueba y predicción por lotes

on_(train|test|predict)_batch_begin(self, batch, logs=None)

Se llama justo antes de procesar un lote durante el entrenamiento/prueba/predicción.

on_(train|test|predict)_batch_end(self, batch, logs=None)

Se llama al final del entrenamiento/prueba/predicción de un lote. Dentro de este método, logs es un dict que contiene los resultados de las métricas.

Métodos a nivel de época (solo para entrenamiento)

on_epoch_begin(self, epoch, logs=None)

Se llama al principio de una época durante el entrenamiento.

on_epoch_end(self, epoch, logs=None)

Se llama al final de una época durante el entrenamiento.

Un ejemplo básico

Veamos un ejemplo concreto. Para comenzar, vamos a importar tensorflow y definir un modelo Keras secuencial simple:

# Define el modelo de Keras sobre el que desea agregar retrollamadas def get_model(): model = keras.Sequential() model.add(keras.layers.Dense(1, input_dim=784)) model.compile( optimizer=keras.optimizers.RMSprop(learning_rate=0.1), loss="mean_squared_error", metrics=["mean_absolute_error"], ) return model

A continuación, suba los datos MNIST para el entrenamiento y las pruebas desde la API de los conjuntos de datos de Keras:

# Sube datos MNIST de ejemplo y preprocesarlos (x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data() x_train = x_train.reshape(-1, 784).astype("float32") / 255.0 x_test = x_test.reshape(-1, 784).astype("float32") / 255.0 # Limita los datos a 1,000 muestras x_train = x_train[:1000] y_train = y_train[:1000] x_test = x_test[:1000] y_test = y_test[:1000]

Ahora, defina una simple retrollamada personalizada que registre:

  • Cuándo fit/evaluate/predict comienza y termina

  • Cuándo comienza y termina cada época

  • Cuándo comienza y termina cada lote de entrenamiento

  • Cuándo comienza y termina cada lote de evaluación (prueba)

  • Cuándo comienza y termina cada lote de inferencia (predicción)

class CustomCallback(keras.callbacks.Callback): def on_train_begin(self, logs=None): keys = list(logs.keys()) print("Starting training; got log keys: {}".format(keys)) def on_train_end(self, logs=None): keys = list(logs.keys()) print("Stop training; got log keys: {}".format(keys)) def on_epoch_begin(self, epoch, logs=None): keys = list(logs.keys()) print("Start epoch {} of training; got log keys: {}".format(epoch, keys)) def on_epoch_end(self, epoch, logs=None): keys = list(logs.keys()) print("End epoch {} of training; got log keys: {}".format(epoch, keys)) def on_test_begin(self, logs=None): keys = list(logs.keys()) print("Start testing; got log keys: {}".format(keys)) def on_test_end(self, logs=None): keys = list(logs.keys()) print("Stop testing; got log keys: {}".format(keys)) def on_predict_begin(self, logs=None): keys = list(logs.keys()) print("Start predicting; got log keys: {}".format(keys)) def on_predict_end(self, logs=None): keys = list(logs.keys()) print("Stop predicting; got log keys: {}".format(keys)) def on_train_batch_begin(self, batch, logs=None): keys = list(logs.keys()) print("...Training: start of batch {}; got log keys: {}".format(batch, keys)) def on_train_batch_end(self, batch, logs=None): keys = list(logs.keys()) print("...Training: end of batch {}; got log keys: {}".format(batch, keys)) def on_test_batch_begin(self, batch, logs=None): keys = list(logs.keys()) print("...Evaluating: start of batch {}; got log keys: {}".format(batch, keys)) def on_test_batch_end(self, batch, logs=None): keys = list(logs.keys()) print("...Evaluating: end of batch {}; got log keys: {}".format(batch, keys)) def on_predict_batch_begin(self, batch, logs=None): keys = list(logs.keys()) print("...Predicting: start of batch {}; got log keys: {}".format(batch, keys)) def on_predict_batch_end(self, batch, logs=None): keys = list(logs.keys()) print("...Predicting: end of batch {}; got log keys: {}".format(batch, keys))

Vamos a probarlo:

model = get_model() model.fit( x_train, y_train, batch_size=128, epochs=1, verbose=0, validation_split=0.5, callbacks=[CustomCallback()], ) res = model.evaluate( x_test, y_test, batch_size=128, verbose=0, callbacks=[CustomCallback()] ) res = model.predict(x_test, batch_size=128, callbacks=[CustomCallback()])

Uso del dict logs

El dict logs contiene el valor de la pérdida, y todas las métricas al final de un lote o época. El ejemplo incluye la pérdida y el error promedio absoluto.

class LossAndErrorPrintingCallback(keras.callbacks.Callback): def on_train_batch_end(self, batch, logs=None): print( "Up to batch {}, the average loss is {:7.2f}.".format(batch, logs["loss"]) ) def on_test_batch_end(self, batch, logs=None): print( "Up to batch {}, the average loss is {:7.2f}.".format(batch, logs["loss"]) ) def on_epoch_end(self, epoch, logs=None): print( "The average loss for epoch {} is {:7.2f} " "and mean absolute error is {:7.2f}.".format( epoch, logs["loss"], logs["mean_absolute_error"] ) ) model = get_model() model.fit( x_train, y_train, batch_size=128, epochs=2, verbose=0, callbacks=[LossAndErrorPrintingCallback()], ) res = model.evaluate( x_test, y_test, batch_size=128, verbose=0, callbacks=[LossAndErrorPrintingCallback()], )

Uso del atributo self.model

Además de recibir información de registro cuando se llama a uno de sus métodos, las retrollamadas tienen acceso al modelo asociado con la ronda actual de entrenamiento/evaluación/inferencia: self.model.

Estas son algunas de las cosas que puede hacer con self.model en una retrollamada:

  • Establece self.model.stop_training = True para interrumpir inmediatamente el entrenamiento.

  • Mute los hiperparámetros del optimizador (disponible como self.model.optimizer), como self.model.optimizer.learning_rate.

  • Guarde el modelo en intervalos periódicos.

  • Registre la salida de model.predict() sobre algunas muestras de la prueba al final de cada época, para utilizarla como una verificación de sensatez durante el entrenamiento.

  • Extraer visualizaciones de características intermedias al final de cada época, para controlar lo que el modelo está aprendiendo con el tiempo.

  • etc.

Vamos a ver esto en acción en un par de ejemplos.

Ejemplos de aplicaciones de retrollamadas de Keras

Parada anticipada con pérdidas mínimas

Este primer ejemplo muestra cómo se crea una Callback que detiene el entrenamiento cuando se alcanza el mínimo de pérdida, mediante el atributo self.model.stop_training (booleano). De forma opcional, se puede proporcionar un argumento patience para especificar cuántas épocas debemos esperar antes de detenernos después de haber alcanzado un mínimo local.

tf.keras.callbacks.EarlyStopping proporciona una implementación más completa y general.

import numpy as np class EarlyStoppingAtMinLoss(keras.callbacks.Callback): """Stop training when the loss is at its min, i.e. the loss stops decreasing. Arguments: patience: Number of epochs to wait after min has been hit. After this number of no improvement, training stops. """ def __init__(self, patience=0): super(EarlyStoppingAtMinLoss, self).__init__() self.patience = patience # best_weights para almacenar las ponderaciones en las que se produce la pérdida mínima. self.best_weights = None def on_train_begin(self, logs=None): # El número de épocas que esperó cuando la pérdida dejó de ser mínima. self.wait = 0 # La época en que se detiene el entrenamiento. self.stopped_epoch = 0 # Inicializa the best como infinity. self.best = np.Inf def on_epoch_end(self, epoch, logs=None): current = logs.get("loss") if np.less(current, self.best): self.best = current self.wait = 0 # Registra las mejores ponderaciones si los resultados actuales son mejores (menos). self.best_weights = self.model.get_weights() else: self.wait += 1 if self.wait >= self.patience: self.stopped_epoch = epoch self.model.stop_training = True print("Restoring model weights from the end of the best epoch.") self.model.set_weights(self.best_weights) def on_train_end(self, logs=None): if self.stopped_epoch > 0: print("Epoch %05d: early stopping" % (self.stopped_epoch + 1)) model = get_model() model.fit( x_train, y_train, batch_size=64, steps_per_epoch=5, epochs=30, verbose=0, callbacks=[LossAndErrorPrintingCallback(), EarlyStoppingAtMinLoss()], )

Programación de la tasa de aprendizaje

En este ejemplo, se muestra cómo se puede utilizar una retrollamada personalizada para cambiar dinámicamente la tasa de aprendizaje del optimizador durante el transcurso del entrenamiento.

Consulte callbacks.LearningRateScheduler para obtener una implementación más general.

class CustomLearningRateScheduler(keras.callbacks.Callback): """Learning rate scheduler which sets the learning rate according to schedule. Arguments: schedule: a function that takes an epoch index (integer, indexed from 0) and current learning rate as inputs and returns a new learning rate as output (float). """ def __init__(self, schedule): super(CustomLearningRateScheduler, self).__init__() self.schedule = schedule def on_epoch_begin(self, epoch, logs=None): if not hasattr(self.model.optimizer, "lr"): raise ValueError('Optimizer must have a "lr" attribute.') # Obtiene la tasa de aprendizaje actual del optimizador del modelo. lr = float(tf.keras.backend.get_value(self.model.optimizer.learning_rate)) # Llame a la función de programación para obtener la tasa de aprendizaje programada. scheduled_lr = self.schedule(epoch, lr) # Devuelva el valor al optimizador antes de que comience esta época tf.keras.backend.set_value(self.model.optimizer.lr, scheduled_lr) print("\nEpoch %05d: Learning rate is %6.4f." % (epoch, scheduled_lr)) LR_SCHEDULE = [ # (epoch to start, learning rate) tuples (3, 0.05), (6, 0.01), (9, 0.005), (12, 0.001), ] def lr_schedule(epoch, lr): """Helper function to retrieve the scheduled learning rate based on epoch.""" if epoch < LR_SCHEDULE[0][0] or epoch > LR_SCHEDULE[-1][0]: return lr for i in range(len(LR_SCHEDULE)): if epoch == LR_SCHEDULE[i][0]: return LR_SCHEDULE[i][1] return lr model = get_model() model.fit( x_train, y_train, batch_size=64, steps_per_epoch=5, epochs=15, verbose=0, callbacks=[ LossAndErrorPrintingCallback(), CustomLearningRateScheduler(lr_schedule), ], )

Retrollamadas de Keras integradas

Asegúrese de revisar las retrollamadas actuales de Keras leyendo la API docs. Las aplicaciones incluyen el registro en CSV, guardar el modelo, visualizar métricas en TensorBoard, ¡y mucho más!