Обучение и оценка с помощью встроенных методов

Посмотреть на TensorFlow.org Запускаем в Google Colab Посмотреть исходный код на GitHub Скачать блокнот

Настраивать

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

Вступление

В этом руководстве рассматриваются модели обучения, оценки и прогнозирования (вывода) при использовании встроенных API-интерфейсов для обучения и проверки (таких как Model.fit() , Model.evaluate() и Model.predict() ).

Если вы заинтересованы в использовании fit() при указании собственной функции шага обучения, см. Руководство по настройке того, что происходит в fit() .

Если вы заинтересованы в написании собственных циклов обучения и оценки с нуля, см. Руководство «Написание цикла обучения с нуля» .

В общем, используете ли вы встроенные циклы или пишете свои собственные, обучение и оценка моделей работают строго одинаково для всех типов моделей Keras - последовательных моделей, моделей, построенных с помощью функционального API, и моделей, написанных с нуля с помощью подклассы модели.

В этом руководстве не рассматривается распределенное обучение, которое рассматривается в нашем руководстве по многопроцессорному и распределенному обучению .

Обзор API: первый сквозной пример

При передаче данных во встроенные циклы обучения модели вы должны использовать либо массивы NumPy (если ваши данные небольшие и умещаются в памяти), либо объекты tf.data Dataset . В следующих нескольких абзацах мы будем использовать набор данных MNIST в качестве массивов NumPy, чтобы продемонстрировать, как использовать оптимизаторы, потери и метрики.

Давайте рассмотрим следующую модель (здесь мы используем функциональный API, но это также может быть последовательная модель или модель с подклассом):

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)

Вот как выглядит типичный сквозной рабочий процесс, состоящий из:

  • Обучение
  • Проверка удерживающего набора, созданного на основе исходных обучающих данных
  • Оценка на тестовых данных

В этом примере мы будем использовать данные 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

Уточняем конфигурацию обучения (оптимизатор, убыток, метрики):

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

Мы вызываем fit() , который будет обучать модель, разделяя данные на «партии» размером batch_size и многократно повторяя весь набор данных в течение заданного количества epochs .

print("Fit model on training data")
history = model.fit(
    x_train,
    y_train,
    batch_size=64,
    epochs=2,
    # We pass some validation for
    # monitoring validation loss and metrics
    # at the end of each epoch
    validation_data=(x_val, y_val),
)
Fit model on training data
Epoch 1/2
782/782 [==============================] - 3s 3ms/step - loss: 0.5769 - sparse_categorical_accuracy: 0.8386 - val_loss: 0.1833 - val_sparse_categorical_accuracy: 0.9464
Epoch 2/2
782/782 [==============================] - 2s 2ms/step - loss: 0.1621 - sparse_categorical_accuracy: 0.9518 - val_loss: 0.1467 - val_sparse_categorical_accuracy: 0.9579

Возвращенный объект history содержит запись значений потерь и значений показателей во время обучения:

history.history
{'loss': [0.3323673903942108, 0.15159013867378235],
 'sparse_categorical_accuracy': [0.9050800204277039, 0.9542400240898132],
 'val_loss': [0.18328842520713806, 0.14667865633964539],
 'val_sparse_categorical_accuracy': [0.946399986743927, 0.9578999876976013]}

Мы оцениваем модель на тестовых данных с помощью 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.1449 - sparse_categorical_accuracy: 0.9539
test loss, test acc: [0.14493884146213531, 0.9538999795913696]
Generate predictions for 3 samples
predictions shape: (3, 10)

Теперь давайте подробно рассмотрим каждую часть этого рабочего процесса.

Метод compile() : указание потерь, показателей и оптимизатора

Чтобы обучить модель с помощью fit() , вам необходимо указать функцию потерь, оптимизатор и, при необходимости, некоторые показатели для мониторинга.

Вы передаете их модели в качестве аргументов методу compile() :

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

Аргумент metrics должен быть списком - ваша модель может иметь любое количество метрик.

Если ваша модель имеет несколько выходов, вы можете указать разные потери и метрики для каждого выхода, а также можете модулировать вклад каждого выхода в общие потери модели. Вы найдете более подробную информацию об этом в разделе « Передача данных в модели с множеством входов и выходов ».

Обратите внимание: если вас устраивают настройки по умолчанию, во многих случаях оптимизатор, потери и метрики можно указать с помощью строковых идентификаторов в виде ярлыка:

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

