Aide à protéger la Grande barrière de corail avec tensorflow sur Kaggle Rejoignez Défi

Formation et évaluation avec les méthodes intégrées

Voir sur TensorFlow.org Exécuter dans Google Colab Voir la source sur GitHub Télécharger le cahier

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 construisons avec l'API fonctionnelle, mais il pourrait é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 façons 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 vous procéderiez :

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 ne nécessiter que 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 l'ensemble 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 dans fit() ).

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 de l'échantillon

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 argument Model.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)

png

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 souhaitez 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 .