Diese Seite wurde von der Cloud Translation API übersetzt.
Switch to English

Schulung und Bewertung mit den eingebauten Methoden

Ansicht auf TensorFlow.org Führen Sie in Google Colab aus Quelle auf GitHub anzeigen Notizbuch herunterladen

Konfiguration

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

Einführung

Dieses Handbuch behandelt Trainings-, Evaluierungs- und Vorhersagemodelle (Inferenzmodelle), wenn integrierte APIs für Training und Validierung verwendet werden (z. B. model.fit() , model.evaluate() , model.predict() ).

Wenn Sie fit() nutzen möchten, während Sie Ihre eigene Trainingsschrittfunktion angeben, lesen Sie die Anleitung "Anpassen, was in fit() passiert" .

Wenn Sie daran interessiert sind, Ihre eigenen Trainings- und Bewertungsschleifen von Grund auf neu zu schreiben , lesen Sie die Anleitung "Schreiben einer Trainingsschleife von Grund auf neu" .

Unabhängig davon, ob Sie integrierte Schleifen verwenden oder eigene schreiben, funktioniert die Modellschulung und -bewertung für alle Arten von Keras-Modellen streng gleich - sequentielle Modelle, Modelle, die mit der Funktions-API erstellt wurden, und Modelle, die von Grund auf neu geschrieben wurden Modellunterklassen.

Dieser Leitfaden behandelt keine verteilten Schulungen. Informationen zu verteilten Schulungen finden Sie in unserem Leitfaden zu Multi-GPU- und verteilten Schulungen .

API-Übersicht: Ein erstes End-to-End-Beispiel

Wenn Sie Daten an die integrierten Trainingsschleifen eines Modells übergeben, sollten Sie entweder NumPy-Arrays (wenn Ihre Daten klein sind und in den Speicher tf.data Dataset ) oder tf.data Dataset Objekte verwenden . In den nächsten Absätzen verwenden wir das MNIST-Dataset als NumPy-Arrays, um die Verwendung von Optimierern, Verlusten und Metriken zu demonstrieren.

Betrachten wir das folgende Modell (hier bauen wir die funktionale API ein, es kann sich aber auch um ein sequentielles Modell oder ein untergeordnetes Modell handeln):

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)

So sieht der typische End-to-End-Workflow aus: Bestehend aus:

  • Ausbildung
  • Validierung eines Holdout-Sets, das aus den ursprünglichen Trainingsdaten generiert wurde
  • Auswertung der Testdaten

In diesem Beispiel werden MNIST-Daten verwendet.

(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]

Wir geben die Trainingskonfiguration an (Optimierer, Verlust, Metriken):

model.compile(
    optimizer=keras.optimizers.RMSprop(),  # Optimizer
    # Loss function to minimize
    loss=keras.losses.SparseCategoricalCrossentropy(),
    # List of metrics to monitor
    metrics=[keras.metrics.SparseCategoricalAccuracy()],
)

Wir rufen fit() , das das Modell trainiert, indem die Daten in "Stapel" der Größe "batch_size" aufgeteilt und für eine bestimmte Anzahl von "Epochen" wiederholt über den gesamten Datensatz iteriert werden.

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 [==============================] - 2s 2ms/step - loss: 0.3425 - sparse_categorical_accuracy: 0.9034 - val_loss: 0.1827 - val_sparse_categorical_accuracy: 0.9478
Epoch 2/2
782/782 [==============================] - 2s 2ms/step - loss: 0.1618 - sparse_categorical_accuracy: 0.9513 - val_loss: 0.1282 - val_sparse_categorical_accuracy: 0.9651

Das zurückgegebene "Verlauf" -Objekt enthält eine Aufzeichnung der Verlustwerte und Metrikwerte während des Trainings:

history.history
{'loss': [0.3424801528453827, 0.16180744767189026],
 'sparse_categorical_accuracy': [0.903439998626709, 0.9512799978256226],
 'val_loss': [0.18268445134162903, 0.12816601991653442],
 'val_sparse_categorical_accuracy': [0.9477999806404114, 0.9650999903678894]}

Wir bewerten das Modell anhand der Testdaten über 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 1ms/step - loss: 0.1310 - sparse_categorical_accuracy: 0.9637
test loss, test acc: [0.1309928148984909, 0.963699996471405]
Generate predictions for 3 samples
predictions shape: (3, 10)

Lassen Sie uns nun jeden Teil dieses Workflows im Detail überprüfen.

Die compile() -Methode: Angabe eines Verlusts, von Metriken und eines Optimierers

Um ein Modell mit fit() zu trainieren, müssen Sie eine Verlustfunktion, einen Optimierer und optional einige zu überwachende Metriken angeben.

Sie übergeben diese als Argumente an die compile() -Methode an das Modell:

model.compile(
    optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
    loss=keras.losses.SparseCategoricalCrossentropy(),
    metrics=[keras.metrics.SparseCategoricalAccuracy()],
)

Das metrics sollte eine Liste sein - Ihr Modell kann eine beliebige Anzahl von Metriken enthalten.

Wenn Ihr Modell mehrere Ausgaben hat, können Sie für jede Ausgabe unterschiedliche Verluste und Metriken angeben und den Beitrag jeder Ausgabe zum Gesamtverlust des Modells modulieren. Weitere Details hierzu finden Sie im Abschnitt "Übergeben von Daten an Modelle mit mehreren Eingängen und mehreren Ausgängen" .

