![]() | ![]() | ![]() | ![]() |
Configuración
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
Introducción
Esta guía cubre la formación, evaluación y predicción (inferencia) modelos cuando se utiliza una función de API para el entrenamiento y validación (como Model.fit()
, Model.evaluate()
y Model.predict()
).
Si usted está interesado en el aprovechamiento de fit()
especificando su propia función de paso de formación, consulte el Personalización de lo que sucede en el fit()
guía .
Si está interesado en escribir sus propios bucles de formación y de evaluación a partir de cero, consulte la guía de "escribir un bucle de formación a partir de cero" .
En general, ya sea que esté utilizando bucles integrados o escribiendo los suyos propios, el entrenamiento y la evaluación de modelos funcionan estrictamente de la misma manera en todos los tipos de modelos de Keras: modelos secuenciales, modelos creados con la API funcional y modelos escritos desde cero a través de subclasificación del modelo.
Esta guía no cubre la formación distribuida, que está cubierto en nuestra guía de multi-GPU y la formación distribuida .
Descripción general de la API: un primer ejemplo de extremo a extremo
Al pasar los datos a la incorporada en la formación de bucles de un modelo, debe utilizar matrices NumPy (si sus datos es pequeño y cabe en memoria) o tf.data Dataset
objetos. En los siguientes párrafos, usaremos el conjunto de datos MNIST como matrices NumPy para demostrar cómo usar optimizadores, pérdidas y métricas.
Consideremos el siguiente modelo (aquí, lo construimos con la API funcional, pero podría ser un modelo secuencial o un modelo de subclases también):
inputs = keras.Input(shape=(784,), name="digits")
x = layers.Dense(64, activation="relu", name="dense_1")(inputs)
x = layers.Dense(64, activation="relu", name="dense_2")(x)
outputs = layers.Dense(10, activation="softmax", name="predictions")(x)
model = keras.Model(inputs=inputs, outputs=outputs)
Así es como se ve el típico flujo de trabajo de un extremo a otro, que consta de:
- Capacitación
- Validación en un conjunto de reserva generado a partir de los datos de entrenamiento originales
- Evaluación de los datos de prueba
Usaremos datos MNIST para este ejemplo.
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
# Preprocess the data (these are NumPy arrays)
x_train = x_train.reshape(60000, 784).astype("float32") / 255
x_test = x_test.reshape(10000, 784).astype("float32") / 255
y_train = y_train.astype("float32")
y_test = y_test.astype("float32")
# Reserve 10,000 samples for validation
x_val = x_train[-10000:]
y_val = y_train[-10000:]
x_train = x_train[:-10000]
y_train = y_train[:-10000]
Especificamos la configuración de entrenamiento (optimizador, pérdida, métricas):
model.compile(
optimizer=keras.optimizers.RMSprop(), # Optimizer
# Loss function to minimize
loss=keras.losses.SparseCategoricalCrossentropy(),
# List of metrics to monitor
metrics=[keras.metrics.SparseCategoricalAccuracy()],
)
Hacemos un llamado fit()
, que formará el modelo por corte de los datos en "lotes" de tamaño batch_size
, y repetidamente interactuando sobre todo el conjunto de datos para un determinado número de epochs
.
print("Fit model on training data")
history = model.fit(
x_train,
y_train,
batch_size=64,
epochs=2,
# We pass some validation for
# monitoring validation loss and metrics
# at the end of each epoch
validation_data=(x_val, y_val),
)
Fit model on training data Epoch 1/2 782/782 [==============================] - 3s 3ms/step - loss: 0.3387 - sparse_categorical_accuracy: 0.9050 - val_loss: 0.1957 - val_sparse_categorical_accuracy: 0.9426 Epoch 2/2 782/782 [==============================] - 2s 3ms/step - loss: 0.1543 - sparse_categorical_accuracy: 0.9548 - val_loss: 0.1425 - val_sparse_categorical_accuracy: 0.9593
La regresado history
objeto contiene un registro de los valores de pérdida y los valores del indicador durante el entrenamiento:
history.history
{'loss': [0.3386789858341217, 0.1543138176202774], 'sparse_categorical_accuracy': [0.9050400257110596, 0.9548400044441223], 'val_loss': [0.19569723308086395, 0.14253544807434082], 'val_sparse_categorical_accuracy': [0.9426000118255615, 0.9592999815940857]}
Evaluamos el modelo de los datos de prueba a través de evaluate()
:
# Evaluate the model on the test data using `evaluate`
print("Evaluate on test data")
results = model.evaluate(x_test, y_test, batch_size=128)
print("test loss, test acc:", results)
# Generate predictions (probabilities -- the output of the last layer)
# on new data using `predict`
print("Generate predictions for 3 samples")
predictions = model.predict(x_test[:3])
print("predictions shape:", predictions.shape)
Evaluate on test data 79/79 [==============================] - 0s 2ms/step - loss: 0.1414 - sparse_categorical_accuracy: 0.9569 test loss, test acc: [0.14140386879444122, 0.9569000005722046] Generate predictions for 3 samples predictions shape: (3, 10)
Ahora, revisemos cada parte de este flujo de trabajo en detalle.
El compile()
método: especificar una pérdida, las métricas, y un optimizador
Para entrenar un modelo con fit()
, es necesario especificar una función de pérdida, un optimizador, y, opcionalmente, algunas métricas a monitor.
Se pasa éstos al modelo como argumentos para la compile()
método:
model.compile(
optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
loss=keras.losses.SparseCategoricalCrossentropy(),
metrics=[keras.metrics.SparseCategoricalAccuracy()],
)
El metrics
argumento debe ser una lista - su modelo puede tener cualquier número de métricas.
Si su modelo tiene múltiples salidas, puede especificar diferentes pérdidas y métricas para cada salida, y puede modular la contribución de cada salida a la pérdida total del modelo. Encontrará más detalles sobre esto en los datos que pasan a multi-entrada, sección de modelos múltiples salidas.
Tenga en cuenta que si está satisfecho con la configuración predeterminada, en muchos casos, el optimizador, la pérdida y las métricas se pueden especificar a través de identificadores de cadenas como acceso directo:
model.compile(
optimizer="rmsprop",
loss="sparse_categorical_crossentropy",
metrics=["sparse_categorical_accuracy"],
)
Para su reutilización posterior, pongamos la definición de nuestro modelo y compilemos el paso en funciones; los llamaremos varias veces a través de diferentes ejemplos en esta guía.
def get_uncompiled_model():
inputs = keras.Input(shape=(784,), name="digits")
x = layers.Dense(64, activation="relu", name="dense_1")(inputs)
x = layers.Dense(64, activation="relu", name="dense_2")(x)
outputs = layers.Dense(10, activation="softmax", name="predictions")(x)
model = keras.Model(inputs=inputs, outputs=outputs)
return model
def get_compiled_model():
model = get_uncompiled_model()
model.compile(
optimizer="rmsprop",
loss="sparse_categorical_crossentropy",
metrics=["sparse_categorical_accuracy"],
)
return model
Muchos optimizadores integrados, pérdidas y métricas están disponibles
En general, no tendrá que crear sus propias pérdidas, métricas u optimizadores desde cero, porque lo que necesita probablemente ya sea parte de la API de Keras:
Optimizadores:
-
SGD()
(con o sin impulso) -
RMSprop()
-
Adam()
- etc
Pérdidas:
-
MeanSquaredError()
-
KLDivergence()
-
CosineSimilarity()
- etc
Métrica:
-
AUC()
-
Precision()
-
Recall()
- etc
Pérdidas personalizadas
Si necesita crear una pérdida personalizada, Keras ofrece dos formas de hacerlo.
El primer método implica la creación de una función que acepta entradas y_true
y y_pred
. El siguiente ejemplo muestra una función de pérdida que calcula el error cuadrático medio entre los datos reales y las predicciones:
def custom_mean_squared_error(y_true, y_pred):
return tf.math.reduce_mean(tf.square(y_true - y_pred))
model = get_uncompiled_model()
model.compile(optimizer=keras.optimizers.Adam(), loss=custom_mean_squared_error)
# We need to one-hot encode the labels to use MSE
y_train_one_hot = tf.one_hot(y_train, depth=10)
model.fit(x_train, y_train_one_hot, batch_size=64, epochs=1)
782/782 [==============================] - 2s 2ms/step - loss: 0.0162 <keras.callbacks.History at 0x7ff8881ba250>
Si necesita una función de pérdida que se lleva en los parámetros lado y_true
y y_pred
, puede subclase el tf.keras.losses.Loss
clase y poner en práctica los dos métodos siguientes:
-
__init__(self)
: aceptar parámetros a pasar durante la llamada de la función de pérdida -
call(self, y_true, y_pred)
: utilizar los objetivos (y_true) y las predicciones del modelo (y_pred) para calcular la pérdida de la modelo
Supongamos que desea utilizar el error cuadrático medio, pero con un término agregado que desincentivará los valores de predicción lejos de 0,5 (asumimos que los objetivos categóricos están codificados en caliente y toman valores entre 0 y 1). Esto crea un incentivo para que el modelo no tenga demasiada confianza, lo que puede ayudar a reducir el sobreajuste (¡no sabremos si funciona hasta que lo intentemos!).
Así es como lo harías:
class CustomMSE(keras.losses.Loss):
def __init__(self, regularization_factor=0.1, name="custom_mse"):
super().__init__(name=name)
self.regularization_factor = regularization_factor
def call(self, y_true, y_pred):
mse = tf.math.reduce_mean(tf.square(y_true - y_pred))
reg = tf.math.reduce_mean(tf.square(0.5 - y_pred))
return mse + reg * self.regularization_factor
model = get_uncompiled_model()
model.compile(optimizer=keras.optimizers.Adam(), loss=CustomMSE())
y_train_one_hot = tf.one_hot(y_train, depth=10)
model.fit(x_train, y_train_one_hot, batch_size=64, epochs=1)
782/782 [==============================] - 2s 2ms/step - loss: 0.0388 <keras.callbacks.History at 0x7ff8882130d0>
Métricas personalizadas
Si necesita una métrica que no forma parte de la API, puede crear fácilmente métricas personalizadas subclasificando la tf.keras.metrics.Metric
clase. Deberá implementar 4 métodos:
-
__init__(self)
, en el que se va a crear variables de estado para su métrica. -
update_state(self, y_true, y_pred, sample_weight=None)
, que utiliza los objetivos y_true y las predicciones del modelo y_pred para actualizar las variables de estado. -
result(self)
, que utiliza las variables de estado para calcular los resultados finales. -
reset_state(self)
, que reinicializa el estado de la métrica.
Actualización de estado y los resultados de cálculo se mantienen separados (en update_state()
y el result()
, respectivamente) debido a que en algunos casos, el cálculo de los resultados puede ser muy costoso y sólo se llevaría a cabo de forma periódica.
He aquí un ejemplo simple que muestra cómo implementar un CategoricalTruePositives
métrica que cuenta cuántas muestras fueron correctamente clasificados como pertenecientes a una clase determinada:
class CategoricalTruePositives(keras.metrics.Metric):
def __init__(self, name="categorical_true_positives", **kwargs):
super(CategoricalTruePositives, self).__init__(name=name, **kwargs)
self.true_positives = self.add_weight(name="ctp", initializer="zeros")
def update_state(self, y_true, y_pred, sample_weight=None):
y_pred = tf.reshape(tf.argmax(y_pred, axis=1), shape=(-1, 1))
values = tf.cast(y_true, "int32") == tf.cast(y_pred, "int32")
values = tf.cast(values, "float32")
if sample_weight is not None:
sample_weight = tf.cast(sample_weight, "float32")
values = tf.multiply(values, sample_weight)
self.true_positives.assign_add(tf.reduce_sum(values))
def result(self):
return self.true_positives
def reset_state(self):
# The state of the metric will be reset at the start of each epoch.
self.true_positives.assign(0.0)
model = get_uncompiled_model()
model.compile(
optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
loss=keras.losses.SparseCategoricalCrossentropy(),
metrics=[CategoricalTruePositives()],
)
model.fit(x_train, y_train, batch_size=64, epochs=3)
Epoch 1/3 782/782 [==============================] - 2s 3ms/step - loss: 0.3404 - categorical_true_positives: 45217.0000 Epoch 2/3 782/782 [==============================] - 2s 3ms/step - loss: 0.1588 - categorical_true_positives: 47606.0000 Epoch 3/3 782/782 [==============================] - 2s 3ms/step - loss: 0.1168 - categorical_true_positives: 48278.0000 <keras.callbacks.History at 0x7ff8880a3610>
Manejo de pérdidas y métricas que no se ajustan a la firma estándar
La inmensa mayoría de las pérdidas y las métricas puede calcularse a partir y_true
y y_pred
, donde y_pred
es una salida de su modelo - pero no todos ellos. Por ejemplo, una pérdida de regularización puede requerir solo la activación de una capa (no hay objetivos en este caso), y esta activación puede no ser un resultado del modelo.
En tales casos, puede llamar self.add_loss(loss_value)
desde el interior del método llamado de una capa personalizada. Las pérdidas añadidas de esta manera se añaden a la pérdida de "principal" durante el entrenamiento (la aprobada para compile()
). Aquí hay un ejemplo simple que agrega regularización de actividad (tenga en cuenta que la regularización de actividad está incorporada en todas las capas de Keras; esta capa es solo para proporcionar un ejemplo concreto):
class ActivityRegularizationLayer(layers.Layer):
def call(self, inputs):
self.add_loss(tf.reduce_sum(inputs) * 0.1)
return inputs # Pass-through layer.
inputs = keras.Input(shape=(784,), name="digits")
x = layers.Dense(64, activation="relu", name="dense_1")(inputs)
# Insert activity regularization as a layer
x = ActivityRegularizationLayer()(x)
x = layers.Dense(64, activation="relu", name="dense_2")(x)
outputs = layers.Dense(10, name="predictions")(x)
model = keras.Model(inputs=inputs, outputs=outputs)
model.compile(
optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
)
# The displayed loss will be much higher than before
# due to the regularization component.
model.fit(x_train, y_train, batch_size=64, epochs=1)
782/782 [==============================] - 2s 2ms/step - loss: 2.4545 <keras.callbacks.History at 0x7ff87c53f310>
Puede hacer lo mismo para el registro de valores de indicadores, utilizando add_metric()
:
class MetricLoggingLayer(layers.Layer):
def call(self, inputs):
# The `aggregation` argument defines
# how to aggregate the per-batch values
# over each epoch:
# in this case we simply average them.
self.add_metric(
keras.backend.std(inputs), name="std_of_activation", aggregation="mean"
)
return inputs # Pass-through layer.
inputs = keras.Input(shape=(784,), name="digits")
x = layers.Dense(64, activation="relu", name="dense_1")(inputs)
# Insert std logging as a layer.
x = MetricLoggingLayer()(x)
x = layers.Dense(64, activation="relu", name="dense_2")(x)
outputs = layers.Dense(10, name="predictions")(x)
model = keras.Model(inputs=inputs, outputs=outputs)
model.compile(
optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
)
model.fit(x_train, y_train, batch_size=64, epochs=1)
782/782 [==============================] - 2s 2ms/step - loss: 0.3461 - std_of_activation: 0.9929 <keras.callbacks.History at 0x7ff87c3d5bd0>
En el API funcional , también puede llamar a model.add_loss(loss_tensor)
, o model.add_metric(metric_tensor, name, aggregation)
.
Aquí hay un ejemplo simple:
inputs = keras.Input(shape=(784,), name="digits")
x1 = layers.Dense(64, activation="relu", name="dense_1")(inputs)
x2 = layers.Dense(64, activation="relu", name="dense_2")(x1)
outputs = layers.Dense(10, name="predictions")(x2)
model = keras.Model(inputs=inputs, outputs=outputs)
model.add_loss(tf.reduce_sum(x1) * 0.1)
model.add_metric(keras.backend.std(x1), name="std_of_activation", aggregation="mean")
model.compile(
optimizer=keras.optimizers.RMSprop(1e-3),
loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
)
model.fit(x_train, y_train, batch_size=64, epochs=1)
782/782 [==============================] - 2s 3ms/step - loss: 2.4647 - std_of_activation: 0.0017 <keras.callbacks.History at 0x7ff87c216f90>
Tenga en cuenta que cuando se pasa a través de las pérdidas add_loss()
, se hace posible la llamada compile()
sin una función de pérdida, ya que el modelo ya tiene una pérdida de minimizar.
Consideremos el siguiente LogisticEndpoint
capa: toma como entradas objetivos y logits, y hace un seguimiento de una pérdida crossentropy través add_loss()
. También sigue la precisión de clasificación a través de add_metric()
.
class LogisticEndpoint(keras.layers.Layer):
def __init__(self, name=None):
super(LogisticEndpoint, self).__init__(name=name)
self.loss_fn = keras.losses.BinaryCrossentropy(from_logits=True)
self.accuracy_fn = keras.metrics.BinaryAccuracy()
def call(self, targets, logits, sample_weights=None):
# Compute the training-time loss value and add it
# to the layer using `self.add_loss()`.
loss = self.loss_fn(targets, logits, sample_weights)
self.add_loss(loss)
# Log accuracy as a metric and add it
# to the layer using `self.add_metric()`.
acc = self.accuracy_fn(targets, logits, sample_weights)
self.add_metric(acc, name="accuracy")
# Return the inference-time prediction tensor (for `.predict()`).
return tf.nn.softmax(logits)
Se puede utilizar en un modelo con dos entradas (datos de entrada y metas), compilado sin loss
argumento, como este:
import numpy as np
inputs = keras.Input(shape=(3,), name="inputs")
targets = keras.Input(shape=(10,), name="targets")
logits = keras.layers.Dense(10)(inputs)
predictions = LogisticEndpoint(name="predictions")(logits, targets)
model = keras.Model(inputs=[inputs, targets], outputs=predictions)
model.compile(optimizer="adam") # No loss argument!
data = {
"inputs": np.random.random((3, 3)),
"targets": np.random.random((3, 10)),
}
model.fit(data)
1/1 [==============================] - 0s 414ms/step - loss: 0.9889 - binary_accuracy: 0.0000e+00 <keras.callbacks.History at 0x7ff87c0848d0>
Para obtener más información sobre el entrenamiento de los modelos multi-entrada, consulte la sección de pasar datos a múltiples modelos de entrada, de salida múltiple.
Separación automática de un conjunto de exclusión de validación
En el primer ejemplo de extremo a extremo que viste, se utilizó el validation_data
argumento para pasar una tupla de matrices NumPy (x_val, y_val)
en el modelo para evaluar una pérdida de validación y las métricas de validación al final de cada época.
Aquí hay otra opción: el argumento validation_split
le permite automáticamente parte de reserva de sus datos de entrenamiento para su validación. El valor del argumento representa la fracción de los datos a ser reservados para la validación, por lo que se debe establecer en un número mayor que 0 y menor que 1. Por ejemplo, validation_split=0.2
medios de "uso 20% de los datos para la validación", y validation_split=0.6
medios de "uso 60% de los datos para la validación".
La forma en que se calcula la validación es a través de los últimos x% de las muestras de las matrices recibidos por el fit()
llamada, antes de cualquier arrastrando los pies.
Tenga en cuenta que sólo se puede utilizar validation_split
cuando el entrenamiento con los datos NumPy.
model = get_compiled_model()
model.fit(x_train, y_train, batch_size=64, validation_split=0.2, epochs=1)
625/625 [==============================] - 2s 3ms/step - loss: 0.3682 - sparse_categorical_accuracy: 0.8957 - val_loss: 0.2276 - val_sparse_categorical_accuracy: 0.9301 <keras.callbacks.History at 0x7ff81c680890>
Capacitación y evaluación de tf.data Datasets
En los últimos párrafos, que ha visto cómo manejar las pérdidas, métricas y optimizadores, y que ha visto cómo utilizar los validation_data
y validation_split
argumentos de fit()
, cuando los datos se pasa como matrices NumPy.
Ahora vamos a echar un vistazo al caso de que sus datos se presenta en forma de un tf.data.Dataset
objeto.
El tf.data
API es un conjunto de utilidades en TensorFlow 2.0 para la carga y los datos de preprocesamiento de un modo que es rápido y escalable.
Para una guía completa sobre la creación de Datasets
, consulte la documentación tf.data .
Puede pasar un Dataset
instancia directamente a los métodos fit()
, evaluate()
, y predict()
:
model = get_compiled_model()
# First, let's create a training Dataset instance.
# For the sake of our example, we'll use the same MNIST data as before.
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
# Shuffle and slice the dataset.
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)
# Now we get a test dataset.
test_dataset = tf.data.Dataset.from_tensor_slices((x_test, y_test))
test_dataset = test_dataset.batch(64)
# Since the dataset already takes care of batching,
# we don't pass a `batch_size` argument.
model.fit(train_dataset, epochs=3)
# You can also evaluate or predict on a dataset.
print("Evaluate")
result = model.evaluate(test_dataset)
dict(zip(model.metrics_names, result))
Epoch 1/3 782/782 [==============================] - 2s 3ms/step - loss: 0.3372 - sparse_categorical_accuracy: 0.9047 Epoch 2/3 782/782 [==============================] - 2s 3ms/step - loss: 0.1596 - sparse_categorical_accuracy: 0.9523 Epoch 3/3 782/782 [==============================] - 2s 3ms/step - loss: 0.1171 - sparse_categorical_accuracy: 0.9655 Evaluate 157/157 [==============================] - 0s 2ms/step - loss: 0.1211 - sparse_categorical_accuracy: 0.9648 {'loss': 0.12107347697019577, 'sparse_categorical_accuracy': 0.9648000001907349}
Tenga en cuenta que el conjunto de datos se restablece al final de cada época, por lo que se puede reutilizar en la próxima época.
Si desea ejecutar el entrenamiento sólo en un determinado número de lotes a partir de este conjunto de datos, se puede pasar el steps_per_epoch
argumento, que especifica el número de pasos de formación del modelo se debe ejecutar utilizando este conjunto de datos antes de pasar a la siguiente época.
Si hace esto, el conjunto de datos no se restablece al final de cada época, sino que seguimos dibujando los siguientes lotes. El conjunto de datos eventualmente se quedará sin datos (a menos que sea un conjunto de datos de bucle infinito).
model = get_compiled_model()
# Prepare the training dataset
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)
# Only use the 100 batches per epoch (that's 64 * 100 samples)
model.fit(train_dataset, epochs=3, steps_per_epoch=100)
Epoch 1/3 100/100 [==============================] - 1s 3ms/step - loss: 0.7937 - sparse_categorical_accuracy: 0.7894 Epoch 2/3 100/100 [==============================] - 0s 3ms/step - loss: 0.3699 - sparse_categorical_accuracy: 0.8938 Epoch 3/3 100/100 [==============================] - 0s 3ms/step - loss: 0.3155 - sparse_categorical_accuracy: 0.9061 <keras.callbacks.History at 0x7ff81c587e90>
Usar un conjunto de datos de validación
Puede pasar un Dataset
de instancia que el validation_data
argumento de fit()
:
model = get_compiled_model()
# Prepare the training dataset
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)
# Prepare the validation dataset
val_dataset = tf.data.Dataset.from_tensor_slices((x_val, y_val))
val_dataset = val_dataset.batch(64)
model.fit(train_dataset, epochs=1, validation_data=val_dataset)
782/782 [==============================] - 3s 3ms/step - loss: 0.3380 - sparse_categorical_accuracy: 0.9035 - val_loss: 0.2015 - val_sparse_categorical_accuracy: 0.9405 <keras.callbacks.History at 0x7ff81c30e450>
Al final de cada época, el modelo iterará sobre el conjunto de datos de validación y calculará la pérdida de validación y las métricas de validación.
Si desea ejecutar la validación sólo en un determinado número de lotes a partir de este conjunto de datos, se puede pasar el validation_steps
argumento, que especifica el número de pasos de validación del modelo se debe ejecutar con el conjunto de datos de validación antes de interrumpir la validación y de pasar a la siguiente época:
model = get_compiled_model()
# Prepare the training dataset
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)
# Prepare the validation dataset
val_dataset = tf.data.Dataset.from_tensor_slices((x_val, y_val))
val_dataset = val_dataset.batch(64)
model.fit(
train_dataset,
epochs=1,
# Only run validation using the first 10 batches of the dataset
# using the `validation_steps` argument
validation_data=val_dataset,
validation_steps=10,
)
782/782 [==============================] - 3s 3ms/step - loss: 0.3369 - sparse_categorical_accuracy: 0.9036 - val_loss: 0.2953 - val_sparse_categorical_accuracy: 0.9187 <keras.callbacks.History at 0x7ff81c30e310>
Tenga en cuenta que el conjunto de datos de validación se restablecerá después de cada uso (para que siempre esté evaluando las mismas muestras de una época a otra).
El argumento validation_split
(generación de un conjunto holdout de los datos de entrenamiento) no se admite cuando la formación de Dataset
de objetos, ya que esta característica requiere la capacidad de índice de las muestras de los conjuntos de datos, que no es posible en general con el Dataset
API.
Otros formatos de entrada compatibles
Además de las matrices, tensores NumPy ansiosos, y TensorFlow Datasets
, es posible entrenar un modelo Keras utilizando tramas de datos pandas, o de los generadores de Python que los lotes de rendimiento de datos y etiquetas.
En particular, los keras.utils.Sequence
ofertas de clase una interfaz sencilla para construir generadores de datos de Python que se multiprocesamiento-conscientes y pueden ser mezcladas.
En general, le recomendamos que utilice:
- Ingrese datos NumPy si sus datos son pequeños y caben en la memoria
-
Dataset
objetos si tiene grandes conjuntos de datos y que tiene que hacer la formación distribuida -
Sequence
objetos si tiene grandes conjuntos de datos y que tiene que hacer una gran cantidad de procesamiento del lado de Python personalizado que no se puede hacer en TensorFlow (por ejemplo, si se basan en las bibliotecas externas para la carga de datos o el procesamiento previo).
El uso de un keras.utils.Sequence
objeto como entrada
keras.utils.Sequence
es una utilidad que puede subclase para obtener un generador de Python con dos propiedades importantes:
- Funciona bien con multiprocesamiento.
- Se puede arrastrando los pies (por ejemplo, al pasar
shuffle=True
enfit()
).
Una Sequence
debe implementar dos métodos:
-
__getitem__
-
__len__
El método __getitem__
debe devolver un lote completo. Si desea modificar el conjunto de datos entre las épocas, es posible aplicar on_epoch_end
.
He aquí un ejemplo rápido:
from skimage.io import imread
from skimage.transform import resize
import numpy as np
# Here, `filenames` is list of path to the images
# and `labels` are the associated labels.
class CIFAR10Sequence(Sequence):
def __init__(self, filenames, labels, batch_size):
self.filenames, self.labels = filenames, labels
self.batch_size = batch_size
def __len__(self):
return int(np.ceil(len(self.filenames) / float(self.batch_size)))
def __getitem__(self, idx):
batch_x = self.filenames[idx * self.batch_size:(idx + 1) * self.batch_size]
batch_y = self.labels[idx * self.batch_size:(idx + 1) * self.batch_size]
return np.array([
resize(imread(filename), (200, 200))
for filename in batch_x]), np.array(batch_y)
sequence = CIFAR10Sequence(filenames, labels, batch_size)
model.fit(sequence, epochs=10)
Uso de ponderación de muestra y ponderación de clase
Con la configuración predeterminada, el peso de una muestra se decide por su frecuencia en el conjunto de datos. Existen dos métodos para ponderar los datos, independientemente de la frecuencia de muestreo:
- Pesos de clase
- Pesos de muestra
Pesos de clase
Esto se establece mediante el paso de un diccionario a la class_weight
argumento para Model.fit()
. Este diccionario asigna índices de clase al peso que debe usarse para las muestras que pertenecen a esta clase.
Esto se puede usar para equilibrar clases sin volver a muestrear, o para entrenar un modelo que le dé más importancia a una clase en particular.
Por ejemplo, si la clase "0" es la mitad de la clase representada como "1" en sus datos, puede utilizar Model.fit(..., class_weight={0: 1., 1: 0.5})
.
Aquí hay un ejemplo de NumPy donde usamos pesos de clase o pesos de muestra para dar más importancia a la clasificación correcta de la clase #5 (que es el dígito "5" en el conjunto de datos MNIST).
import numpy as np
class_weight = {
0: 1.0,
1: 1.0,
2: 1.0,
3: 1.0,
4: 1.0,
# Set weight "2" for class "5",
# making this class 2x more important
5: 2.0,
6: 1.0,
7: 1.0,
8: 1.0,
9: 1.0,
}
print("Fit with class weight")
model = get_compiled_model()
model.fit(x_train, y_train, class_weight=class_weight, batch_size=64, epochs=1)
Fit with class weight 782/782 [==============================] - 2s 3ms/step - loss: 0.3708 - sparse_categorical_accuracy: 0.9032 <keras.callbacks.History at 0x7ff80c7ddd10>
Pesos de muestra
Para un control detallado, o si no está creando un clasificador, puede usar "pesos de muestra".
- Cuando el entrenamiento de los datos NumPy: Pasar el
sample_weight
argumento paraModel.fit()
. - Cuando la formación de
tf.data
o cualquier otro tipo de iterador: Rendimiento(input_batch, label_batch, sample_weight_batch)
tuplas.
Una matriz de "pesos de muestra" es una matriz de números que especifican cuánto peso debe tener cada muestra en un lote para calcular la pérdida total. Se usa comúnmente en problemas de clasificación desequilibrada (la idea es dar más peso a las clases que rara vez se ven).
Cuando los pesos utilizados son unos y ceros, la matriz se puede utilizar como una máscara para la función de pérdida (descartando completamente la contribución de ciertas muestras a la pérdida total).
sample_weight = np.ones(shape=(len(y_train),))
sample_weight[y_train == 5] = 2.0
print("Fit with sample weight")
model = get_compiled_model()
model.fit(x_train, y_train, sample_weight=sample_weight, batch_size=64, epochs=1)
Fit with sample weight 782/782 [==============================] - 2s 3ms/step - loss: 0.3806 - sparse_categorical_accuracy: 0.9000 <keras.callbacks.History at 0x7ff80c650350>
He aquí un juego Dataset
ejemplo:
sample_weight = np.ones(shape=(len(y_train),))
sample_weight[y_train == 5] = 2.0
# Create a Dataset that includes sample weights
# (3rd element in the return tuple).
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train, sample_weight))
# Shuffle and slice the dataset.
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)
model = get_compiled_model()
model.fit(train_dataset, epochs=1)
782/782 [==============================] - 3s 3ms/step - loss: 0.3588 - sparse_categorical_accuracy: 0.9070 <keras.callbacks.History at 0x7ff80c51cb50>
Pasar datos a modelos de múltiples entradas y múltiples salidas
En los ejemplos anteriores, estábamos considerando un modelo con una sola entrada (un tensor de forma (764,)
) y una sola salida (un tensor predicción de forma (10,)
). Pero, ¿qué pasa con los modelos que tienen múltiples entradas o salidas?
Considere el siguiente modelo, que tiene una entrada de imagen de forma (32, 32, 3)
(que es (height, width, channels)
) y una entrada de serie de tiempo de forma (None, 10)
(que es (timesteps, features)
). Nuestro modelo tendrá dos salidas calculadas a partir de la combinación de estas entradas: una "puntuación" (de forma (1,)
) y una distribución de probabilidad sobre cinco clases (de forma (5,)
).
image_input = keras.Input(shape=(32, 32, 3), name="img_input")
timeseries_input = keras.Input(shape=(None, 10), name="ts_input")
x1 = layers.Conv2D(3, 3)(image_input)
x1 = layers.GlobalMaxPooling2D()(x1)
x2 = layers.Conv1D(3, 3)(timeseries_input)
x2 = layers.GlobalMaxPooling1D()(x2)
x = layers.concatenate([x1, x2])
score_output = layers.Dense(1, name="score_output")(x)
class_output = layers.Dense(5, name="class_output")(x)
model = keras.Model(
inputs=[image_input, timeseries_input], outputs=[score_output, class_output]
)
Grafiquemos este modelo, para que pueda ver claramente lo que estamos haciendo aquí (tenga en cuenta que las formas que se muestran en la gráfica son formas por lotes, en lugar de formas por muestra).
keras.utils.plot_model(model, "multi_input_and_output_model.png", show_shapes=True)
En el momento de la compilación, podemos especificar diferentes pérdidas para diferentes salidas, pasando las funciones de pérdida como una lista:
model.compile(
optimizer=keras.optimizers.RMSprop(1e-3),
loss=[keras.losses.MeanSquaredError(), keras.losses.CategoricalCrossentropy()],
)
Si solo pasáramos una sola función de pérdida al modelo, la misma función de pérdida se aplicaría a cada salida (lo que no es apropiado aquí).
Del mismo modo para las métricas:
model.compile(
optimizer=keras.optimizers.RMSprop(1e-3),
loss=[keras.losses.MeanSquaredError(), keras.losses.CategoricalCrossentropy()],
metrics=[
[
keras.metrics.MeanAbsolutePercentageError(),
keras.metrics.MeanAbsoluteError(),
],
[keras.metrics.CategoricalAccuracy()],
],
)
Dado que le dimos nombres a nuestras capas de salida, también podríamos especificar pérdidas y métricas por salida a través de un dictado:
model.compile(
optimizer=keras.optimizers.RMSprop(1e-3),
loss={
"score_output": keras.losses.MeanSquaredError(),
"class_output": keras.losses.CategoricalCrossentropy(),
},
metrics={
"score_output": [
keras.metrics.MeanAbsolutePercentageError(),
keras.metrics.MeanAbsoluteError(),
],
"class_output": [keras.metrics.CategoricalAccuracy()],
},
)
Recomendamos el uso de nombres y dictados explícitos si tiene más de 2 salidas.
Es posible dar diferentes pesos a diferentes pérdidas de producción específicos (por ejemplo, uno podría desear privilegiar la pérdida de "puntuación" en nuestro ejemplo, al dar a 2x la importancia de la pérdida de clases), utilizando el loss_weights
argumento:
model.compile(
optimizer=keras.optimizers.RMSprop(1e-3),
loss={
"score_output": keras.losses.MeanSquaredError(),
"class_output": keras.losses.CategoricalCrossentropy(),
},
metrics={
"score_output": [
keras.metrics.MeanAbsolutePercentageError(),
keras.metrics.MeanAbsoluteError(),
],
"class_output": [keras.metrics.CategoricalAccuracy()],
},
loss_weights={"score_output": 2.0, "class_output": 1.0},
)
También puede optar por no calcular una pérdida para ciertas salidas, si estas salidas están destinadas a la predicción pero no al entrenamiento:
# List loss version
model.compile(
optimizer=keras.optimizers.RMSprop(1e-3),
loss=[None, keras.losses.CategoricalCrossentropy()],
)
# Or dict loss version
model.compile(
optimizer=keras.optimizers.RMSprop(1e-3),
loss={"class_output": keras.losses.CategoricalCrossentropy()},
)
Pasar datos a un multi-entrada o modelo de múltiples salidas de fit()
funciona de una manera similar a la especificación de una función de pérdida de compilación: se puede pasar listas de matrices NumPy (con 1: 1 asignación a las salidas que recibieron una función de pérdida ) o dicts mapeo de nombres de salida de matrices NumPy.
model.compile(
optimizer=keras.optimizers.RMSprop(1e-3),
loss=[keras.losses.MeanSquaredError(), keras.losses.CategoricalCrossentropy()],
)
# Generate dummy NumPy data
img_data = np.random.random_sample(size=(100, 32, 32, 3))
ts_data = np.random.random_sample(size=(100, 20, 10))
score_targets = np.random.random_sample(size=(100, 1))
class_targets = np.random.random_sample(size=(100, 5))
# Fit on lists
model.fit([img_data, ts_data], [score_targets, class_targets], batch_size=32, epochs=1)
# Alternatively, fit on dicts
model.fit(
{"img_input": img_data, "ts_input": ts_data},
{"score_output": score_targets, "class_output": class_targets},
batch_size=32,
epochs=1,
)
4/4 [==============================] - 2s 9ms/step - loss: 5.6917 - score_output_loss: 0.1031 - class_output_loss: 5.5886 4/4 [==============================] - 0s 6ms/step - loss: 4.4108 - score_output_loss: 0.0999 - class_output_loss: 4.3109 <keras.callbacks.History at 0x7ff80c3b4110>
Aquí está el Dataset
de casos de uso: de manera similar a lo que hicimos para las matrices NumPy, el Dataset
debe devolver una tupla de dicts.
train_dataset = tf.data.Dataset.from_tensor_slices(
(
{"img_input": img_data, "ts_input": ts_data},
{"score_output": score_targets, "class_output": class_targets},
)
)
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)
model.fit(train_dataset, epochs=1)
2/2 [==============================] - 0s 21ms/step - loss: 4.2451 - score_output_loss: 0.0993 - class_output_loss: 4.1458 <keras.callbacks.History at 0x7ff80c3ed450>
Usar devoluciones de llamada
Las devoluciones de llamada en Keras son objetos que se llaman en diferentes puntos durante el entrenamiento (al comienzo de una época, al final de un lote, al final de una época, etc.). Se pueden usar para implementar ciertos comportamientos, como:
- Haciendo la validación en diferentes puntos durante el entrenamiento (más allá de la validación por época incorporada)
- Señalar el modelo a intervalos regulares o cuando exceda un cierto umbral de precisión
- Cambiar la tasa de aprendizaje del modelo cuando el entrenamiento parece estancarse
- Hacer un ajuste fino de las capas superiores cuando el entrenamiento parece estancarse
- Envío de notificaciones por correo electrónico o mensajes instantáneos cuando finaliza el entrenamiento o cuando se supera un cierto umbral de rendimiento
- Etc
Devoluciones de llamada se pueden pasar como una lista a su llamada a la fit()
:
model = get_compiled_model()
callbacks = [
keras.callbacks.EarlyStopping(
# Stop training when `val_loss` is no longer improving
monitor="val_loss",
# "no longer improving" being defined as "no better than 1e-2 less"
min_delta=1e-2,
# "no longer improving" being further defined as "for at least 2 epochs"
patience=2,
verbose=1,
)
]
model.fit(
x_train,
y_train,
epochs=20,
batch_size=64,
callbacks=callbacks,
validation_split=0.2,
)
Epoch 1/20 625/625 [==============================] - 2s 3ms/step - loss: 0.3725 - sparse_categorical_accuracy: 0.8939 - val_loss: 0.2314 - val_sparse_categorical_accuracy: 0.9321 Epoch 2/20 625/625 [==============================] - 2s 3ms/step - loss: 0.1805 - sparse_categorical_accuracy: 0.9471 - val_loss: 0.2012 - val_sparse_categorical_accuracy: 0.9379 Epoch 3/20 625/625 [==============================] - 2s 3ms/step - loss: 0.1346 - sparse_categorical_accuracy: 0.9603 - val_loss: 0.1651 - val_sparse_categorical_accuracy: 0.9505 Epoch 4/20 625/625 [==============================] - 2s 3ms/step - loss: 0.1065 - sparse_categorical_accuracy: 0.9684 - val_loss: 0.1510 - val_sparse_categorical_accuracy: 0.9571 Epoch 5/20 625/625 [==============================] - 2s 3ms/step - loss: 0.0884 - sparse_categorical_accuracy: 0.9734 - val_loss: 0.1505 - val_sparse_categorical_accuracy: 0.9538 Epoch 6/20 625/625 [==============================] - 2s 3ms/step - loss: 0.0746 - sparse_categorical_accuracy: 0.9778 - val_loss: 0.1508 - val_sparse_categorical_accuracy: 0.9575 Epoch 00006: early stopping <keras.callbacks.History at 0x7ff80c64cad0>
Muchas devoluciones de llamadas integradas están disponibles
Hay muchas devoluciones de llamada integradas que ya están disponibles en Keras, como:
-
ModelCheckpoint
: Periódicamente guardar el modelo. -
EarlyStopping
: la formación de detención cuando la formación ya no es mejorar las métricas de validación. -
TensorBoard
: troncos modelo periódicamente de escritura que se pueden visualizar en TensorBoard (más detalles en el "Visualización" sección). -
CSVLogger
: Secuencias de pérdida de datos y métricas en un archivo CSV. - etc
Consulte la documentación de las devoluciones de llamada para la lista completa.
Escribiendo su propia devolución de llamada
Puede crear una devolución de llamada personalizados mediante la extensión de la clase base keras.callbacks.Callback
. Una devolución de llamada tiene acceso a su modelo asociado a través de la propiedad de clase self.model
.
Asegúrese de leer la guía completa para escribir devoluciones de llamada personalizados .
Aquí hay un ejemplo simple que guarda una lista de valores de pérdida por lote durante el entrenamiento:
class LossHistory(keras.callbacks.Callback):
def on_train_begin(self, logs):
self.per_batch_losses = []
def on_batch_end(self, batch, logs):
self.per_batch_losses.append(logs.get("loss"))
Modelos de puntos de control
Cuando está entrenando un modelo en conjuntos de datos relativamente grandes, es fundamental guardar los puntos de control de su modelo a intervalos frecuentes.
La forma más sencilla de lograr esto es con el ModelCheckpoint
devolución de llamada:
model = get_compiled_model()
callbacks = [
keras.callbacks.ModelCheckpoint(
# Path where to save the model
# The two parameters below mean that we will overwrite
# the current checkpoint if and only if
# the `val_loss` score has improved.
# The saved model name will include the current epoch.
filepath="mymodel_{epoch}",
save_best_only=True, # Only save a model if `val_loss` has improved.
monitor="val_loss",
verbose=1,
)
]
model.fit(
x_train, y_train, epochs=2, batch_size=64, callbacks=callbacks, validation_split=0.2
)
Epoch 1/2 613/625 [============================>.] - ETA: 0s - loss: 0.3693 - sparse_categorical_accuracy: 0.8972 Epoch 00001: val_loss improved from inf to 0.23508, saving model to mymodel_1 2021-11-12 20:11:50.182298: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them. INFO:tensorflow:Assets written to: mymodel_1/assets 625/625 [==============================] - 3s 4ms/step - loss: 0.3660 - sparse_categorical_accuracy: 0.8979 - val_loss: 0.2351 - val_sparse_categorical_accuracy: 0.9273 Epoch 2/2 620/625 [============================>.] - ETA: 0s - loss: 0.1659 - sparse_categorical_accuracy: 0.9507 Epoch 00002: val_loss improved from 0.23508 to 0.16898, saving model to mymodel_2 INFO:tensorflow:Assets written to: mymodel_2/assets 625/625 [==============================] - 2s 3ms/step - loss: 0.1657 - sparse_categorical_accuracy: 0.9507 - val_loss: 0.1690 - val_sparse_categorical_accuracy: 0.9482 <keras.callbacks.History at 0x7ff8b577cc90>
El ModelCheckpoint
devolución de llamada se puede utilizar para poner en práctica la tolerancia a fallos: la capacidad de formación de reinicio desde el último estado guardado del modelo en el entrenamiento caso se interrumpe al azar. Aquí tienes un ejemplo básico:
import os
# Prepare a directory to store all the checkpoints.
checkpoint_dir = "./ckpt"
if not os.path.exists(checkpoint_dir):
os.makedirs(checkpoint_dir)
def make_or_restore_model():
# Either restore the latest model, or create a fresh one
# if there is no checkpoint available.
checkpoints = [checkpoint_dir + "/" + name for name in os.listdir(checkpoint_dir)]
if checkpoints:
latest_checkpoint = max(checkpoints, key=os.path.getctime)
print("Restoring from", latest_checkpoint)
return keras.models.load_model(latest_checkpoint)
print("Creating a new model")
return get_compiled_model()
model = make_or_restore_model()
callbacks = [
# This callback saves a SavedModel every 100 batches.
# We include the training loss in the saved model name.
keras.callbacks.ModelCheckpoint(
filepath=checkpoint_dir + "/ckpt-loss={loss:.2f}", save_freq=100
)
]
model.fit(x_train, y_train, epochs=1, callbacks=callbacks)
Creating a new model 88/1563 [>.............................] - ETA: 3s - loss: 1.1203 - sparse_categorical_accuracy: 0.6911INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=1.04/assets 185/1563 [==>...........................] - ETA: 6s - loss: 0.7768 - sparse_categorical_accuracy: 0.7858INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.75/assets 286/1563 [====>.........................] - ETA: 6s - loss: 0.6382 - sparse_categorical_accuracy: 0.8211INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.63/assets 383/1563 [======>.......................] - ETA: 6s - loss: 0.5584 - sparse_categorical_accuracy: 0.8433INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.55/assets 484/1563 [========>.....................] - ETA: 6s - loss: 0.5032 - sparse_categorical_accuracy: 0.8578INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.50/assets 586/1563 [==========>...................] - ETA: 5s - loss: 0.4644 - sparse_categorical_accuracy: 0.8684INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.46/assets 685/1563 [============>.................] - ETA: 5s - loss: 0.4356 - sparse_categorical_accuracy: 0.8762INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.43/assets 783/1563 [==============>...............] - ETA: 5s - loss: 0.4127 - sparse_categorical_accuracy: 0.8825INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.41/assets 883/1563 [===============>..............] - ETA: 4s - loss: 0.3958 - sparse_categorical_accuracy: 0.8868INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.39/assets 985/1563 [=================>............] - ETA: 3s - loss: 0.3766 - sparse_categorical_accuracy: 0.8918INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.38/assets 1086/1563 [===================>..........] - ETA: 3s - loss: 0.3624 - sparse_categorical_accuracy: 0.8958INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.36/assets 1184/1563 [=====================>........] - ETA: 2s - loss: 0.3498 - sparse_categorical_accuracy: 0.8994INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.35/assets 1283/1563 [=======================>......] - ETA: 1s - loss: 0.3383 - sparse_categorical_accuracy: 0.9029INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.34/assets 1386/1563 [=========================>....] - ETA: 1s - loss: 0.3265 - sparse_categorical_accuracy: 0.9058INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.33/assets 1485/1563 [===========================>..] - ETA: 0s - loss: 0.3184 - sparse_categorical_accuracy: 0.9081INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.32/assets 1563/1563 [==============================] - 11s 7ms/step - loss: 0.3122 - sparse_categorical_accuracy: 0.9097 <keras.callbacks.History at 0x7ff8b53e1dd0>
También llama a escribir su propia devolución de llamada para guardar y restaurar modelos.
Para una guía completa en la serialización y el ahorro, consulte la guía para el ahorro y la serialización de los modelos .
Usar programas de ritmo de aprendizaje
Un patrón común cuando se entrenan modelos de aprendizaje profundo es reducir gradualmente el aprendizaje a medida que avanza el entrenamiento. Esto se conoce generalmente como "disminución de la tasa de aprendizaje".
El calendario de decaimiento del aprendizaje puede ser estático (fijado de antemano, en función de la época actual o del índice de lote actual), o dinámico (en respuesta al comportamiento actual del modelo, en particular, la pérdida de validación).
Pasar un horario a un optimizador
Usted puede utilizar fácilmente un horario descomposición tasa de aprendizaje estática pasando un objeto horario que el learning_rate
argumento en su optimizador:
initial_learning_rate = 0.1
lr_schedule = keras.optimizers.schedules.ExponentialDecay(
initial_learning_rate, decay_steps=100000, decay_rate=0.96, staircase=True
)
optimizer = keras.optimizers.RMSprop(learning_rate=lr_schedule)
Varios programas internos están disponibles: ExponentialDecay
, PiecewiseConstantDecay
, PolynomialDecay
y InverseTimeDecay
.
Usar devoluciones de llamada para implementar un programa de ritmo de aprendizaje dinámico
No se puede lograr una programación de tasa de aprendizaje dinámica (por ejemplo, disminuir la tasa de aprendizaje cuando la pérdida de validación ya no mejora) con estos objetos de programación, ya que el optimizador no tiene acceso a las métricas de validación.
Sin embargo, las devoluciones de llamada tienen acceso a todas las métricas, ¡incluidas las métricas de validación! Por lo tanto, puede lograr este patrón utilizando una devolución de llamada que modifica la tasa de aprendizaje actual en el optimizador. De hecho, esto es aún incorporada como el ReduceLROnPlateau
de devolución de llamada.
Visualización de pérdidas y métricas durante el entrenamiento
La mejor manera de mantener un ojo en su modelo durante el entrenamiento es utilizar TensorBoard - una aplicación basada en navegador que se puede ejecutar de forma local que le proporciona:
- Gráficos en vivo de la pérdida y métricas para capacitación y evaluación.
- (opcionalmente) Visualizaciones de los histogramas de las activaciones de su capa
- (opcionalmente) y diseño 3D de los espacios de incrustación memorizada por el
Embedding
capas
Si ha instalado TensorFlow con pip, debería poder iniciar TensorBoard desde la línea de comandos:
tensorboard --logdir=/full_path_to_your_logs
Usar la devolución de llamada de TensorBoard
La forma más fácil de usar TensorBoard con un modelo Keras y el fit()
método es el TensorBoard
devolución de llamada.
En el caso más simple, simplemente especifique dónde desea que la devolución de llamada escriba los registros y estará listo para comenzar:
keras.callbacks.TensorBoard(
log_dir="/full_path_to_your_logs",
histogram_freq=0, # How often to log histogram visualizations
embeddings_freq=0, # How often to log embedding visualizations
update_freq="epoch",
) # How often to write logs (default: once per epoch)
<keras.callbacks.TensorBoard at 0x7ff88c8c04d0>
Para obtener más información, consulte la documentación de la TensorBoard
de devolución de llamada .