Ta strona została przetłumaczona przez Cloud Translation API.
Switch to English

Szkolenia i ewaluacja za pomocą wbudowanych metod

Zobacz na TensorFlow.org Uruchom w Google Colab Wyświetl źródło na GitHub Pobierz notatnik

Ustawiać

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

Wprowadzenie

Ten przewodnik obejmuje modele szkolenia, oceny i predykcji (wnioskowania) w przypadku korzystania z wbudowanych interfejsów API do uczenia i walidacji (takich jak model.fit() , model.evaluate() , model.predict() ).

Jeśli jesteś zainteresowany wykorzystaniem funkcji fit() podczas określania własnej funkcji kroku treningowego, zobacz przewodnik „Dostosowywanie tego, co dzieje się w fit() .

Jeśli jesteś zainteresowany pisaniem własnych pętli szkoleniowych i ocen od zera, zobacz przewodnik „Pisanie pętli szkoleniowej od zera” .

Ogólnie rzecz biorąc, niezależnie od tego, czy korzystasz z wbudowanych pętli, czy piszesz własne, szkolenie i ocena modeli działają dokładnie w ten sam sposób w przypadku każdego rodzaju modelu Keras - modele sekwencyjne, modele zbudowane za pomocą funkcjonalnego interfejsu API i modele napisane od podstaw za pośrednictwem podklasy modelu.

Ten przewodnik nie obejmuje szkoleń rozproszonych. W przypadku szkoleń rozproszonych zapoznaj się z naszym przewodnikiem po szkoleniach wieloprocesorowych i rozproszonych .

Omówienie interfejsu API: pierwszy kompleksowy przykład

Podczas przekazywania danych do wbudowanych pętli szkoleniowych modelu należy użyć tablic NumPy (jeśli dane są małe i tf.data Dataset w pamięci) lub obiektów tf.data Dataset . W następnych kilku akapitach użyjemy zbioru danych MNIST jako tablic NumPy, aby zademonstrować, jak używać optymalizatorów, strat i metryk.

Rozważmy następujący model (tutaj budujemy za pomocą funkcjonalnego interfejsu API, ale może to być również model sekwencyjny lub model podklasy):

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)

Oto jak wygląda typowy kompleksowy przepływ pracy, na który składają się:

  • Trening
  • Walidacja zestawu wstrzymanego wygenerowanego z oryginalnych danych uczących
  • Ocena na danych testowych

W tym przykładzie użyjemy danych MNIST.

(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]
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
11493376/11490434 [==============================] - 0s 0us/step

Określamy konfigurację treningu (optymalizator, strata, metryki):

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

Wywołujemy funkcję fit() , która wytrenuje model przez podzielenie danych na „partie” o rozmiarze „batch_size” i wielokrotne iterowanie po całym zestawie danych dla danej liczby „epok”.

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.3476 - sparse_categorical_accuracy: 0.9005 - val_loss: 0.1868 - val_sparse_categorical_accuracy: 0.9452
Epoch 2/2
782/782 [==============================] - 2s 2ms/step - loss: 0.1622 - sparse_categorical_accuracy: 0.9517 - val_loss: 0.1334 - val_sparse_categorical_accuracy: 0.9616

Zwrócony obiekt „history” zawiera zapis wartości strat i wartości metryki podczas uczenia:

history.history
{'loss': [0.34755897521972656, 0.16218683123588562],
 'sparse_categorical_accuracy': [0.9004799723625183, 0.9516800045967102],
 'val_loss': [0.18684418499469757, 0.13335685431957245],
 'val_sparse_categorical_accuracy': [0.9452000260353088, 0.9616000056266785]}

Oceniamy model na danych testowych za pomocą funkcji 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.1379 - sparse_categorical_accuracy: 0.9594
test loss, test acc: [0.13789668679237366, 0.9593999981880188]
Generate predictions for 3 samples
predictions shape: (3, 10)

Przyjrzyjmy się teraz szczegółowo każdej części tego przepływu pracy.

Metoda compile() : określanie straty, metryki i optymalizatora

Aby wytrenować model za pomocą fit() , musisz określić funkcję straty, optymalizator i opcjonalnie niektóre metryki do monitorowania.