Для последующего повторного использования давайте поместим определение нашей модели и этап компиляции в функции; мы будем вызывать их несколько раз в разных примерах в этом руководстве.

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

Доступно множество встроенных оптимизаторов, потерь и метрик.

В общем, вам не придется создавать свои собственные потери, метрики или оптимизаторы с нуля, потому что то, что вам нужно, скорее всего, уже будет частью Keras API:

Оптимизаторы:

  • SGD() (с импульсом или без него)
  • RMSprop()
  • Adam()
  • и т.п.

Убытки:

  • MeanSquaredError()
  • KLDivergence()
  • CosineSimilarity()
  • и т.п.

Метрики:

  • AUC()
  • Precision()
  • Recall()
  • и т.п.

Пользовательские потери

Если вам нужно создать индивидуальную потерю, Keras предлагает два способа сделать это.

Первый метод включает создание функции, которая принимает входные данные y_true и y_pred . В следующем примере показана функция потерь, которая вычисляет среднеквадратичную ошибку между реальными данными и прогнозами:

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.0272
<tensorflow.python.keras.callbacks.History at 0x7fb6b01c09e8>

Если вам нужна функция потерь, которая принимает параметры помимо y_true и y_pred , вы можете tf.keras.losses.Loss подкласс класса tf.keras.losses.Loss и реализовать следующие два метода:

  • __init__(self) : принять параметры для передачи во время вызова вашей функции потерь
  • call(self, y_true, y_pred) : используйте цели (y_true) и прогнозы модели (y_pred) для вычисления потерь модели

Предположим, вы хотите использовать среднеквадратичную ошибку, но с добавленным термином, который деактивирует значения прогноза далеко от 0,5 (мы предполагаем, что категориальные цели закодированы по очереди и принимают значения от 0 до 1). Это создает стимул для модели не быть слишком уверенной, что может помочь уменьшить переобучение (мы не узнаем, сработает ли она, пока не попробуем!).

Вот как бы вы это сделали:

class CustomMSE(keras.losses.Loss):
    def __init__(self, regularization_factor=0.1, name="custom_mse"):
        super().__init__(name=name)
        self.regularization_factor = regularization_factor

    def call(self, y_true, y_pred):
        mse = tf.math.reduce_mean(tf.square(y_true - y_pred))
        reg = tf.math.reduce_mean(tf.square(0.5 - y_pred))
        return mse + reg * self.regularization_factor


model = get_uncompiled_model()
model.compile(optimizer=keras.optimizers.Adam(), loss=CustomMSE())

y_train_one_hot = tf.one_hot(y_train, depth=10)
model.fit(x_train, y_train_one_hot, batch_size=64, epochs=1)
782/782 [==============================] - 2s 2ms/step - loss: 0.0489
<tensorflow.python.keras.callbacks.History at 0x7fb6b00725f8>

Пользовательские метрики

Если вам нужна метрика, не являющаяся частью API, вы можете легко создать собственные метрики, tf.keras.metrics.Metric подкласс класса tf.keras.metrics.Metric . Вам потребуется реализовать 4 метода:

  • __init__(self) , в котором вы создадите переменные состояния для своей метрики.
  • update_state(self, y_true, y_pred, sample_weight=None) , который использует цели y_true и прогнозы модели y_pred для обновления переменных состояния.
  • result(self) , который использует переменные состояния для вычисления окончательных результатов.
  • reset_states(self) , который повторно инициализирует состояние метрики.

Обновление состояния и вычисление результатов хранятся отдельно (в update_state() и result() соответственно), потому что в некоторых случаях вычисление результатов может быть очень дорогостоящим и выполняться только периодически.

Вот простой пример , показывающий , как реализовать CategoricalTruePositives показатель , который подсчитывает , сколько образцы были правильно классифицированы как принадлежащие к данному классу:

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 [==============================] - 2s 2ms/step - loss: 0.5782 - categorical_true_positives: 22110.9323
Epoch 2/3
782/782 [==============================] - 2s 2ms/step - loss: 0.1737 - categorical_true_positives: 23825.8212
Epoch 3/3
782/782 [==============================] - 2s 2ms/step - loss: 0.1254 - categorical_true_positives: 24152.4547
<tensorflow.python.keras.callbacks.History at 0x7fb6a42a55f8>

Обработка потерь и показателей, не соответствующих стандартной подписи