Wenn Sie mit den Standardeinstellungen zufrieden sind, können Optimierer, Verlust und Metriken in vielen Fällen über Zeichenfolgen-IDs als Verknüpfung angegeben werden:

model.compile(
    optimizer="rmsprop",
    loss="sparse_categorical_crossentropy",
    metrics=["sparse_categorical_accuracy"],
)

Lassen Sie uns zur späteren Wiederverwendung unsere Modelldefinition und den Kompilierungsschritt in Funktionen einfügen. Wir werden sie in diesem Handbuch mehrmals anhand verschiedener Beispiele aufrufen.

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

Viele integrierte Optimierer, Verluste und Metriken sind verfügbar

Im Allgemeinen müssen Sie Ihre eigenen Verluste, Metriken oder Optimierer nicht von Grund auf neu erstellen, da das, was Sie benötigen, wahrscheinlich bereits Teil der Keras-API ist:

Optimierer:

  • SGD() (mit oder ohne Impuls)
  • RMSprop()
  • Adam()
  • etc.

Verluste:

  • MeanSquaredError()
  • KLDivergence()
  • CosineSimilarity()
  • etc.

Metriken:

  • AUC()
  • Precision()
  • Recall()
  • etc.

Zollverluste

Es gibt zwei Möglichkeiten, um benutzerdefinierte Verluste mit Keras bereitzustellen. Im ersten Beispiel wird eine Funktion erstellt, die die Eingaben y_true und y_pred akzeptiert. Das folgende Beispiel zeigt eine Verlustfunktion, die den mittleren quadratischen Fehler zwischen den realen Daten und den Vorhersagen berechnet:

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 [==============================] - 1s 1ms/step - loss: 0.0168

<tensorflow.python.keras.callbacks.History at 0x7f75581d56a0>

Wenn Sie eine Verlustfunktion benötigen, die neben y_true und y_pred Parameter y_pred , können Sie die Klasse tf.keras.losses.Loss und die folgenden zwei Methoden implementieren:

  • __init__(self) : Akzeptiert Parameter, die während des Aufrufs Ihrer Verlustfunktion übergeben werden sollen
  • call(self, y_true, y_pred) : Verwenden Sie die Ziele (y_true) und die Modellvorhersagen (y_pred), um den Verlust des Modells zu berechnen

Angenommen, Sie möchten den mittleren quadratischen Fehler verwenden, jedoch mit einem zusätzlichen Begriff, der die Vorhersagewerte weit von 0,5 entfernt (wir gehen davon aus, dass die kategorialen Ziele One-Hot-codiert sind und Werte zwischen 0 und 1 annehmen). Dies schafft einen Anreiz für das Modell, nicht zu sicher zu sein, was dazu beitragen kann, die Überanpassung zu reduzieren (wir werden nicht wissen, ob es funktioniert, bis wir es versuchen!).

So würden Sie es machen:

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 [==============================] - 1s 2ms/step - loss: 0.0390

<tensorflow.python.keras.callbacks.History at 0x7f7558184c88>

Benutzerdefinierte Metriken

Wenn Sie eine Metrik benötigen, die nicht Teil der API ist, können Sie einfach benutzerdefinierte Metriken erstellen, indem Sie die Klasse tf.keras.metrics.Metric . Sie müssen 4 Methoden implementieren:

  • __init__(self) , in dem Sie Statusvariablen für Ihre Metrik erstellen.
  • update_state(self, y_true, y_pred, sample_weight=None) , das die Ziele y_true und die Modellvorhersagen y_pred verwendet, um die Statusvariablen zu aktualisieren.
  • result(self) , das die Statusvariablen verwendet, um die Endergebnisse zu berechnen.
  • reset_states(self) , das den Status der Metrik neu reset_states(self) .

update_state() und Ergebnisberechnung werden getrennt gehalten (in update_state() bzw. result() ), da in einigen Fällen die Ergebnisberechnung sehr teuer sein kann und nur in regelmäßigen Abständen durchgeführt wird.

Hier ist ein einfaches Beispiel, das zeigt, wie eine CategoricalTruePositives Metrik implementiert wird, die zählt, wie viele Stichproben korrekt als zu einer bestimmten Klasse gehörend klassifiziert wurden:

class CategoricalTruePositives(keras.metrics.Metric):
    def __init__(self, name="categorical_true_positives", **kwargs):
        super(CategoricalTruePositives, self).__init__(name=name, **kwargs)
        self.true_positives = self.add_weight(name="ctp", initializer="zeros")

    def update_state(self, y_true, y_pred, sample_weight=None):
        y_pred = tf.reshape(tf.argmax(y_pred, axis=1), shape=(-1, 1))
        values = tf.cast(y_true, "int32") == tf.cast(y_pred, "int32")
        values = tf.cast(values, "float32")
        if sample_weight is not None:
            sample_weight = tf.cast(sample_weight, "float32")
            values = tf.multiply(values, sample_weight)
        self.true_positives.assign_add(tf.reduce_sum(values))

    def result(self):
        return self.true_positives

    def reset_states(self):
        # The state of the metric will be reset at the start of each epoch.
        self.true_positives.assign(0.0)


