Google I/O — это обертка! Наверстать упущенное в сеансах TensorFlow Просмотреть сеансы

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

Посмотреть на 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, и моделей, написанных с нуля с помощью подклассы модели.

Это руководство не распространяется на распределенное обучение, которая охватывает в нашем руководстве для мульти-GPU и распределенного обучения .

Обзор 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]

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

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.3387 - sparse_categorical_accuracy: 0.9050 - val_loss: 0.1957 - val_sparse_categorical_accuracy: 0.9426
Epoch 2/2
782/782 [==============================] - 2s 3ms/step - loss: 0.1543 - sparse_categorical_accuracy: 0.9548 - val_loss: 0.1425 - val_sparse_categorical_accuracy: 0.9593

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

history.history
{'loss': [0.3386789858341217, 0.1543138176202774],
 'sparse_categorical_accuracy': [0.9050400257110596, 0.9548400044441223],
 'val_loss': [0.19569723308086395, 0.14253544807434082],
 'val_sparse_categorical_accuracy': [0.9426000118255615, 0.9592999815940857]}

Мы оцениваем модель на тестовых данных с помощью evaluate() :

# Evaluate the model on the test data using `evaluate`
print("Evaluate on test data")
results = model.evaluate(x_test, y_test, batch_size=128)
print("test loss, test acc:", results)

# Generate predictions (probabilities -- the output of the last layer)
# on new data using `predict`
print("Generate predictions for 3 samples")
predictions = model.predict(x_test[:3])
print("predictions shape:", predictions.shape)
Evaluate on test data
79/79 [==============================] - 0s 2ms/step - loss: 0.1414 - sparse_categorical_accuracy: 0.9569
test loss, test acc: [0.14140386879444122, 0.9569000005722046]
Generate predictions for 3 samples
predictions shape: (3, 10)

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

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 [==============================] - 2s 2ms/step - loss: 0.0162
<keras.callbacks.History at 0x7ff8881ba250>