Подавляющее большинство потерь и показателей можно вычислить из y_true и y_pred , где y_pred - это выход вашей модели, но не все из них. Например, потеря регуляризации может потребовать только активации слоя (в этом случае нет целей), и эта активация может не быть выходом модели.

В таких случаях вы можете вызвать self.add_loss(loss_value) из метода call настраиваемого слоя. Потери, добавленные таким образом, добавляются к «основным» потерям во время обучения (передаваемым в compile() ). Вот простой пример, который добавляет регуляризацию активности (обратите внимание, что регуляризация активности встроена во все слои Keras - этот слой просто для предоставления конкретного примера):

class ActivityRegularizationLayer(layers.Layer):
    def call(self, inputs):
        self.add_loss(tf.reduce_sum(inputs) * 0.1)
        return inputs  # Pass-through layer.


inputs = keras.Input(shape=(784,), name="digits")
x = layers.Dense(64, activation="relu", name="dense_1")(inputs)

# Insert activity regularization as a layer
x = ActivityRegularizationLayer()(x)

x = layers.Dense(64, activation="relu", name="dense_2")(x)
outputs = layers.Dense(10, name="predictions")(x)

model = keras.Model(inputs=inputs, outputs=outputs)
model.compile(
    optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
    loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
)

# The displayed loss will be much higher than before
# due to the regularization component.
model.fit(x_train, y_train, batch_size=64, epochs=1)
782/782 [==============================] - 2s 2ms/step - loss: 3.4140
<tensorflow.python.keras.callbacks.History at 0x7fb6a4233748>

Вы можете сделать то же самое для регистрации значений метрики, используя add_metric() :

class MetricLoggingLayer(layers.Layer):
    def call(self, inputs):
        # The `aggregation` argument defines
        # how to aggregate the per-batch values
        # over each epoch:
        # in this case we simply average them.
        self.add_metric(
            keras.backend.std(inputs), name="std_of_activation", aggregation="mean"
        )
        return inputs  # Pass-through layer.


inputs = keras.Input(shape=(784,), name="digits")
x = layers.Dense(64, activation="relu", name="dense_1")(inputs)

# Insert std logging as a layer.
x = MetricLoggingLayer()(x)

x = layers.Dense(64, activation="relu", name="dense_2")(x)
outputs = layers.Dense(10, name="predictions")(x)

model = keras.Model(inputs=inputs, outputs=outputs)
model.compile(
    optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
    loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
)
model.fit(x_train, y_train, batch_size=64, epochs=1)
782/782 [==============================] - 2s 2ms/step - loss: 0.5646 - std_of_activation: 0.9702
<tensorflow.python.keras.callbacks.History at 0x7fb6a40cf6a0>

В функциональном API вы также можете вызвать model.add_loss(loss_tensor) или model.add_metric(metric_tensor, name, aggregation) .

Вот простой пример:

inputs = keras.Input(shape=(784,), name="digits")
x1 = layers.Dense(64, activation="relu", name="dense_1")(inputs)
x2 = layers.Dense(64, activation="relu", name="dense_2")(x1)
outputs = layers.Dense(10, name="predictions")(x2)
model = keras.Model(inputs=inputs, outputs=outputs)

model.add_loss(tf.reduce_sum(x1) * 0.1)

model.add_metric(keras.backend.std(x1), name="std_of_activation", aggregation="mean")

model.compile(
    optimizer=keras.optimizers.RMSprop(1e-3),
    loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
)
model.fit(x_train, y_train, batch_size=64, epochs=1)
782/782 [==============================] - 2s 2ms/step - loss: 3.6195 - std_of_activation: 0.0020
<tensorflow.python.keras.callbacks.History at 0x7fb6a07d42b0>

Обратите внимание, что когда вы передаете потери через add_loss() , становится возможным вызвать compile() без функции потерь, поскольку в модели уже есть потери, которые необходимо минимизировать.

Рассмотрим следующий уровень LogisticEndpoint : он принимает в качестве входных данных цели и логиты и отслеживает потери add_loss() помощью add_loss() . Он также отслеживает точность классификации с помощью 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)

Вы можете использовать его в модели с двумя входами (входные данные и цели), скомпилированной без аргумента loss , например:

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 222ms/step - loss: 0.9652 - binary_accuracy: 0.0000e+00
<tensorflow.python.keras.callbacks.History at 0x7fb6a05e01d0>

Дополнительные сведения об обучении моделей с несколькими входами см. В разделе « Передача данных в модели с несколькими входами и несколькими выходами» .