model = get_uncompiled_model()
model.compile(
    optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
    loss=keras.losses.SparseCategoricalCrossentropy(),
    metrics=[CategoricalTruePositives()],
)
model.fit(x_train, y_train, batch_size=64, epochs=3)
Epoch 1/3
782/782 [==============================] - 1s 2ms/step - loss: 0.3429 - categorical_true_positives: 45146.0000
Epoch 2/3
782/782 [==============================] - 1s 2ms/step - loss: 0.1560 - categorical_true_positives: 47637.0000
Epoch 3/3
782/782 [==============================] - 1s 2ms/step - loss: 0.1155 - categorical_true_positives: 48237.0000

<tensorflow.python.keras.callbacks.History at 0x7f755801bfd0>

Umgang mit Verlusten und Metriken, die nicht zur Standardsignatur passen

Die überwiegende Mehrheit der Verluste und Metriken kann aus y_true und y_pred berechnet werden, wobei y_pred eine Ausgabe Ihres Modells ist. Aber nicht alle von ihnen. Beispielsweise erfordert ein Regularisierungsverlust möglicherweise nur die Aktivierung einer Ebene (in diesem Fall gibt es keine Ziele), und diese Aktivierung ist möglicherweise keine Modellausgabe.

In solchen Fällen können Sie self.add_loss(loss_value) innerhalb der self.add_loss(loss_value) einer benutzerdefinierten Ebene aufrufen. Auf diese Weise hinzugefügte Verluste werden zum "Hauptverlust" während des Trainings addiert (derjenige, der an compile() ). Hier ist ein einfaches Beispiel, das die Regularisierung von Aktivitäten hinzufügt (beachten Sie, dass die Regularisierung von Aktivitäten in allen Keras-Ebenen integriert ist - diese Ebene dient nur dazu, ein konkretes Beispiel bereitzustellen):

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 [==============================] - 1s 2ms/step - loss: 2.4756

<tensorflow.python.keras.callbacks.History at 0x7f75501e1f98>

Sie können dasselbe für die Protokollierung von add_metric() mit 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 [==============================] - 1s 2ms/step - loss: 0.3493 - std_of_activation: 0.9813

<tensorflow.python.keras.callbacks.History at 0x7f75500321d0>

In der funktionalen API können Sie auch model.add_loss(loss_tensor) oder model.add_metric(metric_tensor, name, aggregation) .

Hier ist ein einfaches Beispiel:

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 [==============================] - 1s 2ms/step - loss: 2.5230 - std_of_activation: 0.0020

<tensorflow.python.keras.callbacks.History at 0x7f74ec71d828>

Beachten Sie, dass es beim add_loss() Verlusten über add_loss() möglich ist, compile() ohne Verlustfunktion aufzurufen, da das Modell bereits einen zu minimierenden Verlust aufweist.

Betrachten Sie die folgende LogisticEndpoint Ebene: Sie verwendet Ziele und Protokolle als Eingabe und verfolgt einen Crossentropieverlust über add_loss() . Es verfolgt auch die Klassifizierungsgenauigkeit über 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)

Sie können es in einem Modell mit zwei Eingaben (Eingabedaten und Zielen) verwenden, die ohne loss wie folgt kompiliert wurden:

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 1ms/step - loss: 0.9344 - binary_accuracy: 0.0000e+00

<tensorflow.python.keras.callbacks.History at 0x7f7558339f28>

Weitere Informationen zum Trainieren von Multi-Input-Modellen finden Sie im Abschnitt Übergeben von Daten an Multi-Input- und Multi-Output-Modelle .

Automatisches Auseinstellen eines Validierungs-Holdout-Sets

Im ersten End-to-End-Beispiel, das Sie gesehen haben, haben wir das Argument validation_data , um ein Tupel von NumPy-Arrays (x_val, y_val) an das Modell zu übergeben, um einen Validierungsverlust und Validierungsmetriken am Ende jeder Epoche zu bewerten.

Hier ist eine weitere Option: Mit dem Argument validation_split können Sie einen Teil Ihrer Trainingsdaten automatisch für die Validierung reservieren. Der Argumentwert stellt den Bruchteil der Daten dar, die für die Validierung reserviert werden sollen. Daher sollte er auf eine Zahl höher als 0 und niedriger als 1 gesetzt werden. validation_split=0.2 bedeutet beispielsweise "20% der Daten für die Validierung verwenden" und validation_split=0.6 bedeutet "60% der Daten zur Validierung verwenden".

Die Art und Weise, wie die Validierung berechnet wird, besteht darin, die letzten x% Abtastwerte der vom Anpassungsaufruf empfangenen Arrays vor dem Mischen zu entnehmen.

Beachten Sie, dass Sie validation_split beim Training mit NumPy-Daten verwenden können.

model = get_compiled_model()
model.fit(x_train, y_train, batch_size=64, validation_split=0.2, epochs=1)
625/625 [==============================] - 1s 2ms/step - loss: 0.3753 - sparse_categorical_accuracy: 0.8927 - val_loss: 0.2252 - val_sparse_categorical_accuracy: 0.9344

<tensorflow.python.keras.callbacks.History at 0x7f755826f160>

Schulung & Auswertung aus tf.data-Datensätzen

In den letzten Absätzen haben Sie gesehen, wie Sie mit Verlusten, Metriken und Optimierern umgehen, und Sie haben gesehen, wie Sie die Argumente validation_data und validation_split in fit verwenden, wenn Ihre Daten als NumPy-Arrays übergeben werden.

Schauen wir uns nun den Fall an, in dem Ihre Daten in Form eines tf.data.Dataset Objekts tf.data.Dataset .