Przekazujesz je do modelu jako argumenty do metody compile() :

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

Argument metrics powinien być listą - Twój model może mieć dowolną liczbę metryk.

Jeśli model ma wiele wyników, możesz określić różne straty i metryki dla każdego wyniku, a także modulować udział każdego wyniku w całkowitej utracie modelu. Więcej szczegółów na ten temat znajdziesz w rozdziale „Przekazywanie danych do modeli z wieloma wejściami i wieloma wyjściami” .

Pamiętaj, że jeśli jesteś zadowolony z ustawień domyślnych, w wielu przypadkach optymalizator, straty i metryki można określić za pomocą identyfikatorów ciągów jako skrótu:

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

W celu późniejszego ponownego wykorzystania umieśćmy definicję modelu i krok kompilacji w funkcjach; będziemy je nazywać kilkakrotnie w różnych przykładach w tym przewodniku.

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

Dostępnych jest wiele wbudowanych optymalizatorów, strat i metryk

Ogólnie rzecz biorąc, nie będziesz musiał tworzyć od podstaw własnych strat, wskaźników ani optymalizatorów, ponieważ to, czego potrzebujesz, jest już prawdopodobnie częścią interfejsu API Keras:

Optymalizatory:

  • SGD() (z momentum lub bez)
  • RMSprop()
  • Adam()
  • itp.

Straty:

  • MeanSquaredError()
  • KLDivergence()
  • CosineSimilarity()
  • itp.

Metryka:

  • AUC()
  • Precision()
  • Recall()
  • itp.

Straty niestandardowe

Istnieją dwa sposoby na zapewnienie niestandardowych strat za pomocą Keras. Pierwszy przykład tworzy funkcję, która akceptuje dane wejściowe y_true i y_pred . Poniższy przykład przedstawia funkcję straty, która oblicza średni kwadrat błędu między rzeczywistymi danymi a prognozami:

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

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

Jeśli potrzebujesz funkcji strat, która przyjmuje parametry obok y_true i y_pred , możesz tf.keras.losses.Loss klasę tf.keras.losses.Loss i zaimplementować następujące dwie metody:

  • __init__(self) : zaakceptuj parametry, które zostaną przekazane podczas wywołania funkcji utraty
  • call(self, y_true, y_pred) : użyj wartości docelowych (y_true) i prognoz modelu (y_pred), aby obliczyć stratę modelu

Załóżmy, że chcesz użyć błędu średniokwadratowego, ale z dodanym terminem, który zmniejszy motywację do wartości prognozy daleko od 0,5 (zakładamy, że cele kategorialne są zakodowane na gorąco i przyjmują wartości od 0 do 1). Stwarza to zachętę do tego, aby model nie był zbyt pewny siebie, co może pomóc zmniejszyć nadmierne dopasowanie (nie będziemy wiedzieć, czy zadziała, dopóki nie spróbujemy!).

Oto jak byś to zrobił:

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 1ms/step - loss: 0.0386

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

Dane niestandardowe

Jeśli potrzebujesz metryki, która nie jest częścią interfejsu API, możesz łatwo utworzyć metryki niestandardowe, tworząc podklasy klasy tf.keras.metrics.Metric . Będziesz musiał zaimplementować 4 metody:

  • __init__(self) , w którym utworzysz zmienne stanu dla swojej metryki.
  • update_state(self, y_true, y_pred, sample_weight=None) , który wykorzystuje wartości docelowe y_true i przewidywania modelu y_pred do aktualizacji zmiennych stanu.
  • result(self) , który używa zmiennych stanu do obliczenia ostatecznych wyników.
  • reset_states(self) , który ponownie inicjuje stan metryki.