Автоматическое разделение набора задержек проверки

В первом (x_val, y_val) примере, который вы видели, мы использовали аргумент validation_data для передачи кортежа массивов NumPy (x_val, y_val) в модель для оценки потерь при проверке и метрик проверки в конце каждой эпохи.

Вот еще один вариант: аргумент validation_split позволяет автоматически зарезервировать часть ваших обучающих данных для проверки. Значение аргумента представляет собой часть данных, которые должны быть зарезервированы для проверки, поэтому для него должно быть установлено число больше 0 и меньше 1. Например, validation_split=0.2 означает «использовать 20% данных для проверки», и validation_split=0.6 означает «использовать 60% данных для проверки».

Способ вычисления валидации состоит в том, чтобы взять последние x% выборок массивов, полученных вызовом fit() , перед любой перетасовкой.

Обратите внимание, что вы можете использовать validation_split только при обучении с данными NumPy.

model = get_compiled_model()
model.fit(x_train, y_train, batch_size=64, validation_split=0.2, epochs=1)
625/625 [==============================] - 2s 2ms/step - loss: 0.6075 - sparse_categorical_accuracy: 0.8389 - val_loss: 0.2291 - val_sparse_categorical_accuracy: 0.9322
<tensorflow.python.keras.callbacks.History at 0x7fb6a0504240>

Обучение и оценка на основе наборов данных tf.data

В последних нескольких абзацах вы видели, как обрабатывать потери, показатели и оптимизаторы, и вы видели, как использовать аргументы validation_data и validation_split в fit() , когда ваши данные передаются в виде массивов NumPy.

Давайте теперь рассмотрим случай, когда ваши данные поступают в виде объектаtf.data.Dataset .

API tf.data - это набор утилит в TensorFlow 2.0 для быстрой и масштабируемой загрузки и предварительной обработки данных.

Полное руководство по созданию Datasets см. В документации tf.data .

Вы можете передать экземпляр Dataset непосредственно в методы fit() , evaluate() и 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.5652 - sparse_categorical_accuracy: 0.8404
Epoch 2/3
782/782 [==============================] - 2s 2ms/step - loss: 0.1721 - sparse_categorical_accuracy: 0.9497
Epoch 3/3
782/782 [==============================] - 2s 2ms/step - loss: 0.1170 - sparse_categorical_accuracy: 0.9645
Evaluate
157/157 [==============================] - 0s 2ms/step - loss: 0.1308 - sparse_categorical_accuracy: 0.9602
{'loss': 0.13075917959213257,
 'sparse_categorical_accuracy': 0.9602000117301941}

Обратите внимание, что набор данных сбрасывается в конце каждой эпохи, поэтому его можно повторно использовать в следующей эпохе.

Если вы хотите запустить обучение только для определенного количества пакетов из этого набора данных, вы можете передать аргумент steps_per_epoch , который указывает, сколько шагов обучения модель должна выполнить с использованием этого набора данных, прежде чем перейти к следующей эпохе.

Если вы это сделаете, набор данных не сбрасывается в конце каждой эпохи, вместо этого мы просто продолжаем рисовать следующие пакеты. В наборе данных в конечном итоге закончатся данные (если только это не набор данных с бесконечным циклом).

model = get_compiled_model()

# Prepare the training dataset
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)

# Only use the 100 batches per epoch (that's 64 * 100 samples)
model.fit(train_dataset, epochs=3, steps_per_epoch=100)
Epoch 1/3
100/100 [==============================] - 1s 2ms/step - loss: 1.2664 - sparse_categorical_accuracy: 0.6389
Epoch 2/3
100/100 [==============================] - 0s 2ms/step - loss: 0.3868 - sparse_categorical_accuracy: 0.8875
Epoch 3/3
100/100 [==============================] - 0s 2ms/step - loss: 0.3578 - sparse_categorical_accuracy: 0.8981
<tensorflow.python.keras.callbacks.History at 0x7fb6a02a5358>

Использование набора данных проверки

Вы можете передать экземпляр Dataset в качестве аргумента validation_data в 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 3ms/step - loss: 0.5754 - sparse_categorical_accuracy: 0.8384 - val_loss: 0.1829 - val_sparse_categorical_accuracy: 0.9465
<tensorflow.python.keras.callbacks.History at 0x7fb6a01651d0>

В конце каждой эпохи модель будет перебирать набор данных валидации и вычислять потери валидации и метрики валидации.