Die tf.data API ist eine Reihe von Dienstprogrammen in TensorFlow 2.0, mit denen Daten schnell und skalierbar tf.data und vorverarbeitet werden können.

Für eine komplette Anleitung zum Erstellen von Datasets finden Sie in der tf.data Dokumentation .

Sie können eine Dataset Instanz direkt an die Methoden fit() , evaluate() und 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 2ms/step - loss: 0.3404 - sparse_categorical_accuracy: 0.9048
Epoch 2/3
782/782 [==============================] - 2s 2ms/step - loss: 0.1596 - sparse_categorical_accuracy: 0.9529
Epoch 3/3
782/782 [==============================] - 2s 2ms/step - loss: 0.1165 - sparse_categorical_accuracy: 0.9658
Evaluate
157/157 [==============================] - 0s 1ms/step - loss: 0.1147 - sparse_categorical_accuracy: 0.9659

{'loss': 0.11471886932849884,
 'sparse_categorical_accuracy': 0.9659000039100647}

Beachten Sie, dass der Datensatz am Ende jeder Epoche zurückgesetzt wird, damit er für die nächste Epoche wiederverwendet werden kann.

Wenn Sie das Training nur für eine bestimmte Anzahl von Stapeln aus diesem steps_per_epoch , können Sie das Argument steps_per_epoch , das angibt, wie viele Trainingsschritte das Modell mit diesem steps_per_epoch ausführen soll, bevor Sie mit der nächsten Epoche steps_per_epoch .

Wenn Sie dies tun, wird der Datensatz nicht am Ende jeder Epoche zurückgesetzt, sondern wir zeichnen einfach die nächsten Stapel weiter. Dem Datensatz gehen möglicherweise die Daten aus (es sei denn, es handelt sich um einen Datensatz mit Endlosschleifen).

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 [==============================] - 0s 2ms/step - loss: 0.8448 - sparse_categorical_accuracy: 0.7734
Epoch 2/3
100/100 [==============================] - 0s 2ms/step - loss: 0.3912 - sparse_categorical_accuracy: 0.8922
Epoch 3/3
100/100 [==============================] - 0s 2ms/step - loss: 0.3399 - sparse_categorical_accuracy: 0.9011

<tensorflow.python.keras.callbacks.History at 0x7f74ec5cf7f0>

Verwenden eines Validierungsdatensatzes

Sie können eine Dataset Instanz als validation_data Argument in 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 [==============================] - 2s 2ms/step - loss: 0.3384 - sparse_categorical_accuracy: 0.9032 - val_loss: 0.1752 - val_sparse_categorical_accuracy: 0.9518

<tensorflow.python.keras.callbacks.History at 0x7f74ec4d2ba8>

Am Ende jeder Epoche durchläuft das Modell den Validierungsdatensatz und berechnet die Validierungsverlust- und Validierungsmetriken.

Wenn Sie die Validierung nur für eine bestimmte Anzahl von Stapeln aus diesem Dataset ausführen möchten, können Sie das Argument validation_steps , das angibt, wie viele Validierungsschritte das Modell mit dem Validierungsdatensatz ausführen soll, bevor die Validierung unterbrochen und mit der nächsten Epoche fortgefahren wird:

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 [==============================] - 2s 2ms/step - loss: 0.3503 - sparse_categorical_accuracy: 0.9021 - val_loss: 0.3226 - val_sparse_categorical_accuracy: 0.9156

<tensorflow.python.keras.callbacks.History at 0x7f74ec4caa58>

Beachten Sie, dass der Validierungsdatensatz nach jeder Verwendung zurückgesetzt wird (sodass Sie von Epoche zu Epoche immer dieselben Proben bewerten).

Das Argument validation_split (Generieren eines Holdout-Sets aus den Trainingsdaten) wird beim Training aus Dataset Objekten nicht unterstützt, da für diese Funktion die Indizierung der Stichproben der Datasets erforderlich ist, was mit der Dataset API im Allgemeinen nicht möglich ist.

Andere Eingabeformate werden unterstützt

Neben NumPy-Arrays, eifrigen Tensoren und TensorFlow- Datasets ist es möglich, ein Keras-Modell mithilfe von Pandas-Datenrahmen oder von Python-Generatoren zu trainieren, die Stapel von Daten und Beschriftungen liefern.

Insbesondere bietet die Klasse keras.utils.Sequence eine einfache Schnittstelle zum Erstellen von Python-Datengeneratoren, die für keras.utils.Sequence sind und gemischt werden können.

Im Allgemeinen empfehlen wir die Verwendung von:

  • NumPy-Eingabedaten, wenn Ihre Daten klein sind und in den Speicher passen
  • Dataset , wenn Sie über große Dataset verfügen und verteiltes Training durchführen müssen
  • Sequence , wenn Sie über große Datenmengen verfügen und viele benutzerdefinierte Python-seitige Verarbeitungen durchführen müssen, die in TensorFlow nicht möglich sind (z. B. wenn Sie zum Laden oder Vorverarbeiten von Daten auf externe Bibliotheken angewiesen sind).

Verwenden eines keras.utils.Sequence Objekts als Eingabe

keras.utils.Sequence ist ein Dienstprogramm, das Sie in Unterklassen unterteilen können, um einen Python-Generator mit zwei wichtigen Eigenschaften zu erhalten:

  • Es funktioniert gut mit Multiprocessing.
  • Es kann gemischt werden (z. B. beim Übergeben von shuffle=True in fit() ).