Aktualizacja stanu i obliczanie wyników są przechowywane oddzielnie (odpowiednio w update_state() i result() , ponieważ w niektórych przypadkach obliczenia wyników mogą być bardzo kosztowne i byłyby wykonywane tylko okresowo.

Oto prosty przykład pokazujący, jak zaimplementować metrykę CategoricalTruePositives , która zlicza, ile próbek zostało poprawnie sklasyfikowanych jako należące do danej klasy:

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.3406 - categorical_true_positives: 45130.0000
Epoch 2/3
782/782 [==============================] - 1s 2ms/step - loss: 0.1591 - categorical_true_positives: 47607.0000
Epoch 3/3
782/782 [==============================] - 2s 2ms/step - loss: 0.1140 - categorical_true_positives: 48302.0000

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

Obsługa strat i metryk, które nie pasują do standardowego podpisu

Zdecydowaną większość strat i metryk można obliczyć na podstawie y_true i y_pred , gdzie y_pred jest wynikiem twojego modelu. Ale nie wszyscy. Na przykład utrata regularyzacji może wymagać jedynie aktywacji warstwy (w tym przypadku nie ma celów), a ta aktywacja może nie być wynikiem modelowym.

W takich przypadkach możesz wywołać self.add_loss(loss_value) z wnętrza metody wywołania warstwy niestandardowej. Straty dodane w ten sposób są dodawane do „głównej” straty podczas treningu (tej, która została przekazana do compile() ). Oto prosty przykład, który dodaje regularyzację działań (zwróć uwagę, że regularyzacja działań jest wbudowana we wszystkie warstwy Keras - ta warstwa ma na celu zapewnienie konkretnego przykładu):

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

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

Możesz zrobić to samo w przypadku rejestrowania wartości metryk, używając 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.3414 - std_of_activation: 1.0120

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

W funkcjonalnym interfejsie API można również wywołać model.add_loss(loss_tensor) lub model.add_metric(metric_tensor, name, aggregation) .

Oto prosty przykład:

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.5604 - std_of_activation: 0.0023

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

Zauważ, że kiedy przekazujesz straty za pomocą add_loss() , staje się możliwe wywołanie compile() bez funkcji strat, ponieważ model ma już straty do zminimalizowania.

Rozważmy następującą warstwę LogisticEndpoint : przyjmuje jako dane wejściowe cele i logi i śledzi stratę add_loss() za pomocą add_loss() . Śledzi również dokładność klasyfikacji za pomocą 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)

Możesz go użyć w modelu z dwoma wejściami (danymi wejściowymi i celami), skompilowanymi bez argumentu loss , na przykład:

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.9677 - binary_accuracy: 0.0000e+00

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

Aby uzyskać więcej informacji na temat uczenia modeli z wieloma wejściami, zobacz sekcję Przekazywanie danych do modeli z wieloma wejściami i wieloma wyjściami .

Automatyczne wyodrębnianie zestawu wstrzymania weryfikacji

W pierwszym (x_val, y_val) przykładzie typu end-to-end użyliśmy argumentu validation_data aby przekazać krotkę tablic NumPy (x_val, y_val) do modelu w celu oszacowania utraty walidacji i metryk walidacji na końcu każdej epoki.

Oto inna opcja: argument validation_split umożliwia automatyczne zarezerwowanie części danych szkoleniowych do walidacji. Wartość argumentu reprezentuje ułamek danych, które mają być zarezerwowane do walidacji, więc powinna być ustawiona na liczbę większą niż 0 i mniejszą niż 1. Na przykład validation_split=0.2 oznacza „użyj 20% danych do walidacji”, a validation_split=0.6 oznacza "użyj 60% danych do walidacji".

Sposób obliczania walidacji polega na pobraniu ostatnich x% próbek tablic odebranych przez wywołanie fit, przed jakimkolwiek tasowaniem.

Pamiętaj, że możesz używać validation_split tylko podczas uczenia z danymi NumPy.

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.3745 - sparse_categorical_accuracy: 0.8950 - val_loss: 0.2279 - val_sparse_categorical_accuracy: 0.9333

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

Szkolenie i ocena z tf.data Datasets

W kilku ostatnich akapitach widziałeś, jak radzić sobie ze stratami, metrykami i optymalizatorami, i widziałeś, jak używać argumentów validation_data i validation_split w dopasowaniu, gdy dane są przekazywane jako tablice NumPy.

Przyjrzyjmy się teraz przypadkowi, w którym Twoje dane są w postaci obiektu tf.data.Dataset .

tf.data API tf.data to zestaw narzędzi w TensorFlow 2.0 do ładowania i wstępnego przetwarzania danych w sposób szybki i skalowalny.