Если вы хотите запустить проверку только для определенного количества пакетов из этого набора данных, вы можете передать аргумент validation_steps , который указывает, сколько шагов проверки модель должна выполнить с набором данных проверки, прежде чем прервать проверку и перейти к следующей эпохе:

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.5503 - sparse_categorical_accuracy: 0.8507 - val_loss: 0.3296 - val_sparse_categorical_accuracy: 0.9062
<tensorflow.python.keras.callbacks.History at 0x7fb6a02e4630>

Обратите внимание, что набор данных проверки будет сбрасываться после каждого использования (так что вы всегда будете оценивать одни и те же образцы от эпохи к эпохе).

Аргумент validation_split (создание набора задержек из обучающих данных) не поддерживается при обучении из объектов Dataset , поскольку эта функция требует возможности индексировать образцы наборов данных, что в целом невозможно с API Dataset .

Поддерживаются другие форматы ввода

Помимо массивов NumPy, активных тензоров и Datasets , можно обучить модель Keras, используя фреймы данных Pandas или генераторы Python, которые создают пакеты данных и меток.

В частности, класс keras.utils.Sequence предлагает простой интерфейс для создания генераторов данных Python, которые учитывают многопроцессорность и могут быть перетасованы.

В целом мы рекомендуем использовать:

  • Входные данные NumPy, если ваши данные маленькие и умещаются в памяти
  • Объекты наборов Dataset если у вас большие наборы данных и вам нужно проводить распределенное обучение
  • Sequence объектов, если у вас есть большие наборы данных, и вам нужно выполнить много пользовательской обработки на стороне Python, что невозможно сделать в TensorFlow (например, если вы полагаетесь на внешние библиотеки для загрузки или предварительной обработки данных).

Использование объекта keras.utils.Sequence качестве ввода

keras.utils.Sequence - это утилита, которую можно создать в подклассе для получения генератора Python с двумя важными свойствами:

  • Он хорошо работает с многопроцессорностью.
  • Его можно перемешать (например, при передаче shuffle=True в fit() ).

Sequence должна реализовывать два метода:

  • __getitem__
  • __len__

Метод __getitem__ должен возвращать полный пакет. Если вы хотите изменить свой набор данных между эпохами, вы можете реализовать on_epoch_end .

Вот небольшой пример:

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)

Использование взвешивания выборки и взвешивания классов

При настройках по умолчанию вес выборки определяется ее частотой в наборе данных. Есть два метода взвешивания данных, независимо от частоты дискретизации:

  • Вес класса
  • Вес образца

Вес класса

Это устанавливается путем передачи словаря в class_weight аргумент Model.fit() . Этот словарь сопоставляет индексы классов с весом, который следует использовать для выборок, принадлежащих этому классу.

Это можно использовать для балансировки классов без повторной выборки или для обучения модели, которая придает большее значение конкретному классу.

Например, если класс «0» наполовину представлен в ваших данных как класс «1», вы можете использовать Model.fit(..., class_weight={0: 1., 1: 0.5}) .

Вот пример NumPy, где мы используем веса классов или выборочные веса, чтобы придать большее значение правильной классификации класса № 5 (который является цифрой «5» в наборе данных MNIST).

import numpy as np

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

print("Fit with class weight")
model = get_compiled_model()
model.fit(x_train, y_train, class_weight=class_weight, batch_size=64, epochs=1)
Fit with class weight
782/782 [==============================] - 2s 2ms/step - loss: 0.6269 - sparse_categorical_accuracy: 0.8396
<tensorflow.python.keras.callbacks.History at 0x7fb6ca2479b0>

Вес образца

Для детального контроля или если вы не создаете классификатор, вы можете использовать «выборочные веса».

  • При обучении на основе данных NumPy: sample_weight аргумент Model.fit() в Model.fit() .
  • При обучении из tf.data или любого другого типа итератора: (input_batch, label_batch, sample_weight_batch) Yield (input_batch, label_batch, sample_weight_batch) .

Массив «весов выборок» - это массив чисел, которые определяют, какой вес должен иметь каждый образец в партии при вычислении общих потерь. Он обычно используется в задачах несбалансированной классификации (идея состоит в том, чтобы придать больший вес редко используемым классам).

Когда используемые веса - это единицы и нули, массив можно использовать в качестве маски для функции потерь (полностью отбрасывая вклад определенных выборок в общие потери).

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.6540 - sparse_categorical_accuracy: 0.8302
<tensorflow.python.keras.callbacks.History at 0x7fb6b03db128>

