![]() | ![]() | ![]() | ![]() |
Installer
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
introduction
Ce guide couvre les modèles de formation, d'évaluation et de prédiction (inférence) lors de l'utilisation d'API intégrées pour la formation et la validation (telles que model.fit()
, model.evaluate()
, model.predict()
).
Si vous souhaitez tirer parti de fit()
tout en spécifiant votre propre fonction d'étape d'entraînement, consultez le guide «Personnalisation de ce qui se passe dans fit()
» .
Si vous souhaitez rédiger vos propres boucles de formation et d'évaluation à partir de zéro, consultez le guide «Écrire une boucle de formation à partir de zéro» .
En général, que vous utilisiez des boucles intégrées ou que vous écriviez les vôtres, la formation et l'évaluation des modèles fonctionnent strictement de la même manière pour tous les types de modèles Keras - modèles séquentiels, modèles construits avec l'API fonctionnelle et modèles écrits à partir de zéro via sous-classement du modèle.
Ce guide ne couvre pas la formation distribuée. Pour la formation distribuée, consultez notre guide sur la formation multi-gpu et distribuée .
Présentation de l'API: un premier exemple de bout en bout
Lorsque vous transmettez des données aux boucles d'apprentissage intégrées d'un modèle, vous devez utiliser des tableaux NumPy (si vos données sont petites et tf.data Dataset
en mémoire) ou des objets tf.data Dataset
. Dans les prochains paragraphes, nous utiliserons l'ensemble de données MNIST en tant que tableaux NumPy, afin de montrer comment utiliser les optimiseurs, les pertes et les métriques.
Considérons le modèle suivant (ici, nous construisons avec l'API fonctionnelle, mais cela peut également être un modèle séquentiel ou un modèle sous-classé):
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)
Voici à quoi ressemble le flux de travail typique de bout en bout, composé de:
- Formation
- Validation sur un jeu d'exclusion généré à partir des données d'entraînement d'origine
- Évaluation sur les données de test
Nous utiliserons les données MNIST pour cet exemple.
(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]
Nous spécifions la configuration de la formation (optimiseur, perte, métriques):
model.compile(
optimizer=keras.optimizers.RMSprop(), # Optimizer
# Loss function to minimize
loss=keras.losses.SparseCategoricalCrossentropy(),
# List of metrics to monitor
metrics=[keras.metrics.SparseCategoricalAccuracy()],
)
Nous appelons fit()
, qui entraînera le modèle en découpant les données en "lots" de taille "batch_size", et en effectuant des itérations répétées sur l'ensemble de données pour un nombre donné "d'époques".
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.5821 - sparse_categorical_accuracy: 0.8361 - val_loss: 0.1893 - val_sparse_categorical_accuracy: 0.9483 Epoch 2/2 782/782 [==============================] - 2s 3ms/step - loss: 0.1676 - sparse_categorical_accuracy: 0.9500 - val_loss: 0.1631 - val_sparse_categorical_accuracy: 0.9488
L'objet "history" renvoyé contient un enregistrement des valeurs de perte et des valeurs de métrique pendant l'entraînement:
history.history
{'loss': [0.344687819480896, 0.15941613912582397], 'sparse_categorical_accuracy': [0.9019200205802917, 0.9523000121116638], 'val_loss': [0.1892719268798828, 0.1630939543247223], 'val_sparse_categorical_accuracy': [0.9483000040054321, 0.9488000273704529]}
Nous évaluons le modèle sur les données de test via 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.1750 - sparse_categorical_accuracy: 0.9460 test loss, test acc: [0.17500483989715576, 0.9459999799728394] Generate predictions for 3 samples predictions shape: (3, 10)
Passons maintenant en revue chaque élément de ce flux de travail en détail.
La méthode compile()
: spécifier une perte, des métriques et un optimiseur
Pour entraîner un modèle avec fit()
, vous devez spécifier une fonction de perte, un optimiseur et, éventuellement, des métriques à surveiller.
Vous les transmettez au modèle en tant qu'arguments de la méthode compile()
:
model.compile(
optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
loss=keras.losses.SparseCategoricalCrossentropy(),
metrics=[keras.metrics.SparseCategoricalAccuracy()],
)
L'argument de metrics
doit être une liste - votre modèle peut avoir n'importe quel nombre de métriques.
Si votre modèle a plusieurs sorties, vous pouvez spécifier différentes pertes et métriques pour chaque sortie, et vous pouvez moduler la contribution de chaque sortie à la perte totale du modèle. Vous trouverez plus de détails à ce sujet dans la section "Transmission de données aux modèles multi-entrées et multi-sorties" .
Notez que si vous êtes satisfait des paramètres par défaut, dans de nombreux cas, l'optimiseur, la perte et les mesures peuvent être spécifiés via des identificateurs de chaîne comme raccourci:
model.compile(
optimizer="rmsprop",
loss="sparse_categorical_crossentropy",
metrics=["sparse_categorical_accuracy"],
)
Pour une réutilisation ultérieure, mettons notre définition de modèle et notre étape de compilation dans les fonctions; nous les appellerons plusieurs fois à travers différents exemples de ce guide.
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
De nombreux optimiseurs, pertes et métriques intégrés sont disponibles
En général, vous n'aurez pas à créer à partir de zéro vos propres pertes, métriques ou optimiseurs, car ce dont vous avez besoin fait probablement déjà partie de l'API Keras:
Optimiseurs:
-
SGD()
(avec ou sans momentum) -
RMSprop()
-
Adam()
- etc.
Pertes:
-
MeanSquaredError()
-
KLDivergence()
-
CosineSimilarity()
- etc.
Métrique:
-
AUC()
-
Precision()
-
Recall()
- etc.
Pertes personnalisées
Il existe deux façons de fournir des pertes personnalisées avec Keras. Le premier exemple crée une fonction qui accepte les entrées y_true
et y_pred
. L'exemple suivant montre une fonction de perte qui calcule l'erreur quadratique moyenne entre les données réelles et les prédictions:
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.0265 <tensorflow.python.keras.callbacks.History at 0x7fb27c7a6cf8>
Si vous avez besoin d'une fonction de perte qui prend des paramètres à côté de y_true
et y_pred
, vous pouvez sous- tf.keras.losses.Loss
classe tf.keras.losses.Loss
et implémenter les deux méthodes suivantes:
-
__init__(self)
: acceptez les paramètres à passer lors de l'appel de votre fonction de perte -
call(self, y_true, y_pred)
: utilisez les cibles (y_true) et les prédictions du modèle (y_pred) pour calculer la perte du modèle
Supposons que vous souhaitiez utiliser l'erreur quadratique moyenne, mais avec un terme supplémentaire qui découragera les valeurs de prédiction loin de 0,5 (nous supposons que les cibles catégorielles sont encodées à chaud et prennent des valeurs comprises entre 0 et 1). Cela incite le modèle à ne pas être trop confiant, ce qui peut aider à réduire le surajustement (nous ne saurons pas si cela fonctionne avant d'essayer!).
Voici comment procéder:
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.0485 <tensorflow.python.keras.callbacks.History at 0x7fb27c64d438>
Métriques personnalisées
Si vous avez besoin d'une métrique qui ne fait pas partie de l'API, vous pouvez facilement créer des métriques personnalisées en sous- tf.keras.metrics.Metric
classe tf.keras.metrics.Metric
. Vous devrez implémenter 4 méthodes:
-
__init__(self)
, dans lequel vous allez créer des variables d'état pour votre métrique. -
update_state(self, y_true, y_pred, sample_weight=None)
, qui utilise les cibles y_true et les prédictions du modèle y_pred pour mettre à jour les variables d'état. -
result(self)
, qui utilise les variables d'état pour calculer les résultats finaux. -
reset_states(self)
, qui réinitialise l'état de la métrique.
La mise à jour de l'état et le calcul des résultats sont séparés (dans update_state()
et result()
, respectivement) car dans certains cas, le calcul des résultats peut être très coûteux et ne serait effectué que périodiquement.
Voici un exemple simple montrant comment implémenter une métrique CategoricalTruePositives
, qui compte le nombre d'échantillons correctement classés comme appartenant à une classe donnée:
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_states(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 [==============================] - 3s 2ms/step - loss: 0.5801 - categorical_true_positives: 22009.8493 Epoch 2/3 782/782 [==============================] - 2s 2ms/step - loss: 0.1717 - categorical_true_positives: 23861.7190 Epoch 3/3 782/782 [==============================] - 2s 2ms/step - loss: 0.1200 - categorical_true_positives: 24233.9246 <tensorflow.python.keras.callbacks.History at 0x7fb27c56f2e8>
Gestion des pertes et des métriques qui ne correspondent pas à la signature standard
L'écrasante majorité des pertes et des métriques peut être calculée à partir de y_true
et y_pred
, où y_pred
est une sortie de votre modèle. Mais pas tous. Par exemple, une perte de régularisation peut nécessiter uniquement l'activation d'une couche (il n'y a pas de cibles dans ce cas), et cette activation peut ne pas être une sortie de modèle.
Dans de tels cas, vous pouvez appeler self.add_loss(loss_value)
depuis la méthode d'appel d'une couche personnalisée. Les pertes ajoutées de cette manière sont ajoutées à la perte "principale" pendant l'entraînement (celle passée à compile()
). Voici un exemple simple qui ajoute la régularisation des activités (notez que la régularisation des activités est intégrée dans toutes les couches Keras - cette couche est juste pour donner un exemple concret):
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: 3.2794 <tensorflow.python.keras.callbacks.History at 0x7fb27c4ea3c8>
Vous pouvez faire de même pour la journalisation des valeurs de métrique, en utilisant 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.5627 - std_of_activation: 0.9609 <tensorflow.python.keras.callbacks.History at 0x7fb27c39e320>
Dans l' API fonctionnelle , vous pouvez également appeler model.add_loss(loss_tensor)
ou model.add_metric(metric_tensor, name, aggregation)
.
Voici un exemple 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 2ms/step - loss: 3.6785 - std_of_activation: 0.0020 <tensorflow.python.keras.callbacks.History at 0x7fb27c2b4860>
Notez que lorsque vous passez des pertes via add_loss()
, il devient possible d'appeler compile()
sans fonction de perte, puisque le modèle a déjà une perte à minimiser.
Considérez la couche LogisticEndpoint
suivante: elle prend comme entrées des cibles et des logits, et elle suit une perte de add_loss()
via add_loss()
. Il suit également la précision de la classification via 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)
Vous pouvez l'utiliser dans un modèle avec deux entrées (données d'entrée et cibles), compilé sans argument de loss
, comme ceci:
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 260ms/step - loss: 1.0546 - binary_accuracy: 0.0000e+00 <tensorflow.python.keras.callbacks.History at 0x7fb27c09cc88>
Pour plus d'informations sur la formation de modèles à entrées multiples, reportez-vous à la section Transmission de données à des modèles à entrées et sorties multiples .
Mise à part automatique d'un jeu d'exclusion de validation
Dans le premier exemple de bout en bout que vous avez vu, nous avons utilisé l'argument validation_data
pour transmettre un tuple de tableaux NumPy (x_val, y_val)
au modèle pour évaluer une perte de validation et des métriques de validation à la fin de chaque époque.
Voici une autre option: l'argument validation_split
vous permet de réserver automatiquement une partie de vos données d'entraînement pour validation. La valeur de l'argument représente la fraction des données à réserver pour la validation, elle doit donc être définie sur un nombre supérieur à 0 et inférieur à 1. Par exemple, validation_split=0.2
signifie "utiliser 20% des données pour la validation", et validation_split=0.6
signifie "utiliser 60% des données pour la validation".
La façon dont la validation est calculée est de prendre les derniers échantillons x% des tableaux reçus par l'appel d'ajustement, avant tout brassage.
Notez que vous ne pouvez utiliser validation_split
lors de l'entraînement avec des données 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.6332 - sparse_categorical_accuracy: 0.8232 - val_loss: 0.2352 - val_sparse_categorical_accuracy: 0.9284 <tensorflow.python.keras.callbacks.History at 0x7fb27014f0f0>
Formation et évaluation à partir des ensembles de données tf.data
Dans les derniers paragraphes, vous avez vu comment gérer les pertes, les métriques et les optimiseurs, et vous avez vu comment utiliser les arguments validation_data
et validation_split
en forme, lorsque vos données sont transmises sous forme de tableaux NumPy.
Examinons maintenant le cas où vos données se présentent sous la forme d'un objettf.data.Dataset
.
L'API tf.data
est un ensemble d'utilitaires dans TensorFlow 2.0 pour charger et prétraiter les données de manière rapide et évolutive.
Pour obtenir un guide complet sur la création de Datasets
, consultez la documentation tf.data .
Vous pouvez passer une instance de Dataset
directement aux méthodes fit()
, evaluate()
et 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.5405 - sparse_categorical_accuracy: 0.8524 Epoch 2/3 782/782 [==============================] - 2s 3ms/step - loss: 0.1624 - sparse_categorical_accuracy: 0.9517 Epoch 3/3 782/782 [==============================] - 2s 3ms/step - loss: 0.1150 - sparse_categorical_accuracy: 0.9660 Evaluate 157/157 [==============================] - 0s 2ms/step - loss: 0.1337 - sparse_categorical_accuracy: 0.9583 {'loss': 0.13374954462051392, 'sparse_categorical_accuracy': 0.958299994468689}
Notez que l'ensemble de données est réinitialisé à la fin de chaque époque, de sorte qu'il peut être réutilisé à l'époque suivante.
Si vous souhaitez exécuter l'entraînement uniquement sur un nombre spécifique de lots de cet ensemble de données, vous pouvez transmettre l'argument steps_per_epoch
, qui spécifie le nombre d'étapes d'entraînement que le modèle doit exécuter à l'aide de cet ensemble de données avant de passer à l'époque suivante.
Si vous faites cela, le jeu de données n'est pas réinitialisé à la fin de chaque époque, au lieu de cela, nous continuons simplement à dessiner les lots suivants. L'ensemble de données finira par manquer de données (à moins qu'il ne s'agisse d'un ensemble de données en boucle infinie).
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: 1.2317 - sparse_categorical_accuracy: 0.6776 Epoch 2/3 100/100 [==============================] - 0s 2ms/step - loss: 0.3834 - sparse_categorical_accuracy: 0.8949 Epoch 3/3 100/100 [==============================] - 0s 3ms/step - loss: 0.3568 - sparse_categorical_accuracy: 0.8912 <tensorflow.python.keras.callbacks.History at 0x7fb21c3b7320>
Utilisation d'un ensemble de données de validation
Vous pouvez passer une instance de Dataset
comme argument validation_data
dans 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.5587 - sparse_categorical_accuracy: 0.8436 - val_loss: 0.1735 - val_sparse_categorical_accuracy: 0.9517 <tensorflow.python.keras.callbacks.History at 0x7fb21c19c7b8>
À la fin de chaque époque, le modèle effectuera une itération sur l'ensemble de données de validation et calculera la perte de validation et les métriques de validation.
Si vous souhaitez exécuter la validation uniquement sur un nombre spécifique de lots de cet ensemble de données, vous pouvez passer l'argument validation_steps
, qui spécifie le nombre d'étapes de validation que le modèle doit exécuter avec l'ensemble de données de validation avant d'interrompre la validation et de passer à l'époque suivante:
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.5708 - sparse_categorical_accuracy: 0.8453 - val_loss: 0.2911 - val_sparse_categorical_accuracy: 0.9312 <tensorflow.python.keras.callbacks.History at 0x7fb21c31ff98>
Notez que l'ensemble de données de validation sera réinitialisé après chaque utilisation (de sorte que vous évaluerez toujours sur les mêmes échantillons d'époque en époque).
L'argument validation_split
(générant un ensemble d'exclusion à partir des données d'entraînement) n'est pas pris en charge lors de l'apprentissage à partir d'objets Dataset
, car cette fonctionnalité nécessite la possibilité d'indexer les échantillons des ensembles de données, ce qui n'est généralement pas possible avec l'API Dataset
.
Autres formats d'entrée pris en charge
Outre les tableaux NumPy, les tenseurs désireux et les Datasets
TensorFlow, il est possible d'entraîner un modèle Keras à l'aide de cadres de données Pandas ou à partir de générateurs Python qui génèrent des lots de données et d'étiquettes.
En particulier, la classe keras.utils.Sequence
offre une interface simple pour créer des générateurs de données Python qui prennent en charge le multitraitement et peuvent être mélangés.
En général, nous vous recommandons d'utiliser:
- Données d'entrée NumPy si vos données sont petites et tiennent en mémoire
- Objets de jeu de
Dataset
si vous avez des jeux de données volumineux et que vous devez effectuer une formation distribuée - Objets de
Sequence
si vous avez de grands ensembles de données et que vous devez effectuer beaucoup de traitements personnalisés côté Python qui ne peuvent pas être effectués dans TensorFlow (par exemple, si vous comptez sur des bibliothèques externes pour le chargement ou le prétraitement des données).
Utilisation d'un objet keras.utils.Sequence
comme entrée
keras.utils.Sequence
est un utilitaire que vous pouvez sous- keras.utils.Sequence
pour obtenir un générateur Python avec deux propriétés importantes:
- Cela fonctionne bien avec le multitraitement.
- Il peut être mélangé (par exemple en passant
shuffle=True
dansfit()
).
Une Sequence
doit implémenter deux méthodes:
-
__getitem__
-
__len__
La méthode __getitem__
doit renvoyer un lot complet. Si vous souhaitez modifier votre ensemble de données entre les époques, vous pouvez implémenter on_epoch_end
.
Voici un exemple rapide:
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)
Utilisation de la pondération de l'échantillon et de la pondération de classe
Avec les paramètres par défaut, le poids d'un échantillon est déterminé par sa fréquence dans l'ensemble de données. Il existe deux méthodes pour pondérer les données, indépendamment de la fréquence d'échantillonnage:
- Poids de classe
- Exemples de poids
Poids de classe
Il est fixé par le passage d' un dictionnaire à l' class_weight
argument Model.fit()
. Ce dictionnaire mappe les indices de classe au poids qui doit être utilisé pour les échantillons appartenant à cette classe.
Cela peut être utilisé pour équilibrer les classes sans rééchantillonnage, ou pour entraîner un modèle qui donne plus d'importance à une classe particulière.
Par exemple, si la classe "0" est deux fois moins représentée que la classe "1" dans vos données, vous pouvez utiliser Model.fit(..., class_weight={0: 1., 1: 0.5})
.
Voici un exemple NumPy où nous utilisons des pondérations de classe ou des pondérations d'échantillons pour donner plus d'importance à la classification correcte de la classe # 5 (qui est le chiffre «5» dans l'ensemble de données 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 2ms/step - loss: 0.6531 - sparse_categorical_accuracy: 0.8268 <tensorflow.python.keras.callbacks.History at 0x7fb27c4e6da0>
Exemples de poids
Pour un contrôle fin, ou si vous ne construisez pas de classificateur, vous pouvez utiliser des "poids d'échantillons".
- Lors de l'entraînement à partir des données NumPy:
sample_weight
argumentModel.fit()
àModel.fit()
. - Lors de l'entraînement à partir de
tf.data
ou de tout autre type d'itérateur:(input_batch, label_batch, sample_weight_batch)
rendement(input_batch, label_batch, sample_weight_batch)
.
Un tableau de "poids d'échantillon" est un tableau de nombres qui spécifient le poids que chaque échantillon d'un lot doit avoir dans le calcul de la perte totale. Il est couramment utilisé dans les problèmes de classification déséquilibrés (l'idée étant de donner plus de poids à des classes rarement vues).
Lorsque les poids utilisés sont des uns et des zéros, le tableau peut être utilisé comme masque pour la fonction de perte (en supprimant entièrement la contribution de certains échantillons à la perte totale).
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 2ms/step - loss: 0.6471 - sparse_categorical_accuracy: 0.8342 <tensorflow.python.keras.callbacks.History at 0x7fb21c1257f0>
Voici un exemple d'ensemble de Dataset
correspondant:
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 [==============================] - 2s 3ms/step - loss: 0.6161 - sparse_categorical_accuracy: 0.8486 <tensorflow.python.keras.callbacks.History at 0x7fb27c7a46a0>
Transmission de données à des modèles multi-entrées et multi-sorties
Dans les exemples précédents, nous considérions un modèle avec une seule entrée (un tenseur de forme (764,)
) et une seule sortie (un tenseur de prédiction de forme (10,)
). Mais qu'en est-il des modèles qui ont plusieurs entrées ou sorties?
Considérez le modèle suivant, qui a une entrée d'image de forme (32, 32, 3)
(c'est-à-dire (height, width, channels)
) et une entrée de série temporelle de forme (None, 10)
(c'est (timesteps, features)
). Notre modèle aura deux sorties calculées à partir de la combinaison de ces entrées: un «score» (de forme (1,)
) et une distribution de probabilité sur cinq classes (de forme (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]
)
Tracons ce modèle afin que vous puissiez voir clairement ce que nous faisons ici (notez que les formes affichées dans le tracé sont des formes par lots, plutôt que des formes par échantillon).
keras.utils.plot_model(model, "multi_input_and_output_model.png", show_shapes=True)
Au moment de la compilation, nous pouvons spécifier différentes pertes sur différentes sorties, en passant les fonctions de perte sous forme de liste:
model.compile(
optimizer=keras.optimizers.RMSprop(1e-3),
loss=[keras.losses.MeanSquaredError(), keras.losses.CategoricalCrossentropy()],
)
Si nous ne transmettions qu'une seule fonction de perte au modèle, la même fonction de perte serait appliquée à chaque sortie (ce qui n'est pas approprié ici).
De même pour les métriques:
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()],
],
)
Puisque nous avons donné des noms à nos couches de sortie, nous pourrions également spécifier des pertes et des métriques par sortie via un dict:
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()],
},
)
Nous vous recommandons d'utiliser des noms et dictionnaires explicites si vous avez plus de 2 sorties.
Il est possible de donner différents poids à différentes pertes spécifiques à la sortie (par exemple, on peut souhaiter privilégier la perte "score" dans notre exemple, en donnant à 2x l'importance de la perte de classe), en utilisant l'argument loss_weights
:
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},
)
Vous pouvez également choisir de ne pas calculer une perte pour certaines sorties, si ces sorties sont destinées à la prédiction mais pas à la formation:
# 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()},
)
La transmission de données à un modèle multi-entrées ou multi-sorties en ajustement fonctionne de la même manière que la spécification d'une fonction de perte lors de la compilation: vous pouvez transmettre des listes de tableaux NumPy (avec un mappage 1: 1 vers les sorties qui ont reçu une fonction de perte) ou dicts le mappage des noms de sortie aux tableaux 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 12ms/step - loss: 19.3697 - score_output_loss: 1.3639 - class_output_loss: 18.0058 4/4 [==============================] - 0s 6ms/step - loss: 17.6548 - score_output_loss: 0.7146 - class_output_loss: 16.9402 <tensorflow.python.keras.callbacks.History at 0x7fb27c5d51d0>
Voici le cas d'utilisation du jeu de Dataset
: de la même manière que ce que nous avons fait pour les tableaux NumPy, le jeu de Dataset
doit renvoyer un tuple de dictionnaires.
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 29ms/step - loss: 17.3215 - score_output_loss: 0.5076 - class_output_loss: 16.8139 <tensorflow.python.keras.callbacks.History at 0x7fb27c46b438>
Utilisation des rappels
Les callbacks dans Keras sont des objets qui sont appelés à différents moments pendant l'apprentissage (au début d'une époque, à la fin d'un batch, à la fin d'une époque, etc.) et qui peuvent être utilisés pour implémenter des comportements tels que:
- Faire la validation à différents moments de la formation (au-delà de la validation intégrée par époque)
- Contrôle du modèle à intervalles réguliers ou lorsqu'il dépasse un certain seuil de précision
- Changer le taux d'apprentissage du modèle lorsque la formation semble plafonner
- Ajuster les couches supérieures lorsque l'entraînement semble plafonner
- Envoi de notifications par e-mail ou par messagerie instantanée à la fin de la formation ou lorsqu'un certain seuil de performance est dépassé
- Etc.
Les rappels peuvent être passés sous forme de liste à votre appel à 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.6313 - sparse_categorical_accuracy: 0.8207 - val_loss: 0.2313 - val_sparse_categorical_accuracy: 0.9307 Epoch 2/20 625/625 [==============================] - 2s 3ms/step - loss: 0.1827 - sparse_categorical_accuracy: 0.9459 - val_loss: 0.1989 - val_sparse_categorical_accuracy: 0.9410 Epoch 3/20 625/625 [==============================] - 2s 3ms/step - loss: 0.1298 - sparse_categorical_accuracy: 0.9619 - val_loss: 0.1561 - val_sparse_categorical_accuracy: 0.9529 Epoch 4/20 625/625 [==============================] - 2s 2ms/step - loss: 0.0977 - sparse_categorical_accuracy: 0.9713 - val_loss: 0.1434 - val_sparse_categorical_accuracy: 0.9576 Epoch 5/20 625/625 [==============================] - 2s 3ms/step - loss: 0.0799 - sparse_categorical_accuracy: 0.9755 - val_loss: 0.1364 - val_sparse_categorical_accuracy: 0.9614 Epoch 6/20 625/625 [==============================] - 2s 3ms/step - loss: 0.0648 - sparse_categorical_accuracy: 0.9806 - val_loss: 0.1351 - val_sparse_categorical_accuracy: 0.9617 Epoch 00006: early stopping <tensorflow.python.keras.callbacks.History at 0x7fb29ca68940>
De nombreux rappels intégrés sont disponibles
-
ModelCheckpoint
: enregistrez périodiquement le modèle. -
EarlyStopping
:EarlyStopping
entraînement lorsque l'entraînement n'améliore plus les métriques de validation. -
TensorBoard
:TensorBoard
périodiquement des journaux de modèles qui peuvent être visualisés dans TensorBoard (plus de détails dans la section «Visualisation»). -
CSVLogger
: diffuse les données de perte et de métrique dans un fichier CSV. - etc.
Voir la documentation des rappels pour la liste complète.
Rédaction de votre propre rappel
Vous pouvez créer un rappel personnalisé en étendant la classe de base keras.callbacks.Callback
. Un rappel a accès à son modèle associé via la propriété de classe self.model
.
Assurez-vous de lire le guide complet sur l'écriture de rappels personnalisés .
Voici un exemple simple d'enregistrement d'une liste de valeurs de perte par lot pendant l'entraînement:
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"))
Modèles de point de contrôle
Lorsque vous entraînez un modèle sur des ensembles de données relativement volumineux, il est essentiel d'enregistrer les points de contrôle de votre modèle à intervalles fréquents.
Le moyen le plus simple d'y parvenir est d' ModelCheckpoint
rappel ModelCheckpoint
:
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 625/625 [==============================] - 2s 3ms/step - loss: 0.6208 - sparse_categorical_accuracy: 0.8258 - val_loss: 0.2241 - val_sparse_categorical_accuracy: 0.9326 Epoch 00001: val_loss improved from inf to 0.22410, saving model to mymodel_1 INFO:tensorflow:Assets written to: mymodel_1/assets Epoch 2/2 625/625 [==============================] - 2s 3ms/step - loss: 0.1820 - sparse_categorical_accuracy: 0.9470 - val_loss: 0.1621 - val_sparse_categorical_accuracy: 0.9497 Epoch 00002: val_loss improved from 0.22410 to 0.16212, saving model to mymodel_2 INFO:tensorflow:Assets written to: mymodel_2/assets <tensorflow.python.keras.callbacks.History at 0x7fb21c3e8a20>
Le rappel ModelCheckpoint
peut être utilisé pour implémenter la tolérance aux pannes: la possibilité de redémarrer l'entraînement à partir du dernier état enregistré du modèle au cas où l'entraînement serait interrompu de manière aléatoire. Voici un exemple de base:
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 94/1563 [>.............................] - ETA: 3s - loss: 1.4324 - sparse_categorical_accuracy: 0.5773INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.96/assets 193/1563 [==>...........................] - ETA: 5s - loss: 1.1162 - sparse_categorical_accuracy: 0.6814INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.69/assets 290/1563 [====>.........................] - ETA: 6s - loss: 0.9546 - sparse_categorical_accuracy: 0.7298INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.57/assets 395/1563 [======>.......................] - ETA: 6s - loss: 0.8447 - sparse_categorical_accuracy: 0.7617INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.51/assets 493/1563 [========>.....................] - ETA: 6s - loss: 0.7744 - sparse_categorical_accuracy: 0.7817INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.47/assets 598/1563 [==========>...................] - ETA: 5s - loss: 0.7186 - sparse_categorical_accuracy: 0.7973INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.44/assets 696/1563 [============>.................] - ETA: 5s - loss: 0.6778 - sparse_categorical_accuracy: 0.8086INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.42/assets 794/1563 [==============>...............] - ETA: 4s - loss: 0.6445 - sparse_categorical_accuracy: 0.8178INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.40/assets 898/1563 [================>.............] - ETA: 4s - loss: 0.6146 - sparse_categorical_accuracy: 0.8260INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.38/assets 995/1563 [==================>...........] - ETA: 3s - loss: 0.5907 - sparse_categorical_accuracy: 0.8326INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.36/assets 1095/1563 [====================>.........] - ETA: 2s - loss: 0.5693 - sparse_categorical_accuracy: 0.8385INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.35/assets 1196/1563 [=====================>........] - ETA: 2s - loss: 0.5503 - sparse_categorical_accuracy: 0.8437INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.34/assets 1297/1563 [=======================>......] - ETA: 1s - loss: 0.5334 - sparse_categorical_accuracy: 0.8484INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.33/assets 1391/1563 [=========================>....] - ETA: 1s - loss: 0.5193 - sparse_categorical_accuracy: 0.8523INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.32/assets 1497/1563 [===========================>..] - ETA: 0s - loss: 0.5050 - sparse_categorical_accuracy: 0.8563INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.31/assets 1563/1563 [==============================] - 11s 6ms/step - loss: 0.4966 - sparse_categorical_accuracy: 0.8586 <tensorflow.python.keras.callbacks.History at 0x7fb2700955c0>
Vous appelez également rédigez votre propre rappel pour enregistrer et restaurer les modèles.
Pour un guide complet sur la sérialisation et l'enregistrement, consultez le guide d'enregistrement et de sérialisation des modèles .
Utilisation des grilles de taux d'apprentissage
Un modèle courant lors de la formation de modèles d'apprentissage profond consiste à réduire progressivement l'apprentissage au fur et à mesure que la formation progresse. Ceci est généralement connu sous le nom de «décroissance du taux d'apprentissage».
Le calendrier de décroissance d'apprentissage peut être statique (fixé à l'avance, en fonction de l'époque courante ou de l'indice de lot courant), ou dynamique (répondant au comportement actuel du modèle, en particulier la perte de validation).
Passer un planning à un optimiseur
Vous pouvez facilement utiliser un calendrier de décroissance du taux d'apprentissage statique en passant un objet de planification comme argument learning_rate
dans votre optimiseur:
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)
Plusieurs planifications intégrées sont disponibles: ExponentialDecay
, PiecewiseConstantDecay
, PolynomialDecay
et InverseTimeDecay
.
Utilisation des rappels pour mettre en œuvre un calendrier de taux d'apprentissage dynamique
Un programme de taux d'apprentissage dynamique (par exemple, la diminution du taux d'apprentissage lorsque la perte de validation ne s'améliore plus) ne peut pas être obtenu avec ces objets de planification car l'optimiseur n'a pas accès aux métriques de validation.
Cependant, les rappels ont accès à toutes les métriques, y compris les métriques de validation! Vous pouvez ainsi réaliser ce modèle en utilisant un callback qui modifie le taux d'apprentissage actuel sur l'optimiseur. En fait, cela est même intégré au rappel ReduceLROnPlateau
.
Visualiser les pertes et les métriques pendant l'entraînement
La meilleure façon de garder un œil sur votre modèle pendant l'entraînement est d'utiliser TensorBoard , une application basée sur un navigateur que vous pouvez exécuter localement et qui vous fournit:
- Graphiques en direct de la perte et métriques pour la formation et l'évaluation
- (en option) Visualisations des histogrammes de vos activations de calques
- (en option) visualisations 3D des espaces d'incorporation appris par vos calques d'
Embedding
Si vous avez installé TensorFlow avec pip, vous devriez pouvoir lancer TensorBoard à partir de la ligne de commande:
tensorboard --logdir=/full_path_to_your_logs
Utilisation du rappel TensorBoard
Le moyen le plus simple d'utiliser TensorBoard avec un modèle Keras et la méthode fit est le rappel TensorBoard
.
Dans le cas le plus simple, spécifiez simplement où vous voulez que le rappel écrive les journaux, et vous êtes prêt à partir:
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)
<tensorflow.python.keras.callbacks.TensorBoard at 0x7fb21c22deb8>
Pour plus d'informations, consultez la documentation du rappel TensorBoard
.