Pełny przewodnik dotyczący tworzenia Datasets znajduje się w dokumentacji tf.data .

Instancję Dataset można przekazać bezpośrednio do metod fit() , evaluate() i 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.3373 - sparse_categorical_accuracy: 0.9045
Epoch 2/3
782/782 [==============================] - 2s 2ms/step - loss: 0.1582 - sparse_categorical_accuracy: 0.9528
Epoch 3/3
782/782 [==============================] - 2s 2ms/step - loss: 0.1146 - sparse_categorical_accuracy: 0.9658
Evaluate
157/157 [==============================] - 0s 1ms/step - loss: 0.1300 - sparse_categorical_accuracy: 0.9601

{'loss': 0.12998636066913605, 'sparse_categorical_accuracy': 0.960099995136261}

Zwróć uwagę, że zestaw danych jest resetowany na koniec każdej epoki, więc można go ponownie wykorzystać w następnej epoce.

Jeśli chcesz uruchomić uczenie tylko na określonej liczbie partii z tego zestawu danych, możesz przekazać argument steps_per_epoch , który określa, ile kroków szkoleniowych model powinien uruchomić przy użyciu tego zestawu danych przed przejściem do następnej epoki.

Jeśli to zrobisz, zestaw danych nie zostanie zresetowany na koniec każdej epoki, zamiast tego po prostu rysujemy kolejne partie. W zbiorze danych w końcu zabraknie danych (chyba że jest to zbiór danych o nieskończonej pętli).

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.7669 - sparse_categorical_accuracy: 0.8027
Epoch 2/3
100/100 [==============================] - 0s 2ms/step - loss: 0.3694 - sparse_categorical_accuracy: 0.8947
Epoch 3/3
100/100 [==============================] - 0s 2ms/step - loss: 0.3178 - sparse_categorical_accuracy: 0.9080

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

Korzystanie ze zbioru danych do walidacji

Możesz przekazać instancję Dataset jako argument validation_data w 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.3401 - sparse_categorical_accuracy: 0.9047 - val_loss: 0.1726 - val_sparse_categorical_accuracy: 0.9521

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

Pod koniec każdej epoki model dokona iteracji po zbiorze danych walidacyjnych i obliczy utratę walidacji i metryki walidacji.

Jeśli chcesz uruchomić walidację tylko na określonej liczbie partii z tego zestawu danych, możesz przekazać argument validation_steps , który określa, ile kroków walidacji model powinien uruchomić z zestawem danych walidacji, zanim przerwie walidację i przejdzie do następnej epoki:

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.3402 - sparse_categorical_accuracy: 0.9024 - val_loss: 0.3108 - val_sparse_categorical_accuracy: 0.9250

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

Zwróć uwagę, że zestaw danych do walidacji zostanie zresetowany po każdym użyciu (dzięki czemu będziesz zawsze oceniać te same próbki od epoki do epoki).

Argument validation_split (generowanie zestawu wstrzymanego z danych uczących) nie jest obsługiwany podczas uczenia z obiektów Dataset , ponieważ ta funkcja wymaga możliwości indeksowania próbek zestawów danych, co jest ogólnie niemożliwe w przypadku interfejsu API Dataset .

Obsługiwane są inne formaty wejściowe

Oprócz tablic NumPy, chętnych tensorów i Datasets TensorFlow, możliwe jest trenowanie modelu Keras przy użyciu ramek danych Pandas lub generatorów Pythona, które generują partie danych i etykiet.

W szczególności klasa keras.utils.Sequence oferuje prosty interfejs do tworzenia generatorów danych Pythona, które obsługują wieloprocesorowość i mogą być tasowane.

Ogólnie zalecamy używanie:

  • NumPy wprowadź dane, jeśli dane są małe i mieszczą się w pamięci
  • Obiekty Dataset jeśli masz duże zestawy danych i musisz przeprowadzić rozproszone szkolenie
  • Sequence obiekty, jeśli masz duże zbiory danych i musisz wykonać wiele niestandardowego przetwarzania po stronie Pythona, którego nie można wykonać w TensorFlow (np. Jeśli polegasz na zewnętrznych bibliotekach do ładowania lub przetwarzania wstępnego danych).