Вот соответствующий пример 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.6052 - sparse_categorical_accuracy: 0.8477
<tensorflow.python.keras.callbacks.History at 0x7fb6a40cc908>

Передача данных в модели с несколькими входами и выходами

В предыдущих примерах мы рассматривали модель с одним входом (тензор формы (764,) ) и одним выходом (тензор предсказания формы (10,) ). Но как насчет моделей с несколькими входами или выходами?

Рассмотрим следующую модель, которая имеет входное изображение формы (32, 32, 3) (это (height, width, channels) ) и вход временного ряда формы (None, 10) (это (timesteps, features) ). Наша модель будет иметь два выхода, вычисленных из комбинации этих входных данных: «оценка» (формы (1,) ) и распределение вероятностей по пяти классам (формы (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]
)

Давайте построим эту модель, чтобы вы могли ясно видеть, что мы здесь делаем (обратите внимание, что фигуры, показанные на графике, являются пакетными формами, а не формами для каждого образца).

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

PNG

Во время компиляции мы можем указать разные потери для разных выходов, передав функции потерь в виде списка:

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

Если бы мы передали модели только одну функцию потерь, та же функция потерь была бы применена к каждому выходу (что здесь неуместно).

То же самое и для показателей:

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

Поскольку мы дали имена нашим выходным слоям, мы также могли указать потери и метрики для каждого выхода с помощью dict:

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

Мы рекомендуем использовать явные имена и словари, если у вас более двух выходов.

Можно присвоить разные веса разным потерям, зависящим от результата (например, в нашем примере можно было бы отдать loss_weights потере «очков», присвоив 2- loss_weights значение потери класса), используя аргумент 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},
)

Вы также можете не рассчитывать потери для определенных выходных данных, если эти выходные данные предназначены для прогнозирования, но не для обучения:

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

Передача данных в модель с несколькими входами или несколькими выходами в fit() работает аналогично указанию функции потерь при компиляции: вы можете передавать списки массивов NumPy (с отображением 1: 1 на выходы, получившие функцию потерь ) или диктует отображение выходных имен в массивы 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 [==============================] - 10s 10ms/step - loss: 12.4255 - score_output_loss: 0.7638 - class_output_loss: 11.6617
4/4 [==============================] - 0s 5ms/step - loss: 11.1176 - score_output_loss: 0.6303 - class_output_loss: 10.4873
<tensorflow.python.keras.callbacks.History at 0x7fb6a02ed828>

Вот пример использования Dataset : аналогично тому, как мы делали для массивов NumPy, Dataset должен возвращать кортеж словарных статей.

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 27ms/step - loss: 10.9011 - score_output_loss: 0.4919 - class_output_loss: 10.4092
<tensorflow.python.keras.callbacks.History at 0x7fb6b00ae9e8>

Использование обратных вызовов

Обратные вызовы в Keras - это объекты, которые вызываются в разные моменты во время обучения (в начале эпохи, в конце пакета, в конце эпохи и т. Д.). Их можно использовать для реализации определенного поведения, например:

  • Выполнение проверки в разные моменты во время обучения (помимо встроенной проверки для каждой эпохи)
  • Проверка модели через регулярные промежутки времени или когда она превышает определенный порог точности
  • Изменение скорости обучения модели, когда кажется, что обучение выходит на плато
  • Выполнение тонкой настройки верхних слоев, когда тренировка, кажется, выходит на плато
  • Отправка уведомлений по электронной почте или мгновенным сообщениям при завершении обучения или превышении определенного порога производительности
  • И т.п.

Обратные вызовы могут быть переданы в виде списка вашему вызову fit() :

model = get_compiled_model()

