Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/es-419/guide/migrate/early_stopping.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.

En este bloc de notas se muestra cómo se puede preparar un modelo de entrenamiento con parada anticipada, en primer lugar, en TensorFlow 1 con tf.estimator.Estimator y un hook de parada anticipada, y después, en TensorFlow 2 con las APIs de Keras o un bucle de entrenamiento personalizado. La parada anticipada es una técnica de regularización que detiene el entrenamiento si, por ejemplo, la pérdida de validación alcanza un cierto umbral.

En TensorFlow 2, hay tres formas de implementar la parada anticipada:

  • Utilice una retrollamada integrada de Keras - tf.keras.callbacks.EarlyStopping - y transfiérala a Model.fit.

  • Defina una retrollamada personalizada y transfiérala a Keras Model.fit.

  • Escriba una regla de parada anticipada personalizada en un bucle de entrenamiento personalizado (con tf.GradientTape).

Preparación

import time import numpy as np import tensorflow as tf import tensorflow.compat.v1 as tf1 import tensorflow_datasets as tfds

TensorFlow 1: Parada anticipada con un hook de parada anticipada y tf.estimator

Comience definiendo las funciones para la carga y el preprocesamiento del conjunto de datos MNIST, y la definición del modelo que se utilizará con tf.estimator.Estimator:

def normalize_img(image, label): return tf.cast(image, tf.float32) / 255., label def _input_fn(): ds_train = tfds.load( name='mnist', split='train', shuffle_files=True, as_supervised=True) ds_train = ds_train.map( normalize_img, num_parallel_calls=tf.data.AUTOTUNE) ds_train = ds_train.batch(128) ds_train = ds_train.repeat(100) return ds_train def _eval_input_fn(): ds_test = tfds.load( name='mnist', split='test', shuffle_files=True, as_supervised=True) ds_test = ds_test.map( normalize_img, num_parallel_calls=tf.data.AUTOTUNE) ds_test = ds_test.batch(128) return ds_test def _model_fn(features, labels, mode): flatten = tf1.layers.Flatten()(features) features = tf1.layers.Dense(128, 'relu')(flatten) logits = tf1.layers.Dense(10)(features) loss = tf1.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits) optimizer = tf1.train.AdagradOptimizer(0.005) train_op = optimizer.minimize(loss, global_step=tf1.train.get_global_step()) return tf1.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op)

En TensorFlow 1, la parada anticipada funciona configurando un anzuelo de parada anticipada con tf.estimator.experimental.make_early_stopping_hook. El anzuelo se transfiere al método make_early_stopping_hook como parámetro para should_stop_fn, que puede aceptar una función sin argumentos. El entrenamiento se detiene una vez que should_stop_fn devuelve True.

En el siguiente ejemplo se muestra cómo implementar una técnica de parada anticipada que limita el tiempo de entrenamiento a un máximo de 20 segundos:

estimator = tf1.estimator.Estimator(model_fn=_model_fn) start_time = time.time() max_train_seconds = 20 def should_stop_fn(): return time.time() - start_time > max_train_seconds early_stopping_hook = tf1.estimator.experimental.make_early_stopping_hook( estimator=estimator, should_stop_fn=should_stop_fn, run_every_secs=1, run_every_steps=None) train_spec = tf1.estimator.TrainSpec( input_fn=_input_fn, hooks=[early_stopping_hook]) eval_spec = tf1.estimator.EvalSpec(input_fn=_eval_input_fn) tf1.estimator.train_and_evaluate(estimator, train_spec, eval_spec)

TensorFlow 2: Parada anticipada con una retrollamada incorporada y Model.fit

Prepare el conjunto de datos MNIST y un modelo Keras simple:

(ds_train, ds_test), ds_info = tfds.load( 'mnist', split=['train', 'test'], shuffle_files=True, as_supervised=True, with_info=True, ) ds_train = ds_train.map( normalize_img, num_parallel_calls=tf.data.AUTOTUNE) ds_train = ds_train.batch(128) ds_test = ds_test.map( normalize_img, num_parallel_calls=tf.data.AUTOTUNE) ds_test = ds_test.batch(128) model = tf.keras.models.Sequential([ tf.keras.layers.Flatten(input_shape=(28, 28)), tf.keras.layers.Dense(128, activation='relu'), tf.keras.layers.Dense(10) ]) model.compile( optimizer=tf.keras.optimizers.Adam(0.005), loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), metrics=[tf.keras.metrics.SparseCategoricalAccuracy()], )

En TensorFlow 2, cuando se utiliza la función incorporada de Keras Model.fit (o Model.evaluate), se puede configurar la parada anticipada transfiriendo una retrollamada incorporada -tf.keras.callbacks.EarlyStopping - al parámetro callbacks de Model.fit.