Если вам нужна функция потерь , которая принимает в параметрах рядом y_true и y_pred , вы можете подкласс 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.0388
<keras.callbacks.History at 0x7ff8882130d0>

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

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

  • __init__(self) , в котором вы будете создавать переменные состояния для вашей метрики.
  • update_state(self, y_true, y_pred, sample_weight=None) , которая использует цели y_true и предсказание модели y_pred для обновления переменных состояния.
  • result(self) , которая использует переменные состояния для вычисления окончательных результатов.
  • reset_state(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_state(self):
        # The state of the metric will be reset at the start of each epoch.
        self.true_positives.assign(0.0)


model = get_uncompiled_model()
model.compile(
    optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
    loss=keras.losses.SparseCategoricalCrossentropy(),
    metrics=[CategoricalTruePositives()],
)
model.fit(x_train, y_train, batch_size=64, epochs=3)
Epoch 1/3
782/782 [==============================] - 2s 3ms/step - loss: 0.3404 - categorical_true_positives: 45217.0000
Epoch 2/3
782/782 [==============================] - 2s 3ms/step - loss: 0.1588 - categorical_true_positives: 47606.0000
Epoch 3/3
782/782 [==============================] - 2s 3ms/step - loss: 0.1168 - categorical_true_positives: 48278.0000
<keras.callbacks.History at 0x7ff8880a3610>

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

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

В таких случаях, вы можете вызвать self.add_loss(loss_value) внутри метода вызова заказного слоя. Потери , добавленные таким образом добавляются к «основной» потере во время тренировки (тот перешел к 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: 2.4545
<keras.callbacks.History at 0x7ff87c53f310>

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

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


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

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

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

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

В функциональной 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 3ms/step - loss: 2.4647 - std_of_activation: 0.0017
<keras.callbacks.History at 0x7ff87c216f90>

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

Рассмотрим следующий LogisticEndpoint слой: он принимает в качестве входных данных целей и логит, и она отслеживает crossentropy потери с помощью 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 414ms/step - loss: 0.9889 - binary_accuracy: 0.0000e+00
<keras.callbacks.History at 0x7ff87c0848d0>

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

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

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

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

Способ проверки достоверности вычисляется, принимая последние Х% образцов массивов , полученных 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 3ms/step - loss: 0.3682 - sparse_categorical_accuracy: 0.8957 - val_loss: 0.2276 - val_sparse_categorical_accuracy: 0.9301
<keras.callbacks.History at 0x7ff81c680890>

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

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

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

tf.data API представляет собой набор утилит в 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 3ms/step - loss: 0.3372 - sparse_categorical_accuracy: 0.9047
Epoch 2/3
782/782 [==============================] - 2s 3ms/step - loss: 0.1596 - sparse_categorical_accuracy: 0.9523
Epoch 3/3
782/782 [==============================] - 2s 3ms/step - loss: 0.1171 - sparse_categorical_accuracy: 0.9655
Evaluate
157/157 [==============================] - 0s 2ms/step - loss: 0.1211 - sparse_categorical_accuracy: 0.9648
{'loss': 0.12107347697019577,
 'sparse_categorical_accuracy': 0.9648000001907349}

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

Если вы хотите запустить обучение только на определенное число партий из этого набора данных, вы можете передать 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 3ms/step - loss: 0.7937 - sparse_categorical_accuracy: 0.7894
Epoch 2/3
100/100 [==============================] - 0s 3ms/step - loss: 0.3699 - sparse_categorical_accuracy: 0.8938
Epoch 3/3
100/100 [==============================] - 0s 3ms/step - loss: 0.3155 - sparse_categorical_accuracy: 0.9061
<keras.callbacks.History at 0x7ff81c587e90>

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

Вы можете передать 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 [==============================] - 3s 3ms/step - loss: 0.3380 - sparse_categorical_accuracy: 0.9035 - val_loss: 0.2015 - val_sparse_categorical_accuracy: 0.9405
<keras.callbacks.History at 0x7ff81c30e450>

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

Если вы хотите запустить проверку только на определенном числе партий из этого набора данных, вы можете передать 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 [==============================] - 3s 3ms/step - loss: 0.3369 - sparse_categorical_accuracy: 0.9036 - val_loss: 0.2953 - val_sparse_categorical_accuracy: 0.9187
<keras.callbacks.History at 0x7ff81c30e310>

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

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

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

Кроме NumPy массивы, жаждущих тензоров и TensorFlow Datasets , можно обучить модель Keras с помощью панд dataframes, или от генераторов Python , что выход партии данных и этикеток.

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

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

  • Входные данные 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 3ms/step - loss: 0.3708 - sparse_categorical_accuracy: 0.9032
<keras.callbacks.History at 0x7ff80c7ddd10>

Вес образца

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

  • При обучении по данным NumPy: Передайте sample_weight аргумент Model.fit() .
  • При обучении с tf.data или любого другого вида итератора: Выход (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 3ms/step - loss: 0.3806 - sparse_categorical_accuracy: 0.9000
<keras.callbacks.History at 0x7ff80c650350>

Вот соответствующий 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 [==============================] - 3s 3ms/step - loss: 0.3588 - sparse_categorical_accuracy: 0.9070
<keras.callbacks.History at 0x7ff80c51cb50>

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

В предыдущих примерах мы рассматривали модель с одним входом (тензором формы (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()],
    },
)

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

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

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

# Generate dummy NumPy data
img_data = np.random.random_sample(size=(100, 32, 32, 3))
ts_data = np.random.random_sample(size=(100, 20, 10))
score_targets = np.random.random_sample(size=(100, 1))
class_targets = np.random.random_sample(size=(100, 5))

# Fit on lists
model.fit([img_data, ts_data], [score_targets, class_targets], batch_size=32, epochs=1)

# Alternatively, fit on dicts
model.fit(
    {"img_input": img_data, "ts_input": ts_data},
    {"score_output": score_targets, "class_output": class_targets},
    batch_size=32,
    epochs=1,
)
4/4 [==============================] - 2s 9ms/step - loss: 5.6917 - score_output_loss: 0.1031 - class_output_loss: 5.5886
4/4 [==============================] - 0s 6ms/step - loss: 4.4108 - score_output_loss: 0.0999 - class_output_loss: 4.3109
<keras.callbacks.History at 0x7ff80c3b4110>

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

train_dataset = tf.data.Dataset.from_tensor_slices(
    (
        {"img_input": img_data, "ts_input": ts_data},
        {"score_output": score_targets, "class_output": class_targets},
    )
)
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)

model.fit(train_dataset, epochs=1)
2/2 [==============================] - 0s 21ms/step - loss: 4.2451 - score_output_loss: 0.0993 - class_output_loss: 4.1458
<keras.callbacks.History at 0x7ff80c3ed450>

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

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

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

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

model = get_compiled_model()

callbacks = [
    keras.callbacks.EarlyStopping(
        # Stop training when `val_loss` is no longer improving
        monitor="val_loss",
        # "no longer improving" being defined as "no better than 1e-2 less"
        min_delta=1e-2,
        # "no longer improving" being further defined as "for at least 2 epochs"
        patience=2,
        verbose=1,
    )
]
model.fit(
    x_train,
    y_train,
    epochs=20,
    batch_size=64,
    callbacks=callbacks,
    validation_split=0.2,
)
Epoch 1/20
625/625 [==============================] - 2s 3ms/step - loss: 0.3725 - sparse_categorical_accuracy: 0.8939 - val_loss: 0.2314 - val_sparse_categorical_accuracy: 0.9321
Epoch 2/20
625/625 [==============================] - 2s 3ms/step - loss: 0.1805 - sparse_categorical_accuracy: 0.9471 - val_loss: 0.2012 - val_sparse_categorical_accuracy: 0.9379
Epoch 3/20
625/625 [==============================] - 2s 3ms/step - loss: 0.1346 - sparse_categorical_accuracy: 0.9603 - val_loss: 0.1651 - val_sparse_categorical_accuracy: 0.9505
Epoch 4/20
625/625 [==============================] - 2s 3ms/step - loss: 0.1065 - sparse_categorical_accuracy: 0.9684 - val_loss: 0.1510 - val_sparse_categorical_accuracy: 0.9571
Epoch 5/20
625/625 [==============================] - 2s 3ms/step - loss: 0.0884 - sparse_categorical_accuracy: 0.9734 - val_loss: 0.1505 - val_sparse_categorical_accuracy: 0.9538
Epoch 6/20
625/625 [==============================] - 2s 3ms/step - loss: 0.0746 - sparse_categorical_accuracy: 0.9778 - val_loss: 0.1508 - val_sparse_categorical_accuracy: 0.9575
Epoch 00006: early stopping
<keras.callbacks.History at 0x7ff80c64cad0>

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

В 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 обратного вызова:

model = get_compiled_model()

callbacks = [
    keras.callbacks.ModelCheckpoint(
        # Path where to save the model
        # The two parameters below mean that we will overwrite
        # the current checkpoint if and only if
        # the `val_loss` score has improved.
        # The saved model name will include the current epoch.
        filepath="mymodel_{epoch}",
        save_best_only=True,  # Only save a model if `val_loss` has improved.
        monitor="val_loss",
        verbose=1,
    )
]
model.fit(
    x_train, y_train, epochs=2, batch_size=64, callbacks=callbacks, validation_split=0.2
)
Epoch 1/2
613/625 [============================>.] - ETA: 0s - loss: 0.3693 - sparse_categorical_accuracy: 0.8972
Epoch 00001: val_loss improved from inf to 0.23508, saving model to mymodel_1
2021-11-12 20:11:50.182298: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
INFO:tensorflow:Assets written to: mymodel_1/assets
625/625 [==============================] - 3s 4ms/step - loss: 0.3660 - sparse_categorical_accuracy: 0.8979 - val_loss: 0.2351 - val_sparse_categorical_accuracy: 0.9273
Epoch 2/2
620/625 [============================>.] - ETA: 0s - loss: 0.1659 - sparse_categorical_accuracy: 0.9507
Epoch 00002: val_loss improved from 0.23508 to 0.16898, saving model to mymodel_2
INFO:tensorflow:Assets written to: mymodel_2/assets
625/625 [==============================] - 2s 3ms/step - loss: 0.1657 - sparse_categorical_accuracy: 0.9507 - val_loss: 0.1690 - val_sparse_categorical_accuracy: 0.9482
<keras.callbacks.History at 0x7ff8b577cc90>

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
  88/1563 [>.............................] - ETA: 3s - loss: 1.1203 - sparse_categorical_accuracy: 0.6911INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=1.04/assets
 185/1563 [==>...........................] - ETA: 6s - loss: 0.7768 - sparse_categorical_accuracy: 0.7858INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.75/assets
 286/1563 [====>.........................] - ETA: 6s - loss: 0.6382 - sparse_categorical_accuracy: 0.8211INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.63/assets
 383/1563 [======>.......................] - ETA: 6s - loss: 0.5584 - sparse_categorical_accuracy: 0.8433INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.55/assets
 484/1563 [========>.....................] - ETA: 6s - loss: 0.5032 - sparse_categorical_accuracy: 0.8578INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.50/assets
 586/1563 [==========>...................] - ETA: 5s - loss: 0.4644 - sparse_categorical_accuracy: 0.8684INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.46/assets
 685/1563 [============>.................] - ETA: 5s - loss: 0.4356 - sparse_categorical_accuracy: 0.8762INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.43/assets
 783/1563 [==============>...............] - ETA: 5s - loss: 0.4127 - sparse_categorical_accuracy: 0.8825INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.41/assets
 883/1563 [===============>..............] - ETA: 4s - loss: 0.3958 - sparse_categorical_accuracy: 0.8868INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.39/assets
 985/1563 [=================>............] - ETA: 3s - loss: 0.3766 - sparse_categorical_accuracy: 0.8918INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.38/assets
1086/1563 [===================>..........] - ETA: 3s - loss: 0.3624 - sparse_categorical_accuracy: 0.8958INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.36/assets
1184/1563 [=====================>........] - ETA: 2s - loss: 0.3498 - sparse_categorical_accuracy: 0.8994INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.35/assets
1283/1563 [=======================>......] - ETA: 1s - loss: 0.3383 - sparse_categorical_accuracy: 0.9029INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.34/assets
1386/1563 [=========================>....] - ETA: 1s - loss: 0.3265 - sparse_categorical_accuracy: 0.9058INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.33/assets
1485/1563 [===========================>..] - ETA: 0s - loss: 0.3184 - sparse_categorical_accuracy: 0.9081INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.32/assets
1563/1563 [==============================] - 11s 7ms/step - loss: 0.3122 - sparse_categorical_accuracy: 0.9097
<keras.callbacks.History at 0x7ff8b53e1dd0>

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

Полное руководство по сериализации и экономии, см руководства по экономии и сериализации модели .

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

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

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

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

Вы можете легко использовать статическую учебный график затухания скорости, передавая объект графики в качестве 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 обратного вызова.

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

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

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

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

tensorboard --logdir=/full_path_to_your_logs

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

Самый простой способ использовать TensorBoard с моделью Keras и fit() метод является 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)
<keras.callbacks.TensorBoard at 0x7ff88c8c04d0>

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