Użycie obiektu keras.utils.Sequence jako danych wejściowych

keras.utils.Sequence to narzędzie, które można keras.utils.Sequence , aby uzyskać generator keras.utils.Sequence Python z dwiema ważnymi właściwościami:

  • Działa dobrze w przypadku przetwarzania wieloprocesowego.
  • Można go przetasować (np. Przy podawaniu shuffle=True in fit() ).

Sequence musi implementować dwie metody:

  • __getitem__
  • __len__

Metoda __getitem__ powinna zwrócić całą wiązkę. Jeśli chcesz zmodyfikować swój zestaw danych między epokami, możesz zaimplementować on_epoch_end .

Oto krótki przykład:

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)

Korzystanie z ważenia próbek i ważenia klas

Przy ustawieniach domyślnych o wadze próbki decyduje częstotliwość w zbiorze danych. Istnieją dwie metody ważenia danych, niezależnie od częstotliwości próbkowania:

  • Wagi klas
  • Przykładowe wagi

Wagi klas

Jest to ustawiane przez przekazanie słownika do argumentu class_weight do Model.fit() . Ten słownik odwzorowuje indeksy klas na wagę, która powinna być używana dla próbek należących do tej klasy.

Może to służyć do równoważenia klas bez ponownego próbkowania lub do trenowania modelu, który nadaje większe znaczenie określonej klasie.

Na przykład, jeśli klasa „0” jest w połowie reprezentowana jako klasa „1” w Twoich danych, możesz użyć Model.fit(..., class_weight={0: 1., 1: 0.5}) .

Oto przykład NumPy, w którym używamy wag klas lub wag próbek, aby nadać większą wagę poprawnej klasyfikacji klasy # 5 (która jest cyfrą „5” w zbiorze danych 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 [==============================] - 1s 2ms/step - loss: 0.3811 - sparse_categorical_accuracy: 0.8999

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

Przykładowe wagi

Aby uzyskać precyzyjną kontrolę lub jeśli nie tworzysz klasyfikatora, możesz użyć „wag próbki”.

  • Podczas uczenia z danych NumPy: Przekaż argument sample_weight do Model.fit() .
  • Podczas uczenia z tf.data lub innego rodzaju iteratora: (input_batch, label_batch, sample_weight_batch) Yield (input_batch, label_batch, sample_weight_batch) .

Tablica „wag próbek” to tablica liczb, które określają, jaką wagę każda próbka w partii powinna mieć przy obliczaniu całkowitej straty. Jest powszechnie stosowany w niezrównoważonych problemach klasyfikacyjnych (chodzi o nadanie większej wagi rzadko spotykanym klasom).

Gdy używane wagi to jedynki i zera, tablica może służyć jako maska funkcji straty (całkowicie odrzucając udział niektórych próbek w całkowitej utracie).

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

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

Oto pasujący przykład 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.3776 - sparse_categorical_accuracy: 0.9005

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

Przekazywanie danych do modeli z wieloma wejściami i wieloma wyjściami

W poprzednich przykładach rozważaliśmy model z jednym wejściem (tensor kształtu (764,) ) i jednym wyjściem (tensor predykcji kształtu (10,) ). Ale co z modelami, które mają wiele wejść lub wyjść?

Rozważmy następujący model, który zawiera dane wejściowe obrazu o kształcie (32, 32, 3) (to jest (height, width, channels) ) i dane wejściowe kształtu z serii timeeries (None, 10) (to jest (timesteps, features) ). Nasz model będzie miał dwa wyniki obliczone z kombinacji tych danych wejściowych: „wynik” (o kształcie (1,) ) i rozkład prawdopodobieństwa na pięć klas (o kształcie (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]
)

Narysujmy ten model, abyś mógł wyraźnie zobaczyć, co tutaj robimy (zwróć uwagę, że kształty pokazane na wykresie są kształtami wsadowymi, a nie kształtami na próbkę).

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

png

W czasie kompilacji możemy określić różne straty dla różnych wyjść, przekazując funkcje strat jako listę:

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

Gdybyśmy przekazali do modelu tylko jedną funkcję straty, ta sama funkcja straty byłaby zastosowana do każdego wyniku (co nie jest tutaj właściwe).