La retrollamada EarlyStopping monitoriza una métrica que especifica el usuario y finaliza el entrenamiento cuando deja de mejorar. (Consulte Entrenamiento y evaluación con los métodos incorporados o los Documentos de la API para obtener más información).

A continuación se muestra un ejemplo de una retrollamada de parada anticipada que monitoriza la pérdida y detiene el entrenamiento después de que el número de épocas que no muestran mejoras se establece en 3 ( patience):

callback = tf.keras.callbacks.EarlyStopping(monitor='loss', patience=3) # Only around 25 epochs are run during training, instead of 100. history = model.fit( ds_train, epochs=100, validation_data=ds_test, callbacks=[callback] ) len(history.history['loss'])

TensorFlow 2: Parada temprana con una retrollamada personalizada y Model.fit

También puede implementar una retrollamada personalizada de parada anticipada, que también puede transferirse al parámetro callbacks de Model.fit (o Model.evaluate).

En este ejemplo, el proceso de entrenamiento se detiene una vez que self.model.stop_training se establece en True:

class LimitTrainingTime(tf.keras.callbacks.Callback): def __init__(self, max_time_s): super().__init__() self.max_time_s = max_time_s self.start_time = None def on_train_begin(self, logs): self.start_time = time.time() def on_train_batch_end(self, batch, logs): now = time.time() if now - self.start_time > self.max_time_s: self.model.stop_training = True
# Limit the training time to 30 seconds. callback = LimitTrainingTime(30) history = model.fit( ds_train, epochs=100, validation_data=ds_test, callbacks=[callback] ) len(history.history['loss'])

TensorFlow 2: Parada anticipada con un bucle de entrenamiento personalizado

En TensorFlow 2, puede implementar la parada anticipada en un bucle de entrenamiento personalizado si no está entrenando y evaluando con los métodos de Keras incorporados.

Comience utilizando las APIs de Keras para definir otro modelo simple, un optimizador, una función de pérdida y métricas:

model = tf.keras.models.Sequential([ tf.keras.layers.Flatten(input_shape=(28, 28)), tf.keras.layers.Dense(128, activation='relu'), tf.keras.layers.Dense(10) ]) optimizer = tf.keras.optimizers.Adam(0.005) loss_fn = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True) train_acc_metric = tf.keras.metrics.SparseCategoricalAccuracy() train_loss_metric = tf.keras.metrics.SparseCategoricalCrossentropy() val_acc_metric = tf.keras.metrics.SparseCategoricalAccuracy() val_loss_metric = tf.keras.metrics.SparseCategoricalCrossentropy()

Defina las funciones de actualización de parámetros con tf.GradientTape y el decorador @tf.function para una aceleración:

@tf.function def train_step(x, y): with tf.GradientTape() as tape: logits = model(x, training=True) loss_value = loss_fn(y, logits) grads = tape.gradient(loss_value, model.trainable_weights) optimizer.apply_gradients(zip(grads, model.trainable_weights)) train_acc_metric.update_state(y, logits) train_loss_metric.update_state(y, logits) return loss_value @tf.function def test_step(x, y): logits = model(x, training=False) val_acc_metric.update_state(y, logits) val_loss_metric.update_state(y, logits)

A continuación, escriba un bucle de entrenamiento personalizado, en el que podrá implementar manualmente su regla de parada anticipada.

En el siguiente ejemplo se muestra cómo detener el entrenamiento cuando la pérdida de validación no mejora en un determinado número de épocas:

epochs = 100 patience = 5 wait = 0 best = float('inf') for epoch in range(epochs): print("\nStart of epoch %d" % (epoch,)) start_time = time.time() for step, (x_batch_train, y_batch_train) in enumerate(ds_train): loss_value = train_step(x_batch_train, y_batch_train) if step % 200 == 0: print("Training loss at step %d: %.4f" % (step, loss_value.numpy())) print("Seen so far: %s samples" % ((step + 1) * 128)) train_acc = train_acc_metric.result() train_loss = train_loss_metric.result() train_acc_metric.reset_states() train_loss_metric.reset_states() print("Training acc over epoch: %.4f" % (train_acc.numpy())) for x_batch_val, y_batch_val in ds_test: test_step(x_batch_val, y_batch_val) val_acc = val_acc_metric.result() val_loss = val_loss_metric.result() val_acc_metric.reset_states() val_loss_metric.reset_states() print("Validation acc: %.4f" % (float(val_acc),)) print("Time taken: %.2fs" % (time.time() - start_time)) # The early stopping strategy: stop the training if `val_loss` does not # decrease over a certain number of epochs. wait += 1 if val_loss < best: best = val_loss wait = 0 if wait >= patience: break

Siguientes pasos