Eine Sequence muss zwei Methoden implementieren:

  • __getitem__
  • __len__

Die Methode __getitem__ sollte einen vollständigen Stapel zurückgeben. Wenn Sie Ihr Dataset zwischen Epochen ändern möchten, können Sie on_epoch_end implementieren.

Hier ist ein kurzes Beispiel:

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)

Verwenden der Stichprobengewichtung und der Klassengewichtung

Mit den Standardeinstellungen wird das Gewicht einer Probe durch ihre Häufigkeit im Datensatz bestimmt. Es gibt zwei Methoden, um die Daten unabhängig von der Probenfrequenz zu gewichten:

  • Klassengewichte
  • Probengewichte

Klassengewichte

Dies wird durch einen Wörterbuch zum vorbei class_weight Argumente Model.fit() . Dieses Wörterbuch ordnet Klassenindizes dem Gewicht zu, das für Stichproben dieser Klasse verwendet werden soll.

Dies kann verwendet werden, um Klassen ohne erneutes Abtasten auszugleichen oder um ein Modell zu trainieren, das einer bestimmten Klasse mehr Bedeutung beimisst.

Wenn beispielsweise die Klasse "0" in Ihren Daten halb so Model.fit(..., class_weight={0: 1., 1: 0.5}) ist wie die Klasse "1", können Sie Model.fit(..., class_weight={0: 1., 1: 0.5}) .

Hier ist ein NumPy-Beispiel, in dem wir Klassengewichte oder Stichprobengewichte verwenden, um der korrekten Klassifizierung der Klasse 5 (die die Ziffer "5" im MNIST-Datensatz ist) mehr Bedeutung zu verleihen.

import numpy as np

class_weight = {
    0: 1.0,
    1: 1.0,
    2: 1.0,
    3: 1.0,
    4: 1.0,
    # Set weight "2" for class "5",
    # making this class 2x more important
    5: 2.0,
    6: 1.0,
    7: 1.0,
    8: 1.0,
    9: 1.0,
}

print("Fit with class weight")
model = get_compiled_model()
model.fit(x_train, y_train, class_weight=class_weight, batch_size=64, epochs=1)
Fit with class weight
782/782 [==============================] - 2s 2ms/step - loss: 0.3729 - sparse_categorical_accuracy: 0.9025

<tensorflow.python.keras.callbacks.History at 0x7f74ec265358>

Probengewichte

Für eine feinkörnige Kontrolle oder wenn Sie keinen Klassifikator erstellen, können Sie "Stichprobengewichte" verwenden.

  • Beim Training aus NumPy-Daten: sample_weight Argument Model.fit() an Model.fit() .
  • Beim Training mit tf.data oder einer anderen Art von Iterator: (input_batch, label_batch, sample_weight_batch) .

Ein Array "Probengewichte" ist ein Array von Zahlen, die angeben, wie viel Gewicht jede Probe in einer Charge bei der Berechnung des Gesamtverlusts haben soll. Es wird häufig bei unausgeglichenen Klassifizierungsproblemen verwendet (die Idee ist, selten gesehenen Klassen mehr Gewicht zu verleihen).

Wenn die verwendeten Gewichte Einsen und Nullen sind, kann das Array als Maske für die Verlustfunktion verwendet werden (wobei der Beitrag bestimmter Stichproben zum Gesamtverlust vollständig verworfen wird).

sample_weight = np.ones(shape=(len(y_train),))
sample_weight[y_train == 5] = 2.0

print("Fit with sample weight")
model = get_compiled_model()
model.fit(x_train, y_train, sample_weight=sample_weight, batch_size=64, epochs=1)
Fit with sample weight
782/782 [==============================] - 2s 2ms/step - loss: 0.3837 - sparse_categorical_accuracy: 0.8984

<tensorflow.python.keras.callbacks.History at 0x7f74ec11afd0>

Hier ist ein passendes Dataset :

sample_weight = np.ones(shape=(len(y_train),))
sample_weight[y_train == 5] = 2.0

# Create a Dataset that includes sample weights
# (3rd element in the return tuple).
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train, sample_weight))

# Shuffle and slice the dataset.
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)

model = get_compiled_model()
model.fit(train_dataset, epochs=1)
782/782 [==============================] - 2s 2ms/step - loss: 0.3792 - sparse_categorical_accuracy: 0.9030

<tensorflow.python.keras.callbacks.History at 0x7f74d47f2208>

Übergabe von Daten an Modelle mit mehreren Eingängen und Ausgängen

In den vorherigen Beispielen haben wir ein Modell mit einer einzelnen Eingabe (einem Tensor der Form (764,) ) und einer einzelnen Ausgabe (einem Vorhersage-Tensor der Form (10,) ) betrachtet. Aber was ist mit Modellen mit mehreren Ein- oder Ausgängen?

Stellen Sie sich das folgende Modell vor, das eine Bildeingabe der Form (32, 32, 3) (das ist (height, width, channels) ) und eine Zeitreiheneingabe der Form (None, 10) (das ist (timesteps, features) ) hat. Unser Modell wird zwei Ausgaben haben, die aus der Kombination dieser Eingaben berechnet werden: eine "Punktzahl" (der Form (1,) ) und eine Wahrscheinlichkeitsverteilung über fünf Klassen (der Form (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]
)