callbacks = [
    keras.callbacks.EarlyStopping(
        # Stop training when `val_loss` is no longer improving
        monitor="val_loss",
        # "no longer improving" being defined as "no better than 1e-2 less"
        min_delta=1e-2,
        # "no longer improving" being further defined as "for at least 2 epochs"
        patience=2,
        verbose=1,
    )
]
model.fit(
    x_train,
    y_train,
    epochs=20,
    batch_size=64,
    callbacks=callbacks,
    validation_split=0.2,
)
Epoch 1/20
625/625 [==============================] - 2s 3ms/step - loss: 0.6076 - sparse_categorical_accuracy: 0.8350 - val_loss: 0.2323 - val_sparse_categorical_accuracy: 0.9306
Epoch 2/20
625/625 [==============================] - 1s 2ms/step - loss: 0.1925 - sparse_categorical_accuracy: 0.9436 - val_loss: 0.1828 - val_sparse_categorical_accuracy: 0.9446
Epoch 3/20
625/625 [==============================] - 1s 2ms/step - loss: 0.1310 - sparse_categorical_accuracy: 0.9616 - val_loss: 0.1580 - val_sparse_categorical_accuracy: 0.9510
Epoch 4/20
625/625 [==============================] - 1s 2ms/step - loss: 0.0967 - sparse_categorical_accuracy: 0.9700 - val_loss: 0.1681 - val_sparse_categorical_accuracy: 0.9490
Epoch 5/20
625/625 [==============================] - 1s 2ms/step - loss: 0.0841 - sparse_categorical_accuracy: 0.9742 - val_loss: 0.1482 - val_sparse_categorical_accuracy: 0.9568
Epoch 00005: early stopping
<tensorflow.python.keras.callbacks.History at 0x7fb63c5945c0>

Доступно множество встроенных обратных вызовов

В Keras уже доступно множество встроенных обратных вызовов, например:

  • ModelCheckpoint : периодически сохраняйте модель.
  • EarlyStopping : остановите обучение, когда обучение больше не улучшает показатели валидации.
  • TensorBoard : периодически пишите логи модели, которые можно визуализировать в TensorBoard (подробнее в разделе «Визуализация»).
  • CSVLogger : передает данные о потерях и метриках в файл CSV.
  • и т.п.

Полный список см. В документации по обратным вызовам .

Написание собственного обратного вызова

Вы можете создать собственный обратный вызов, расширив базовый класс keras.callbacks.Callback . Обратный вызов имеет доступ к связанной с ним модели через свойство класса self.model .

Обязательно прочтите полное руководство по написанию пользовательских обратных вызовов .

Вот простой пример сохранения списка значений потерь для каждой партии во время обучения:

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

Модели контрольных точек

Когда вы обучаете модель на относительно больших наборах данных, очень важно сохранять контрольные точки вашей модели через частые промежутки времени.

Самый простой способ добиться этого - использовать ModelCheckpoint вызов ModelCheckpoint :

model = get_compiled_model()

callbacks = [
    keras.callbacks.ModelCheckpoint(
        # Path where to save the model
        # The two parameters below mean that we will overwrite
        # the current checkpoint if and only if
        # the `val_loss` score has improved.
        # The saved model name will include the current epoch.
        filepath="mymodel_{epoch}",
        save_best_only=True,  # Only save a model if `val_loss` has improved.
        monitor="val_loss",
        verbose=1,
    )
]
model.fit(
    x_train, y_train, epochs=2, batch_size=64, callbacks=callbacks, validation_split=0.2
)
Epoch 1/2
625/625 [==============================] - 2s 2ms/step - loss: 0.6397 - sparse_categorical_accuracy: 0.8210 - val_loss: 0.2310 - val_sparse_categorical_accuracy: 0.9326

Epoch 00001: val_loss improved from inf to 0.23098, saving model to mymodel_1
INFO:tensorflow:Assets written to: mymodel_1/assets
Epoch 2/2
625/625 [==============================] - 1s 2ms/step - loss: 0.1885 - sparse_categorical_accuracy: 0.9454 - val_loss: 0.1851 - val_sparse_categorical_accuracy: 0.9435

Epoch 00002: val_loss improved from 0.23098 to 0.18510, saving model to mymodel_2
INFO:tensorflow:Assets written to: mymodel_2/assets
<tensorflow.python.keras.callbacks.History at 0x7fb6a04271d0>