Podobnie w przypadku danych:

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

Ponieważ nadaliśmy nazwy naszym warstwom wyjściowym, możemy również określić straty na wyjście i metryki za pomocą dyktowania:

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

Jeśli masz więcej niż 2 wyjścia, zalecamy używanie jawnych nazw i nakazów.

Możliwe jest przypisanie różnych wag różnym stratom specyficznym dla produkcji (na przykład można chcieć uprzywilejować stratę „wyniku” w naszym przykładzie, nadając 2x wagę straty klasy), używając argumentu 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},
)

Możesz również zdecydować, aby nie obliczać strat dla niektórych wyników, jeśli te dane wyjściowe były przeznaczone do przewidywania, ale nie do uczenia:

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

Przekazywanie danych do modelu z wieloma wejściami lub wieloma wyjściami w dopasowaniu działa w podobny sposób, jak określanie funkcji strat w kompilacji: możesz przekazać listy tablic NumPy (z mapowaniem 1: 1 do wyjść, które otrzymały funkcję utraty) lub dicts mapuje nazwy wyjściowe na tablice 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 [==============================] - 0s 6ms/step - loss: 11.1192 - score_output_loss: 0.5547 - class_output_loss: 10.5645
4/4 [==============================] - 0s 4ms/step - loss: 9.9594 - score_output_loss: 0.4204 - class_output_loss: 9.5390

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

Oto przypadek użycia Dataset : podobnie jak w przypadku tablic NumPy, Dataset powinien zwrócić krotkę dykt.

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: 9.7058 - score_output_loss: 0.3508 - class_output_loss: 9.3550

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

Korzystanie z wywołań zwrotnych

Callbacki w Keras to obiekty wywoływane w różnych punktach podczas uczenia (na początku epoki, na końcu partii, na końcu epoki itp.), Które można wykorzystać do realizacji takich zachowań, jak:

  • Przeprowadzanie walidacji w różnych punktach podczas szkolenia (poza wbudowaną walidacją na epokę)
  • Sprawdzanie modelu w regularnych odstępach czasu lub gdy przekracza on określony próg dokładności
  • Zmiana współczynnika uczenia się modelu, gdy szkolenie wydaje się być plateau
  • Dostrajanie górnych warstw podczas treningu wydaje się być stabilne
  • Wysyłanie powiadomień e-mail lub wiadomości błyskawicznych po zakończeniu szkolenia lub przekroczeniu określonego progu wydajności
  • Itp.

Wywołania zwrotne można przekazać jako listę do wywołania 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.3744 - sparse_categorical_accuracy: 0.8949 - val_loss: 0.2301 - val_sparse_categorical_accuracy: 0.9336
Epoch 2/20
625/625 [==============================] - 1s 2ms/step - loss: 0.1762 - sparse_categorical_accuracy: 0.9485 - val_loss: 0.1818 - val_sparse_categorical_accuracy: 0.9463
Epoch 3/20
625/625 [==============================] - 1s 2ms/step - loss: 0.1292 - sparse_categorical_accuracy: 0.9616 - val_loss: 0.1620 - val_sparse_categorical_accuracy: 0.9524
Epoch 4/20
625/625 [==============================] - 1s 2ms/step - loss: 0.1014 - sparse_categorical_accuracy: 0.9699 - val_loss: 0.1486 - val_sparse_categorical_accuracy: 0.9566
Epoch 5/20
625/625 [==============================] - 1s 2ms/step - loss: 0.0847 - sparse_categorical_accuracy: 0.9751 - val_loss: 0.1612 - val_sparse_categorical_accuracy: 0.9533
Epoch 6/20
625/625 [==============================] - 1s 2ms/step - loss: 0.0699 - sparse_categorical_accuracy: 0.9788 - val_loss: 0.1447 - val_sparse_categorical_accuracy: 0.9600
Epoch 00006: early stopping

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