Lassen Sie uns dieses Modell zeichnen, damit Sie klar sehen können, was wir hier tun (beachten Sie, dass die im Diagramm gezeigten Formen Stapelformen sind und keine Formen pro Stichprobe).

keras.utils.plot_model(model, "multi_input_and_output_model.png", show_shapes=True)

png

Zur Kompilierungszeit können wir unterschiedliche Verluste für unterschiedliche Ausgaben angeben, indem wir die Verlustfunktionen als Liste übergeben:

model.compile(
    optimizer=keras.optimizers.RMSprop(1e-3),
    loss=[keras.losses.MeanSquaredError(), keras.losses.CategoricalCrossentropy()],
)

Wenn wir nur eine einzige Verlustfunktion an das Modell übergeben würden, würde dieselbe Verlustfunktion auf jede Ausgabe angewendet (was hier nicht angemessen ist).

Ebenso für Metriken:

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()],
    ],
)

Da wir unseren Ausgabeebenen Namen gegeben haben, können wir auch Verluste und Metriken pro Ausgabe über ein Diktat angeben:

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()],
    },
)

Wir empfehlen die Verwendung expliziter Namen und Diktate, wenn Sie mehr als 2 Ausgänge haben.

Es ist möglich, verschiedenen ausgabespezifischen Verlusten unterschiedliche Gewichte zuzuweisen (zum Beispiel möchten Sie in unserem Beispiel den "Score" -Verlust privilegieren, indem Sie 2x die Wichtigkeit des Klassenverlusts loss_weights ), indem Sie das Argument loss_weights :

model.compile(
    optimizer=keras.optimizers.RMSprop(1e-3),
    loss={
        "score_output": keras.losses.MeanSquaredError(),
        "class_output": keras.losses.CategoricalCrossentropy(),
    },
    metrics={
        "score_output": [
            keras.metrics.MeanAbsolutePercentageError(),
            keras.metrics.MeanAbsoluteError(),
        ],
        "class_output": [keras.metrics.CategoricalAccuracy()],
    },
    loss_weights={"score_output": 2.0, "class_output": 1.0},
)

Sie können sich auch dafür entscheiden, für bestimmte Ausgaben keinen Verlust zu berechnen, wenn diese Ausgaben für die Vorhersage, aber nicht für das Training bestimmt sind:

# 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()},
)

Das Übergeben von Daten an ein Multi-Input- oder Multi-Output-Modell in Fit funktioniert ähnlich wie das Festlegen einer Verlustfunktion beim Kompilieren: Sie können Listen von NumPy-Arrays übergeben (mit 1: 1-Zuordnung zu den Ausgaben, die eine Verlustfunktion erhalten haben) oder diktiert die Zuordnung von Ausgabenamen zu NumPy-Arrays .

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 [==============================] - 0s 6ms/step - loss: 20.0184 - score_output_loss: 0.5383 - class_output_loss: 19.4800
4/4 [==============================] - 0s 4ms/step - loss: 17.7266 - score_output_loss: 0.3122 - class_output_loss: 17.4145

<tensorflow.python.keras.callbacks.History at 0x7f755022feb8>

Hier ist der Anwendungsfall für den Dataset : Ähnlich wie bei NumPy-Arrays sollte der Dataset ein Tupel von Diktaten zurückgeben.

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 8ms/step - loss: 17.2156 - score_output_loss: 0.2522 - class_output_loss: 16.9634

<tensorflow.python.keras.callbacks.History at 0x7f75c56c1128>

Rückrufe verwenden

Rückrufe in Keras sind Objekte, die an verschiedenen Punkten während des Trainings aufgerufen werden (zu Beginn einer Epoche, am Ende eines Stapels, am Ende einer Epoche usw.) und die zum Implementieren von Verhaltensweisen verwendet werden können, wie z.

  • Validierung an verschiedenen Punkten während des Trainings (über die integrierte Validierung pro Epoche hinaus)
  • Überprüfen Sie das Modell in regelmäßigen Abständen oder wenn es einen bestimmten Genauigkeitsschwellenwert überschreitet
  • Das Ändern der Lernrate des Modells während des Trainings scheint ein Plateau zu erreichen
  • Die Feinabstimmung der obersten Schichten während des Trainings scheint ein Plateau zu sein
  • Senden von E-Mail- oder Sofortnachrichtenbenachrichtigungen, wenn das Training endet oder wenn ein bestimmter Leistungsschwellenwert überschritten wird
  • Etc.

Rückrufe können als Liste an Ihren Anruf übergeben werden, fit() zu 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 [==============================] - 1s 2ms/step - loss: 0.3816 - sparse_categorical_accuracy: 0.8913 - val_loss: 0.2325 - val_sparse_categorical_accuracy: 0.9304
Epoch 2/20
625/625 [==============================] - 1s 2ms/step - loss: 0.1773 - sparse_categorical_accuracy: 0.9477 - val_loss: 0.2088 - val_sparse_categorical_accuracy: 0.9343
Epoch 3/20
625/625 [==============================] - 1s 2ms/step - loss: 0.1293 - sparse_categorical_accuracy: 0.9606 - val_loss: 0.1515 - val_sparse_categorical_accuracy: 0.9568
Epoch 4/20
625/625 [==============================] - 1s 2ms/step - loss: 0.1009 - sparse_categorical_accuracy: 0.9700 - val_loss: 0.1376 - val_sparse_categorical_accuracy: 0.9607
Epoch 5/20
625/625 [==============================] - 1s 2ms/step - loss: 0.0821 - sparse_categorical_accuracy: 0.9747 - val_loss: 0.1533 - val_sparse_categorical_accuracy: 0.9545
Epoch 6/20
625/625 [==============================] - 1s 2ms/step - loss: 0.0704 - sparse_categorical_accuracy: 0.9794 - val_loss: 0.1319 - val_sparse_categorical_accuracy: 0.9616
Epoch 00006: early stopping

