![]() | ![]() | ![]() | ![]() |
Installer
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
introduction
Ce guide couvre la formation, l' évaluation et la prévision des modèles (inférence) lors de l' utilisation intégrée des API pour la formation et la validation (comme Model.fit()
, Model.evaluate()
et Model.predict()
).
Si vous êtes intéressé à tirer parti fit()
en spécifiant votre propre fonction de l' étape de formation, consultez le Personnalisation ce qui se passe en fit()
Guide .
Si vous êtes intéressé par écrit 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, qui est couvert dans notre guide pour la formation multi-GPU et distribué .
Présentation de l'API : un premier exemple de bout en bout
Lors du passage des données aux boucles de formation intégré d'un modèle, vous devez soit utiliser des tableaux numpy (si vos données sont petites et se glisse dans la mémoire) ou tf.data Dataset
objets. 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 intégrons l'API fonctionnelle, mais il peut également s'agir d'un modèle séquentiel ou d'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 de bout en bout typique, composé de :
- Entraînement
- Validation sur un ensemble de holdout 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 d'entraînement (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 lançons un appel en fit()
, qui formera le modèle en découpant les données en « lots » de taille batch_size
, et à plusieurs reprises itérer sur l'ensemble des données pour un nombre donné d' 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
Le retour history
objet contient un enregistrement des valeurs de perte et les valeurs métriques au cours de la formation:
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]}
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.1414 - sparse_categorical_accuracy: 0.9569 test loss, test acc: [0.14140386879444122, 0.9569000005722046] 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 compile()
méthode: spécifier une perte, des métriques, et un optimiseur
Pour former un modèle avec fit()
, vous devez spécifier une fonction de perte, un optimiseur, et le cas échéant, certains paramètres à surveiller.
Vous passez ces au modèle comme arguments à la compile()
méthode:
model.compile(
optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
loss=keras.losses.SparseCategoricalCrossentropy(),
metrics=[keras.metrics.SparseCategoricalAccuracy()],
)
Les metrics
argument doit être une liste - votre modèle peut avoir un certain nombre de mesures.
Si votre modèle a plusieurs sorties, vous pouvez spécifier différentes pertes et mesures 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 les données transitant à entrées multiples, section modèles multi-sorties.
Notez que si vous êtes satisfait des paramètres par défaut, dans de nombreux cas, l'optimiseur, la perte et les métriques peuvent être spécifiés via des identifiants de chaîne comme raccourci :
model.compile(
optimizer="rmsprop",
loss="sparse_categorical_crossentropy",
metrics=["sparse_categorical_accuracy"],
)
Pour une réutilisation ultérieure, plaçons notre définition de modèle et notre étape de compilation dans les fonctions ; nous les appellerons plusieurs fois à travers différents exemples dans 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 vos propres pertes, métriques ou optimiseurs à partir de zéro, car ce dont vous avez besoin fait probablement déjà partie de l'API Keras :
Optimiseurs :
-
SGD()
(avec ou sans élan) -
RMSprop()
-
Adam()
- etc.
Pertes:
-
MeanSquaredError()
-
KLDivergence()
-
CosineSimilarity()
- etc.
Métrique:
-
AUC()
-
Precision()
-
Recall()
- etc.
Pertes personnalisées
Si vous devez créer une perte personnalisée, Keras propose deux manières de le faire.
Le premier procédé implique la création d' 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.0162 <keras.callbacks.History at 0x7ff8881ba250>
Si vous avez besoin d' une fonction de perte qui prend en paramètres à côté y_true
et y_pred
, vous pouvez créer une sous tf.keras.losses.Loss
classe et mettre en œuvre les deux méthodes suivantes:
-
__init__(self)
: accepter des paramètres à passer lors de l'appel de votre fonction de perte -
call(self, y_true, y_pred)
: utiliser 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 une erreur quadratique moyenne, mais avec un terme ajouté qui désincitera les valeurs de prédiction loin de 0,5 (nous supposons que les cibles catégorielles sont codé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 surapprentissage (nous ne saurons pas si cela fonctionne avant d'avoir essayé !).
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.0388 <keras.callbacks.History at 0x7ff8882130d0>
Métriques personnalisées
Si vous avez besoin d' une mesure qui ne fait pas partie de l'API, vous pouvez facilement créer des paramètres personnalisés par la sous - classement tf.keras.metrics.Metric
classe. Vous devrez mettre en œuvre 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 le résultat final. -
reset_state(self)
, qui réinitialise l'état de la métrique.
Mise à jour de l' Etat et le calcul des résultats sont maintenus séparés (dans update_state()
et result()
, respectivement) parce que dans certains cas, le calcul des résultats pourrait être très coûteux et ne seront faites périodiquement.
Voici un exemple simple montrant comment implémenter une CategoricalTruePositives
métrique qui compte combien d'échantillons ont été classés correctement 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_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>
Gérer les pertes et les métriques qui ne correspondent pas à la signature standard
La majorité écrasante des pertes et des mesures peut être calculée à partir 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 ce cas, vous pouvez appeler self.add_loss(loss_value)
à l' intérieur de la méthode d'appel d'une couche personnalisée. Les pertes ajoutées de cette manière sont ajoutés à la perte « principale » pendant l' entraînement (celui passé à compile()
). Voici un exemple simple qui ajoute une régularisation d'activité (notez que la régularisation d'activité est intégrée dans toutes les couches Keras - cette couche est juste pour fournir 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: 2.4545 <keras.callbacks.History at 0x7ff87c53f310>
Vous pouvez faire la même chose pour les valeurs métriques d' exploitation forestière, à l' aide 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>
Dans l' API fonctionnelle , vous pouvez également appeler model.add_loss(loss_tensor)
, ou model.add_metric(metric_tensor, name, aggregation)
le model.add_metric(metric_tensor, name, aggregation)
l' 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 3ms/step - loss: 2.4647 - std_of_activation: 0.0017 <keras.callbacks.History at 0x7ff87c216f90>
Notez que lorsque vous passez des pertes par add_loss()
, il devient possible d'appeler la compile()
sans fonction de perte, puisque le modèle a déjà une perte de minimiser.
Considérez ce qui suit LogisticEndpoint
couche: il faut que les cibles entrées et logits, et il suit une perte crossentropy via add_loss()
. Il suit également la précision de la classification par 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és sans loss
argument, 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 414ms/step - loss: 0.9889 - binary_accuracy: 0.0000e+00 <keras.callbacks.History at 0x7ff87c0848d0>
Pour plus d' informations sur la formation des modèles multi-entrée, consultez la section Passage de données à entrées multiples, des modèles multi-sorties.
Mise à part automatique d'un ensemble d'exclusion de validation
Dans le premier exemple de bout en bout que vous avez vu, nous avons utilisé le validation_data
argument pour passer un tuple de tableaux numpy (x_val, y_val)
au modèle d'évaluation d' une perte et de validation des paramètres de validation à la fin de chaque époque.
Voici une autre option: l'argument validation_split
vous permet de réserver une partie automatiquement de vos données de formation pour la validation. La valeur de l' argument représente la fraction des données qui doivent être réservés pour la validation, de sorte qu'il doit être réglé sur un nombre supérieur à 0 et inférieur à 1. Par exemple, validation_split=0.2
signifie « utilisation 20% des données de validation », et validation_split=0.6
signifie « l' utilisation de 60% des données de validation ».
La façon dont la validation est calculée est en prenant les derniers échantillons x% des réseaux reçus par l' fit()
appel, avant tout brassage.
Notez que vous ne pouvez utiliser validation_split
lors de la formation 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.3682 - sparse_categorical_accuracy: 0.8957 - val_loss: 0.2276 - val_sparse_categorical_accuracy: 0.9301 <keras.callbacks.History at 0x7ff81c680890>
Formation et évaluation à partir des ensembles de données tf.data
Dans les derniers paragraphes, vous avez vu comment gérer les pertes, les mesures et les optimiseurs, et vous avez vu comment utiliser les validation_data
et validation_split
arguments en fit()
, vos données sont transmis sous forme de tableaux numpy.
Jetons maintenant un coup d' oeil au cas où vos données se présente sous la forme d'un tf.data.Dataset
objet.
L' tf.data
API est un ensemble d'utilitaires en tensorflow 2.0 pour le chargement et les données de pré - traitement d'une manière qui est rapide et évolutive.
Pour un guide complet sur la création Datasets
, consultez la documentation tf.data .
Vous pouvez passer un Dataset
exemple 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.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}
Notez que le jeu de données est réinitialisé à la fin de chaque époque, il peut donc être réutilisé à l'époque suivante.
Si vous voulez exécuter la formation que sur un nombre spécifique de lots de ce DataSet, vous pouvez passer le steps_per_epoch
argument, qui indique le nombre de formations les étapes du modèle devrait fonctionner en utilisant ce DataSet avant de passer à l'époque suivante.
Si vous faites cela, l'ensemble de données n'est pas réinitialisé à la fin de chaque époque, au lieu de cela, nous continuons simplement à dessiner les prochains lots. L'ensemble de données finira par manquer de données (sauf s'il s'agit 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: 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>
Utilisation d'un ensemble de données de validation
Vous pouvez passer une Dataset
instance que le validation_data
argument en 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>
À la fin de chaque époque, le modèle itérera 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 sur un nombre spécifique de lots de ce jeu de données, vous pouvez passer le validation_steps
argument, qui indique le nombre de validation étapes du modèle devrait fonctionner 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.3369 - sparse_categorical_accuracy: 0.9036 - val_loss: 0.2953 - val_sparse_categorical_accuracy: 0.9187 <keras.callbacks.History at 0x7ff81c30e310>
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'une époque à l'autre).
L'argument validation_split
(générant un ensemble holdout à partir des données de formation) ne sont pas pris en charge lors de la formation de Dataset
objets, car cette fonction requiert la capacité d'indexer les échantillons des ensembles de données, ce qui est impossible en général avec l' Dataset
API.
Autres formats d'entrée pris en charge
En plus des tableaux numpy, tenseurs, avides et tensorflow Datasets
, il est possible de former un modèle en utilisant Keras dataframes Pandas, ou de générateurs Python que les lots de rendement des données et des étiquettes.
En particulier, les keras.utils.Sequence
offre de classe une interface simple pour construire des générateurs de données Python qui sont multitraitement, et qui pourrait être brassés.
De manière générale, nous vous recommandons d'utiliser :
- Données d'entrée NumPy si vos données sont petites et tiennent en mémoire
-
Dataset
objets si vous avez de grands ensembles de données et vous devez faire une formation distribuée -
Sequence
des objets si vous avez de grands ensembles de données et vous devez faire beaucoup de traitement personnalisé côté Python qui ne peut pas être fait dans tensorflow (par exemple , si vous comptez sur les bibliothèques externes pour le chargement de données ou prétraiter).
L' utilisation d' un keras.utils.Sequence
objet comme entrée
keras.utils.Sequence
est un utilitaire que vous pouvez sous - classe 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 lors du passage
shuffle=True
dansfit()
).
Une Sequence
doit mettre en œuvre deux méthodes:
-
__getitem__
-
__len__
La méthode __getitem__
doit retourner un lot complet. Si vous souhaitez modifier votre ensemble de données entre les époques, vous pouvez mettre en œuvre 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 d'é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 des classes
- Poids des échantillons
Poids des classes
Il est fixé par le passage d' un dictionnaire à l' class_weight
argument Model.fit()
. Ce dictionnaire mappe les indices de classe sur le poids qui doit être utilisé pour les échantillons appartenant à cette classe.
Cela peut être utilisé pour équilibrer les classes sans rééchantillonnage, ou pour former un modèle qui donne plus d'importance à une classe particulière.
Par exemple, si la classe "0" est la moitié représentée en 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 poids de classe ou des poids d'échantillon 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 3ms/step - loss: 0.3708 - sparse_categorical_accuracy: 0.9032 <keras.callbacks.History at 0x7ff80c7ddd10>
Poids des échantillons
Pour un contrôle à grain fin, ou si vous ne construisez pas de classificateur, vous pouvez utiliser des "poids d'échantillonnage".
- Lorsque la formation à partir des données numpy: Faire passer le
sample_weight
argumentModel.fit()
. - Lorsque la formation de
tf.data
ou tout autre type de iterator: Rendement(input_batch, label_batch, sample_weight_batch)
tuples.
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ée (l'idée étant de donner plus de poids à des classes rarement vues).
Lorsque les poids utilisés sont des uns et de zéros, la matrice peut être utilisée comme un masque pour la fonction de perte (entièrement rejeter 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 3ms/step - loss: 0.3806 - sparse_categorical_accuracy: 0.9000 <keras.callbacks.History at 0x7ff80c650350>
Voici un correspondant Dataset
exemple:
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>
Transmission de données à des modèles multi-entrées et multi-sorties
Dans les exemples précédents, nous avons été considérons un modèle avec une seule entrée (un tenseur de forme (764,)
) et une sortie unique (un tenseur de prédiction de forme (10,)
). Mais qu'en est-il des modèles qui ont plusieurs entrées ou sorties ?
Considérons le modèle suivant, qui a une entrée d'image de forme (32, 32, 3)
(qui est (height, width, channels)
) et une entrée de séries chronologiques de forme (None, 10)
(ce qui est (timesteps, features)
pas de (timesteps, features)
les (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]
)
Traçons ce modèle pour 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 les pertes et les 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 recommandons l'utilisation de noms et de dicts explicites si vous avez plus de 2 sorties.
Il est possible de donner différents poids à différentes pertes spécifiques de sortie (par exemple, on pourrait souhaiter privilégier la perte « score » dans notre exemple, en donnant à 2x l'importance de la perte de classe), en utilisant le loss_weights
argument:
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 de perte pour certaines sorties, si ces sorties sont destinées à la prédiction mais pas à l'entraînement :
# 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()},
)
Faire passer des données à un modèle à sorties multiples ou multi-entrée en fit()
fonctionne d'une manière similaire à celle de la spécification d' une fonction de perte de compilation: vous pouvez transmettre des listes de réseaux numpy (avec mappage 1: 1 des sorties qui ont reçu une fonction de perte ) ou dicts cartographier les noms de sortie de 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 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>
Voici le Dataset
cas d'utilisation: de même que ce que nous avons fait pour les tableaux numpy, le Dataset
doit retourner un tuple 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>
Utiliser les rappels
Les rappels dans Keras sont des objets qui sont appelés à différents moments de l'apprentissage (au début d'une époque, à la fin d'un lot, à la fin d'une époque, etc.). Ils peuvent être utilisés pour mettre en œuvre certains comportements, tels que :
- Faire la validation à différents moments pendant la formation (au-delà de la validation par époque intégrée)
- Point de contrôle du modèle à intervalles réguliers ou lorsqu'il dépasse un certain seuil de précision
- Modification du taux d'apprentissage du modèle lorsque l'entraînement semble plafonner
- Faire un réglage fin des couches supérieures lorsque l'entraînement semble plafonner
- Envoi de notifications par e-mail ou par message instantané lorsque la formation se termine ou lorsqu'un certain seuil de performance est dépassé
- Etc.
Callbacks peuvent être passés comme une 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.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>
De nombreux rappels intégrés sont disponibles
De nombreux rappels intégrés sont déjà disponibles dans Keras, tels que :
-
ModelCheckpoint
: périodiquement sauvegarder le modèle. -
EarlyStopping
: formation d' arrêt lorsque la formation ne s'améliore plus les mesures de validation. -
TensorBoard
: les journaux de modèle écrire périodiquement visualisables dans TensorBoard (plus de détails dans la section « Visualisation »). -
CSVLogger
: les flux de données de perte et métriques dans un fichier CSV. - etc.
Consultez la documentation de callbacks pour la liste complète.
Rédiger 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é par la propriété de la classe self.model
.
Assurez - vous de lire le guide complet pour écrire callbacks 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 points 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.
La meilleure façon d' y parvenir est avec le ModelCheckpoint
rappel:
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>
Le ModelCheckpoint
rappel peut être utilisé pour mettre en œuvre la tolérance aux pannes: la capacité de formation de redémarrage du dernier état enregistré du modèle dans la formation de cas se aléatoire interrompu. 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 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>
Vous appelez également écrire votre propre rappel pour enregistrer et restaurer des modèles.
Pour un guide complet sur la sérialisation et la sauvegarde, consultez le guide pour l' enregistrement et la sérialisation modèles .
Utilisation des grilles tarifaires d'apprentissage
Un modèle courant lors de la formation de modèles d'apprentissage en profondeur 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 planning de décroissance de l'apprentissage peut être statique (fixé à l'avance, en fonction de l'époque courante ou de l'indice batch courant), ou dynamique (répondant au comportement courant du modèle, notamment la perte de validation).
Passer un planning à un optimiseur
Vous pouvez facilement utiliser un programme de décroissance du taux d'apprentissage statique en passant un objet calendrier que le learning_rate
argument 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 programmes intégrés sont disponibles: ExponentialDecay
, PiecewiseConstantDecay
, PolynomialDecay
et InverseTimeDecay
.
Utiliser des rappels pour mettre en œuvre un calendrier de taux d'apprentissage dynamique
Un calendrier de taux d'apprentissage dynamique (par exemple, diminuer le taux d'apprentissage lorsque la perte de validation ne s'améliore plus) ne peut pas être réalisé avec ces objets de calendrier, 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 donc réaliser ce pattern en utilisant un callback qui modifie le taux d'apprentissage actuel sur l'optimiseur. En fait, cela est même intégré comme ReduceLROnPlateau
rappel.
Visualisation des pertes et des mesures pendant l'entraînement
La meilleure façon de garder un oeil sur votre modèle lors de la formation est d'utiliser TensorBoard - une application basée sur un navigateur que vous pouvez exécuter qui vous fournit localement avec:
- Tracés en direct de la perte et métriques pour la formation et l'évaluation
- (optionnellement) Visualisations des histogrammes de vos activations de couches
- ( en option) visualisations 3D des espaces appris par vos encastrement
Embedding
couches
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
Utiliser le rappel TensorBoard
La meilleure façon d'utiliser TensorBoard avec un modèle Keras et l' fit()
méthode est la TensorBoard
rappel.
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)
<keras.callbacks.TensorBoard at 0x7ff88c8c04d0>
Pour plus d' informations, consultez la documentation du TensorBoard
rappel .