Dostępnych jest wiele wbudowanych wywołań zwrotnych

  • ModelCheckpoint : Okresowo zapisuj model.
  • EarlyStopping : Zatrzymaj trenowanie, gdy szkolenie nie poprawia już wskaźników walidacji.
  • TensorBoard : okresowo zapisuj dzienniki modeli, które można wizualizować w TensorBoard (więcej szczegółów w sekcji „Wizualizacja”).
  • CSVLogger : przesyła dane dotyczące strat i metryk do pliku CSV.
  • itp.

Pełną listę znajdziesz w dokumentacji callbacków .

Pisanie własnego oddzwonienia

Możesz utworzyć niestandardowe wywołanie zwrotne, rozszerzając klasę bazową keras.callbacks.Callback . self.model zwrotne ma dostęp do skojarzonego z nim modelu za pośrednictwem właściwości klasy self.model .

Przeczytaj pełny przewodnik dotyczący pisania niestandardowych wywołań zwrotnych .

Oto prosty przykład zapisywania listy wartości strat na partię podczas uczenia:

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

Modele kontrolne

Kiedy trenujesz model na stosunkowo dużych zestawach danych, ważne jest, aby zapisywać punkty kontrolne modelu w częstych odstępach czasu.

Najłatwiej to osiągnąć za pomocą wywołania zwrotnego ModelCheckpoint :

model = get_compiled_model()

callbacks = [
    keras.callbacks.ModelCheckpoint(
        # Path where to save the model
        # The two parameters below mean that we will overwrite
        # the current checkpoint if and only if
        # the `val_loss` score has improved.
        # The saved model name will include the current epoch.
        filepath="mymodel_{epoch}",
        save_best_only=True,  # Only save a model if `val_loss` has improved.
        monitor="val_loss",
        verbose=1,
    )
]
model.fit(
    x_train, y_train, epochs=2, batch_size=64, callbacks=callbacks, validation_split=0.2
)
Epoch 1/2
617/625 [============================>.] - ETA: 0s - loss: 0.3784 - sparse_categorical_accuracy: 0.8940
Epoch 00001: val_loss improved from inf to 0.22038, 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.3766 - sparse_categorical_accuracy: 0.8946 - val_loss: 0.2204 - val_sparse_categorical_accuracy: 0.9363
Epoch 2/2
595/625 [===========================>..] - ETA: 0s - loss: 0.1721 - sparse_categorical_accuracy: 0.9498
Epoch 00002: val_loss improved from 0.22038 to 0.18707, saving model to mymodel_2
INFO:tensorflow:Assets written to: mymodel_2/assets
625/625 [==============================] - 2s 3ms/step - loss: 0.1708 - sparse_categorical_accuracy: 0.9501 - val_loss: 0.1871 - val_sparse_categorical_accuracy: 0.9453

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

ModelCheckpoint zwrotne ModelCheckpoint może służyć do implementacji odporności na błędy: możliwość ponownego uruchomienia uczenia od ostatniego zapisanego stanu modelu w przypadku losowego przerwania uczenia. Oto podstawowy przykład:

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
  83/1563 [>.............................] - ETA: 2s - loss: 1.0490 - sparse_categorical_accuracy: 0.7165INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.97/assets
 185/1563 [==>...........................] - ETA: 5s - loss: 0.7407 - sparse_categorical_accuracy: 0.7959INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.72/assets
 286/1563 [====>.........................] - ETA: 5s - loss: 0.6176 - sparse_categorical_accuracy: 0.8253INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.60/assets
 385/1563 [======>.......................] - ETA: 5s - loss: 0.5432 - sparse_categorical_accuracy: 0.8475INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.53/assets
 485/1563 [========>.....................] - ETA: 5s - loss: 0.4909 - sparse_categorical_accuracy: 0.8607INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.48/assets
 585/1563 [==========>...................] - ETA: 4s - loss: 0.4531 - sparse_categorical_accuracy: 0.8713INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.45/assets
 684/1563 [============>.................] - ETA: 4s - loss: 0.4262 - sparse_categorical_accuracy: 0.8788INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.42/assets
 784/1563 [==============>...............] - ETA: 3s - loss: 0.4066 - sparse_categorical_accuracy: 0.8845INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.40/assets
 882/1563 [===============>..............] - ETA: 3s - loss: 0.3863 - sparse_categorical_accuracy: 0.8902INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.38/assets
 985/1563 [=================>............] - ETA: 2s - loss: 0.3682 - sparse_categorical_accuracy: 0.8954INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.37/assets