<tensorflow.python.keras.callbacks.History at 0x7f74d46abdd8>

Viele integrierte Rückrufe sind verfügbar

  • ModelCheckpoint : Speichern Sie das Modell regelmäßig.
  • EarlyStopping : EarlyStopping Sie das Training, wenn das Training die Validierungsmetriken nicht mehr verbessert.
  • TensorBoard : Schreiben TensorBoard regelmäßig Modellprotokolle, die in TensorBoard visualisiert werden können (weitere Details im Abschnitt "Visualisierung").
  • CSVLogger : CSVLogger Verlust- und CSVLogger in eine CSV-Datei.
  • etc.

Die vollständige Liste finden Sie in der Dokumentation zu Rückrufen .

Schreiben Sie Ihren eigenen Rückruf

Sie können einen benutzerdefinierten Rückruf erstellen, indem Sie die Basisklasse keras.callbacks.Callback . Ein Rückruf hat über die Klasseneigenschaft self.model Zugriff auf das zugehörige Modell.

Lesen Sie unbedingt die vollständige Anleitung zum Schreiben von benutzerdefinierten Rückrufen .

Hier ist ein einfaches Beispiel zum Speichern einer Liste von Verlustwerten pro Charge während des Trainings:

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"))

Checkpointing-Modelle

Wenn Sie ein Modell mit relativ großen Datenmengen trainieren, ist es wichtig, die Prüfpunkte Ihres Modells in regelmäßigen Abständen zu speichern.

Der einfachste Weg, dies zu erreichen, ist der ModelCheckpoint Rückruf:

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
608/625 [============================>.] - ETA: 0s - loss: 0.3797 - sparse_categorical_accuracy: 0.8940
Epoch 00001: val_loss improved from inf to 0.23986, saving model to mymodel_1
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/training/tracking/tracking.py:111: Model.state_updates (from tensorflow.python.keras.engine.training) is deprecated and will be removed in a future version.
Instructions for updating:
This property should not be used in TensorFlow 2.0, as updates are applied automatically.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/training/tracking/tracking.py:111: Layer.updates (from tensorflow.python.keras.engine.base_layer) is deprecated and will be removed in a future version.
Instructions for updating:
This property should not be used in TensorFlow 2.0, as updates are applied automatically.
INFO:tensorflow:Assets written to: mymodel_1/assets
625/625 [==============================] - 2s 3ms/step - loss: 0.3765 - sparse_categorical_accuracy: 0.8949 - val_loss: 0.2399 - val_sparse_categorical_accuracy: 0.9276
Epoch 2/2
606/625 [============================>.] - ETA: 0s - loss: 0.1758 - sparse_categorical_accuracy: 0.9474
Epoch 00002: val_loss improved from 0.23986 to 0.19765, saving model to mymodel_2
INFO:tensorflow:Assets written to: mymodel_2/assets
625/625 [==============================] - 2s 3ms/step - loss: 0.1751 - sparse_categorical_accuracy: 0.9477 - val_loss: 0.1976 - val_sparse_categorical_accuracy: 0.9409

<tensorflow.python.keras.callbacks.History at 0x7f7550171f28>

Der ModelCheckpoint Rückruf kann verwendet werden, um Fehlertoleranz zu implementieren: Die Möglichkeit, das Training ab dem zuletzt gespeicherten Status des Modells neu zu starten, falls das Training zufällig unterbrochen wird. Hier ist ein einfaches Beispiel:

import os

# Prepare a directory to store all the checkpoints.
checkpoint_dir = "./ckpt"
if not os.path.exists(checkpoint_dir):
    os.makedirs(checkpoint_dir)


def make_or_restore_model():
    # Either restore the latest model, or create a fresh one
    # if there is no checkpoint available.
    checkpoints = [checkpoint_dir + "/" + name for name in os.listdir(checkpoint_dir)]
    if checkpoints:
        latest_checkpoint = max(checkpoints, key=os.path.getctime)
        print("Restoring from", latest_checkpoint)
        return keras.models.load_model(latest_checkpoint)
    print("Creating a new model")
    return get_compiled_model()