ModelCheckpoint вызов ModelCheckpoint может использоваться для реализации отказоустойчивости: возможность перезапустить обучение из последнего сохраненного состояния модели в случае, если обучение прерывается случайным образом. Вот простой пример:

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
  85/1563 [>.............................] - ETA: 2s - loss: 1.4465 - sparse_categorical_accuracy: 0.5717INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.93/assets
 185/1563 [==>...........................] - ETA: 5s - loss: 1.1118 - sparse_categorical_accuracy: 0.6784INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.69/assets
 284/1563 [====>.........................] - ETA: 5s - loss: 0.9495 - sparse_categorical_accuracy: 0.7266INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.58/assets
 385/1563 [======>.......................] - ETA: 5s - loss: 0.8464 - sparse_categorical_accuracy: 0.7569INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.52/assets
 485/1563 [========>.....................] - ETA: 5s - loss: 0.7749 - sparse_categorical_accuracy: 0.7776INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.47/assets
 585/1563 [==========>...................] - ETA: 4s - loss: 0.7210 - sparse_categorical_accuracy: 0.7930INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.44/assets
 685/1563 [============>.................] - ETA: 4s - loss: 0.6788 - sparse_categorical_accuracy: 0.8050INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.42/assets
 785/1563 [==============>...............] - ETA: 4s - loss: 0.6445 - sparse_categorical_accuracy: 0.8149INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.40/assets
 883/1563 [===============>..............] - ETA: 3s - loss: 0.6165 - sparse_categorical_accuracy: 0.8229INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.38/assets
 984/1563 [=================>............] - ETA: 3s - loss: 0.5917 - sparse_categorical_accuracy: 0.8299INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.37/assets
1082/1563 [===================>..........] - ETA: 2s - loss: 0.5709 - sparse_categorical_accuracy: 0.8358INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.35/assets
1185/1563 [=====================>........] - ETA: 1s - loss: 0.5517 - sparse_categorical_accuracy: 0.8413INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.34/assets
1282/1563 [=======================>......] - ETA: 1s - loss: 0.5356 - sparse_categorical_accuracy: 0.8459INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.33/assets
1384/1563 [=========================>....] - ETA: 0s - loss: 0.5202 - sparse_categorical_accuracy: 0.8503INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.32/assets
1484/1563 [===========================>..] - ETA: 0s - loss: 0.5065 - sparse_categorical_accuracy: 0.8542INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.31/assets
1563/1563 [==============================] - 9s 5ms/step - loss: 0.4965 - sparse_categorical_accuracy: 0.8570
<tensorflow.python.keras.callbacks.History at 0x7fb6a036f5c0>

Звоните и пишите свой обратный вызов для сохранения и восстановления моделей.

Полное руководство по сериализации и сохранению см. В руководстве по сохранению и сериализации моделей .

Использование расписаний скорости обучения

Распространенным шаблоном при обучении моделей глубокого обучения является постепенное сокращение объема обучения по мере обучения. Это обычно известно как «снижение скорости обучения».

График замедления обучения может быть статическим (фиксированным заранее, как функция текущей эпохи или текущего индекса пакета) или динамическим (реагирующим на текущее поведение модели, в частности, на потерю проверки).

Передача расписания оптимизатору

Вы можете легко использовать статическое расписание спада скорости обучения, передав объект расписания в качестве аргумента learning_rate в оптимизаторе:

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)

Доступно несколько встроенных расписаний: ExponentialDecay , PiecewiseConstantDecay , PolynomialDecay и InverseTimeDecay .

Использование обратных вызовов для реализации динамического расписания скорости обучения

График скорости динамического обучения (например, уменьшение скорости обучения, когда потеря проверки больше не улучшается) не может быть достигнуто с этими объектами расписания, так как оптимизатор не имеет доступа к метрикам проверки.

Однако у обратных вызовов есть доступ ко всем метрикам, включая метрики валидации! Таким образом, вы можете достичь этого шаблона, используя обратный вызов, который изменяет текущую скорость обучения в оптимизаторе. Фактически, это даже встроенный ReduceLROnPlateau вызов ReduceLROnPlateau .

Визуализация потерь и показателей во время тренировки

Лучший способ следить за своей моделью во время обучения - использовать TensorBoard - приложение на основе браузера, которое вы можете запускать локально и которое предоставляет вам:

  • Живые графики потерь и метрики для обучения и оценки
  • (опционально) Визуализации гистограмм активации ваших слоев
  • (опционально) 3D-визуализация пространств вложения, изученных вашими слоями Embedding

Если вы установили TensorFlow с помощью pip, вы сможете запустить TensorBoard из командной строки:

tensorboard --logdir=/full_path_to_your_logs

Использование обратного вызова TensorBoard

Самый простой способ использовать TensorBoard с моделью Keras и методом fit() - это TensorBoard вызов TensorBoard .

В простейшем случае просто укажите, где вы хотите, чтобы обратный вызов записывал журналы, и все готово:

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

Для получения дополнительной информации см. Документацию по TensorBoard вызову TensorBoard .