1084/1563 [===================>..........] - ETA: 2s - loss: 0.3532 - sparse_categorical_accuracy: 0.8993INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.35/assets
1185/1563 [=====================>........] - ETA: 1s - loss: 0.3407 - sparse_categorical_accuracy: 0.9028INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.34/assets
1284/1563 [=======================>......] - ETA: 1s - loss: 0.3287 - sparse_categorical_accuracy: 0.9063INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.33/assets
1385/1563 [=========================>....] - ETA: 0s - loss: 0.3171 - sparse_categorical_accuracy: 0.9095INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.32/assets
1485/1563 [===========================>..] - ETA: 0s - loss: 0.3090 - sparse_categorical_accuracy: 0.9116INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.31/assets
1563/1563 [==============================] - 8s 5ms/step - loss: 0.3018 - sparse_categorical_accuracy: 0.9136

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

Dzwonisz również napisz własne wywołanie zwrotne do zapisywania i przywracania modeli.

Aby uzyskać pełny przewodnik po serializacji i zapisywaniu, zobacz przewodnik dotyczący zapisywania i serializacji modeli .

Korzystanie z harmonogramów kursów nauki

Powszechnym wzorcem podczas trenowania modeli głębokiego uczenia się jest stopniowe ograniczanie uczenia się w miarę postępu szkolenia. Jest to ogólnie znane jako „spadek szybkości uczenia się”.

Harmonogram zaniku uczenia się może być statyczny (ustalony z góry, jako funkcja bieżącej epoki lub bieżącego indeksu wsadu) lub dynamiczny (odpowiadający aktualnemu zachowaniu modelu, w szczególności utracie walidacji).

Przekazywanie harmonogramu optymalizatorowi

Możesz łatwo użyć harmonogramu spadku szybkości uczenia się, przekazując obiekt harmonogramu jako argument learning_rate w swoim optymalizatorze:

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)

Dostępnych jest kilka wbudowanych harmonogramów: ExponentialDecay , PiecewiseConstantDecay , PolynomialDecay i InverseTimeDecay .

Używanie wywołań zwrotnych do wdrażania harmonogramu dynamicznego uczenia się

Harmonogram dynamicznego współczynnika uczenia się (na przykład zmniejszenie współczynnika uczenia się, gdy utrata walidacji już się nie poprawia) nie może zostać osiągnięty za pomocą tych obiektów harmonogramu, ponieważ optymalizator nie ma dostępu do metryk walidacji.

Jednak wywołania zwrotne mają dostęp do wszystkich metryk, w tym metryk walidacji! W ten sposób można osiągnąć ten wzorzec, używając wywołania zwrotnego, które modyfikuje bieżący współczynnik uczenia się optymalizatora. W rzeczywistości jest to nawet wbudowane jako wywołanie zwrotne ReduceLROnPlateau .

Wizualizacja strat i metryk podczas treningu

Najlepszym sposobem na obserwowanie modelu podczas treningu jest użycie TensorBoard , aplikacji opartej na przeglądarce, którą można uruchamiać lokalnie i która zapewnia:

  • Wykresy na żywo strat i metryki do szkolenia i oceny
  • (opcjonalnie) Wizualizacje histogramów aktywacji warstw
  • (opcjonalnie) wizualizacje 3D przestrzeni osadzania poznane przez warstwy Embedding

Jeśli zainstalowałeś TensorFlow z pip, powinieneś być w stanie uruchomić TensorBoard z wiersza poleceń:

tensorboard --logdir=/full_path_to_your_logs

Korzystanie z wywołania zwrotnego TensorBoard

Najłatwiejszym sposobem użycia TensorBoard z modelem Keras i metodą dopasowania jest wywołanie zwrotne TensorBoard .

W najprostszym przypadku po prostu określ, gdzie chcesz, aby wywołanie zwrotne zapisywało dzienniki i jesteś gotowy:

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 0x7fda1f3062e8>

Więcej informacji można znaleźć w dokumentacji wywołania zwrotnego TensorBoard .