model = make_or_restore_model()
callbacks = [
    # This callback saves a SavedModel every 100 batches.
    # We include the training loss in the saved model name.
    keras.callbacks.ModelCheckpoint(
        filepath=checkpoint_dir + "/ckpt-loss={loss:.2f}", save_freq=100
    )
]
model.fit(x_train, y_train, epochs=1, callbacks=callbacks)
Creating a new model
  94/1563 [>.............................] - ETA: 3s - loss: 0.9261 - sparse_categorical_accuracy: 0.7420INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.90/assets
 192/1563 [==>...........................] - ETA: 6s - loss: 0.6734 - sparse_categorical_accuracy: 0.8097INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.66/assets
 292/1563 [====>.........................] - ETA: 6s - loss: 0.5676 - sparse_categorical_accuracy: 0.8390INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.56/assets
 393/1563 [======>.......................] - ETA: 6s - loss: 0.5077 - sparse_categorical_accuracy: 0.8543INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.51/assets
 490/1563 [========>.....................] - ETA: 5s - loss: 0.4665 - sparse_categorical_accuracy: 0.8652INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.46/assets
 589/1563 [==========>...................] - ETA: 5s - loss: 0.4356 - sparse_categorical_accuracy: 0.8735INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.43/assets
 690/1563 [============>.................] - ETA: 4s - loss: 0.4077 - sparse_categorical_accuracy: 0.8813INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.41/assets
 791/1563 [==============>...............] - ETA: 4s - loss: 0.3883 - sparse_categorical_accuracy: 0.8873INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.39/assets
 892/1563 [================>.............] - ETA: 3s - loss: 0.3715 - sparse_categorical_accuracy: 0.8921INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.37/assets
 992/1563 [==================>...........] - ETA: 3s - loss: 0.3569 - sparse_categorical_accuracy: 0.8964INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.36/assets
1092/1563 [===================>..........] - ETA: 2s - loss: 0.3444 - sparse_categorical_accuracy: 0.8994INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.34/assets
1194/1563 [=====================>........] - ETA: 2s - loss: 0.3315 - sparse_categorical_accuracy: 0.9025INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.33/assets
1293/1563 [=======================>......] - ETA: 1s - loss: 0.3217 - sparse_categorical_accuracy: 0.9056INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.32/assets
1383/1563 [=========================>....] - ETA: 1s - loss: 0.3145 - sparse_categorical_accuracy: 0.9077INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.31/assets
1478/1563 [===========================>..] - ETA: 0s - loss: 0.3057 - sparse_categorical_accuracy: 0.9102INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.30/assets
1563/1563 [==============================] - 9s 6ms/step - loss: 0.2996 - sparse_categorical_accuracy: 0.9119

<tensorflow.python.keras.callbacks.History at 0x7f74ec20d668>

Sie rufen auch Ihren eigenen Rückruf zum Speichern und Wiederherstellen von Modellen an.

Eine vollständige Anleitung zum Serialisieren und Speichern finden Sie in der Anleitung zum Speichern und Serialisieren von Modellen .

Verwenden von Lernratenplänen

Ein gängiges Muster beim Training von Deep-Learning-Modellen besteht darin, das Lernen im Verlauf des Trainings schrittweise zu reduzieren. Dies ist allgemein als "Lernratenabfall" bekannt.

Der Zeitplan für den Lernabfall kann statisch (im Voraus festgelegt, in Abhängigkeit von der aktuellen Epoche oder dem aktuellen Batch-Index) oder dynamisch (entsprechend dem aktuellen Verhalten des Modells, insbesondere dem Validierungsverlust) sein.

Übergeben eines Zeitplans an einen Optimierer

Sie können einen Zeitplan für den statischen Lernratenabfall einfach verwenden, indem Sie ein Zeitplanobjekt als Argument für learning_rate in Ihrem Optimierer übergeben:

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)

Es stehen mehrere integrierte Zeitpläne zur Verfügung: ExponentialDecay , PiecewiseConstantDecay , PolynomialDecay und InverseTimeDecay .

Verwenden von Rückrufen zum Implementieren eines dynamischen Lernratenplans

Ein dynamischer Zeitplan für die Lernrate (z. B. Verringerung der Lernrate, wenn sich der Validierungsverlust nicht mehr verbessert) kann mit diesen Zeitplanobjekten nicht erreicht werden, da der Optimierer keinen Zugriff auf Validierungsmetriken hat.

Rückrufe haben jedoch Zugriff auf alle Metriken, einschließlich Validierungsmetriken! Sie können dieses Muster also erreichen, indem Sie einen Rückruf verwenden, der die aktuelle Lernrate im Optimierer ändert. Dies ist sogar als ReduceLROnPlateau Rückruf integriert.

Visualisierung von Verlusten und Metriken während des Trainings

Der beste Weg, um Ihr Modell während des Trainings im Auge zu behalten, ist die Verwendung von TensorBoard , einer browserbasierten Anwendung, die Sie lokal ausführen können und die Ihnen Folgendes bietet:

  • Live-Diagramme der Verluste und Metriken für Training und Bewertung
  • (optional) Visualisierungen der Histogramme Ihrer Ebenenaktivierungen
  • (optional) 3D-Visualisierungen der Einbettungsräume, die von Ihren Embedding gelernt wurden

Wenn Sie TensorFlow mit pip installiert haben, sollten Sie TensorBoard über die Befehlszeile starten können:

tensorboard --logdir=/full_path_to_your_logs

Verwenden des TensorBoard-Rückrufs

Der einfachste Weg, TensorBoard mit einem Keras-Modell und der Anpassungsmethode zu verwenden, ist der TensorBoard Rückruf.

Geben Sie im einfachsten Fall einfach an, wo der Rückruf Protokolle schreiben soll, und los geht's:

keras.callbacks.TensorBoard(
    log_dir="/full_path_to_your_logs",
    histogram_freq=0,  # How often to log histogram visualizations
    embeddings_freq=0,  # How often to log embedding visualizations
    update_freq="epoch",
)  # How often to write logs (default: once per epoch)
<tensorflow.python.keras.callbacks.TensorBoard at 0x7f74ec5179e8>

Weitere Informationen finden Sie in der Dokumentation zum TensorBoard Rückruf .