O Dia da Comunidade de ML é dia 9 de novembro! Junte-nos para atualização de TensorFlow, JAX, e mais Saiba mais

Treinamento e avaliação com os métodos integrados

Ver no TensorFlow.org Executar no Google Colab Ver fonte no GitHub Baixar caderno

Configurar

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

Introdução

Este guia aborda formação, avaliação e previsão (inferência) modelos ao usar built-in APIs para a formação e validação (como Model.fit() , Model.evaluate() e Model.predict() ).

Se você estiver interessado em aproveitar fit() ao especificar a sua própria função etapa de treinamento, consulte o Personalizando o que acontece no fit() guia .

Se você estiver interessado em escrever a sua própria formação e de avaliação laços a partir do zero, consulte o guia "escrever um loop de formação a partir do zero" .

Em geral, esteja você usando loops integrados ou escrevendo seus próprios, o treinamento e a avaliação do modelo funcionam estritamente da mesma maneira em todos os tipos de modelo Keras - modelos sequenciais, modelos construídos com a API Funcional e modelos escritos do zero via subclasse de modelo.

Este guia não cobre formação distribuída, que é coberto em nosso guia para multi-GPU e formação distribuída .

Visão geral da API: um primeiro exemplo de ponta a ponta

Ao passar os dados para o built-in formação voltas de um modelo, você deve usar matrizes Numpy (se os seus dados é pequena e se encaixa na memória) ou tf.data Dataset objetos. Nos próximos parágrafos, usaremos o conjunto de dados MNIST como matrizes NumPy, a fim de demonstrar como usar otimizadores, perdas e métricas.

Vamos considerar o seguinte modelo (aqui, construímos com a API Funcional, mas também pode ser um modelo Sequencial ou um modelo de subclasse):

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)

Esta é a aparência de um fluxo de trabalho ponta a ponta típico, consistindo em:

  • Treinamento
  • Validação em um conjunto de validação gerado a partir dos dados de treinamento originais
  • Avaliação dos dados de teste

Usaremos dados MNIST para este exemplo.

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

Especificamos a configuração do treinamento (otimizador, perda, métricas):

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

Chamamos fit() , que vai treinar o modelo por corte os dados em "lotes" de tamanho batch_size , e repetidamente iteração sobre todo o conjunto de dados para um determinado número de 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.3483 - sparse_categorical_accuracy: 0.9025 - val_loss: 0.1949 - val_sparse_categorical_accuracy: 0.9443
Epoch 2/2
782/782 [==============================] - 2s 3ms/step - loss: 0.1611 - sparse_categorical_accuracy: 0.9519 - val_loss: 0.1420 - val_sparse_categorical_accuracy: 0.9612

O retornado history objeto mantém um registro dos valores de perda e valores métricas durante o treinamento:

history.history
{'loss': [0.3483238220214844, 0.16108229756355286],
 'sparse_categorical_accuracy': [0.9025400280952454, 0.9518600106239319],
 'val_loss': [0.19487273693084717, 0.14200106263160706],
 'val_sparse_categorical_accuracy': [0.9442999958992004, 0.9611999988555908]}

Nós avaliamos o modelo nos dados de teste através de 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.1485 - sparse_categorical_accuracy: 0.9542
test loss, test acc: [0.1484519988298416, 0.954200029373169]
Generate predictions for 3 samples
predictions shape: (3, 10)

Agora, vamos revisar cada parte desse fluxo de trabalho em detalhes.

A compile() Método: especificando uma perda, métricas, e um optimizador

Para treinar um modelo com fit() , você precisa especificar uma função de perda, um otimizador, e, opcionalmente, algumas métricas para monitor.

Você passar estes para o modelo como argumentos para a compile() método:

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

O metrics argumento deve ser uma lista - o modelo pode ter qualquer número de métricas.

Se o seu modelo tem várias saídas, você pode especificar diferentes perdas e métricas para cada saída e pode modular a contribuição de cada saída para a perda total do modelo. Você vai encontrar mais detalhes sobre este nos dados de passagem a multi-entrada, seção de modelos multi-saída.

Observe que se você estiver satisfeito com as configurações padrão, em muitos casos, o otimizador, a perda e as métricas podem ser especificados por meio de identificadores de string como um atalho:

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

Para reutilização posterior, vamos colocar nossa definição de modelo e etapa de compilação em funções; vamos chamá-los várias vezes em diferentes exemplos neste guia.

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

Muitos otimizadores, perdas e métricas integrados estão disponíveis

Em geral, você não terá que criar suas próprias perdas, métricas ou otimizadores do zero, porque o que você precisa provavelmente já faz parte da API Keras:

Otimizadores:

  • SGD() (com ou sem impulso)
  • RMSprop()
  • Adam()
  • etc.

Perdas:

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

Métricas:

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

Perdas personalizadas

Se você precisar criar uma perda personalizada, o Keras oferece duas maneiras de fazer isso.

O primeiro método envolve a criação de uma função que aceita entradas y_true e y_pred . O exemplo a seguir mostra uma função de perda que calcula o erro quadrático médio entre os dados reais e as previsões:

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.0161
<keras.callbacks.History at 0x7f4b14549e90>

Se você precisar de uma função perda que leva em parâmetros ao lado y_true e y_pred , você pode subclasse o tf.keras.losses.Loss classe e implementar os dois métodos a seguir:

  • __init__(self) : aceitar parâmetros para passar durante a chamada de sua função de perda
  • call(self, y_true, y_pred) : usar os alvos (y_true) e as previsões do modelo (y_pred) para calcular a perda do modelo

Digamos que você queira usar o erro quadrático médio, mas com um termo adicionado que diminuirá os valores de predição longe de 0,5 (assumimos que os alvos categóricos são codificados em um ponto e assumem valores entre 0 e 1). Isso cria um incentivo para que o modelo não fique muito confiante, o que pode ajudar a reduzir o sobreajuste (não saberemos se funciona até tentarmos!).

Veja como você faria isso:

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.0383
<keras.callbacks.History at 0x7f4b143d8e10>

Métricas personalizadas

Se você precisar de uma métrica que não faz parte da API, você pode facilmente criar métricas personalizadas por subclasse do tf.keras.metrics.Metric classe. Você precisará implementar 4 métodos:

  • __init__(self) , em que você vai criar variáveis de estado para sua métrica.
  • update_state(self, y_true, y_pred, sample_weight=None) , que usa as metas y_true e as previsões do modelo y_pred para atualizar as variáveis de estado.
  • result(self) , que usa as variáveis de estado para calcular os resultados finais.
  • reset_states(self) , que reinicializa o estado da métrica.

Atualização Estado e de resultados de cálculo são mantidos separados (em update_state() e result() , respectivamente) porque, em alguns casos, os resultados computação pode ser muito caro e só seria feito periodicamente.

Aqui está um exemplo simples que mostra como implementar um CategoricalTruePositives métrica que conta quantas amostras foram corretamente classificados como pertencentes a uma determinada classe:

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.3441 - categorical_true_positives: 45120.0000
Epoch 2/3
 70/782 [=>............................] - ETA: 1s - loss: 0.1721 - categorical_true_positives: 4247.0000
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/metrics.py:257: UserWarning: Metric CategoricalTruePositives implements a `reset_states()` method; rename it to `reset_state()` (without the final "s"). The name `reset_states()` has been deprecated to improve API consistency.
  'consistency.' % (self.__class__.__name__,))
782/782 [==============================] - 2s 2ms/step - loss: 0.1625 - categorical_true_positives: 47585.0000
Epoch 3/3
782/782 [==============================] - 2s 2ms/step - loss: 0.1202 - categorical_true_positives: 48190.0000
<keras.callbacks.History at 0x7f4b14228910>

Lidar com perdas e métricas que não se enquadram na assinatura padrão

A esmagadora maioria das perdas e métricas podem ser computados a partir y_true e y_pred , onde y_pred é uma saída do seu modelo - mas não todos eles. Por exemplo, uma perda de regularização pode exigir apenas a ativação de uma camada (não há alvos neste caso), e essa ativação pode não ser uma saída do modelo.

Nesses casos, você pode chamar self.add_loss(loss_value) de dentro do método chamada de uma camada de costume. Perdas adicionados desta forma são adicionados à perda "principal" durante o treinamento (o passado para compile() ). Aqui está um exemplo simples que adiciona regularização de atividade (observe que a regularização de atividade é integrada em todas as camadas Keras - esta camada serve apenas para fornecer um exemplo concreto):

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.5364
<keras.callbacks.History at 0x7f4b140acc50>

Você pode fazer o mesmo para registrando valores de métricas, usando 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.3495 - std_of_activation: 0.9820
<keras.callbacks.History at 0x7f4af21e3bd0>

Na API funcional , você também pode ligar model.add_loss(loss_tensor) , ou model.add_metric(metric_tensor, name, aggregation) .

Aqui está um exemplo simples:

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: 2.4347 - std_of_activation: 0.0016
<keras.callbacks.History at 0x7f4af216d810>

Note que quando você passar perdas via add_loss() , torna-se possível chamada compile() sem uma função de perda, uma vez que o modelo já tem uma perda de minimizar.

Considere o seguinte LogisticEndpoint camada: leva como entradas alvos e logits, e acompanha uma perda crossentropy via add_loss() . Ele também rastreia a precisão da classificação através 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)

Você pode usá-lo em um modelo com duas entradas (dados de entrada e metas), compilados sem loss argumento, como este:

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 242ms/step - loss: 0.9816 - binary_accuracy: 0.0000e+00
<keras.callbacks.History at 0x7f4af212bed0>

Para mais informações sobre o treinamento modelos multi-entrada, consulte a seção Passando dados para multi-entrada, modelos multi-saída.

Separar automaticamente um conjunto de validação de validação

No primeiro exemplo, end-to-end que você viu, foi utilizado o validation_data argumento para passar uma tupla de arrays numpy (x_val, y_val) para o modelo de avaliação de uma perda validação e métricas de validação no final de cada época.

Aqui está uma outra opção: o argumento validation_split permite-lhe parte de reserva automaticamente de seus dados de treinamento para validação. O valor do argumento representa a fracção dos dados a serem reservados para validação, por isso, deve ser definido como um número maior do que 0 e menor do que 1. Por exemplo, validation_split=0.2 meios "de uso de 20% dos dados de validação", e validation_split=0.6 meios "de uso de 60% dos dados de validação".

A maneira como a validação é calculado é tomando as% das amostras últimos x das matrizes recebidas pelo fit() chamada, antes de qualquer baralhar.

Note que você só pode usar validation_split quando o treinamento com os dados 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.3737 - sparse_categorical_accuracy: 0.8947 - val_loss: 0.2427 - val_sparse_categorical_accuracy: 0.9249
<keras.callbacks.History at 0x7f4af1847610>

Treinamento e avaliação de conjuntos de dados tf.data

Nos últimos parágrafos, você viu como lidar com perdas, métricas e otimizadores, e você viu como usar os validation_data e validation_split argumentos no fit() , quando os dados são passados como matrizes Numpy.

Vamos agora dar uma olhada no caso onde os dados vem na forma de um tf.data.Dataset objeto.

O tf.data API é um conjunto de utilidades em TensorFlow 2,0 para o carregamento e de pré-processamento de dados de um modo que é rápido e escalável.

Para um guia completo sobre a criação de Datasets , consulte a documentação tf.data .

Você pode passar um Dataset instância diretamente para os métodos de fit() , evaluate() , e 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.3280 - sparse_categorical_accuracy: 0.9088
Epoch 2/3
782/782 [==============================] - 2s 2ms/step - loss: 0.1550 - sparse_categorical_accuracy: 0.9525
Epoch 3/3
782/782 [==============================] - 2s 2ms/step - loss: 0.1143 - sparse_categorical_accuracy: 0.9650
Evaluate
157/157 [==============================] - 0s 2ms/step - loss: 0.1126 - sparse_categorical_accuracy: 0.9659
{'loss': 0.11255467683076859,
 'sparse_categorical_accuracy': 0.9659000039100647}

Observe que o conjunto de dados é redefinido no final de cada época, para que possa ser reutilizado na próxima época.

Se você deseja executar treinando apenas em um número específico de lotes deste conjunto de dados, você pode passar o steps_per_epoch argumento, que especifica quantos formação passos o modelo deve executar usando esse conjunto de dados antes de passar para a próxima época.

Se você fizer isso, o conjunto de dados não será redefinido no final de cada época, em vez disso, continuaremos desenhando os próximos lotes. O conjunto de dados acabará ficando sem dados (a menos que seja um conjunto de dados em loop infinito).

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: 0.8098 - sparse_categorical_accuracy: 0.8011
Epoch 2/3
100/100 [==============================] - 0s 2ms/step - loss: 0.3844 - sparse_categorical_accuracy: 0.8933
Epoch 3/3
100/100 [==============================] - 0s 2ms/step - loss: 0.3357 - sparse_categorical_accuracy: 0.9002
<keras.callbacks.History at 0x7f4af1f95150>

Usando um conjunto de dados de validação

Você pode passar um Dataset instância como o validation_data argumento em 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.3319 - sparse_categorical_accuracy: 0.9069 - val_loss: 0.1979 - val_sparse_categorical_accuracy: 0.9418
<keras.callbacks.History at 0x7f4af1e3ce50>

No final de cada época, o modelo irá iterar sobre o conjunto de dados de validação e calcular a perda de validação e as métricas de validação.

Se você deseja executar a validação apenas em um número específico de lotes deste conjunto de dados, você pode passar o validation_steps argumento, que especifica quantos validação os passos do modelo deve ser executado com o conjunto de dados de validação antes de interromper validação e passar para a próxima época:

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 3ms/step - loss: 0.3502 - sparse_categorical_accuracy: 0.9024 - val_loss: 0.3006 - val_sparse_categorical_accuracy: 0.9125
<keras.callbacks.History at 0x7f4af1c9b050>

Observe que o conjunto de dados de validação será redefinido após cada uso (para que você sempre avalie nas mesmas amostras de época para época).

O argumento validation_split (gerando um conjunto de validação a partir dos dados de formação) não é suportada quando da formação do Dataset objetos, uma vez que esta característica requer a capacidade para indexar as amostras dos conjuntos de dados, que não é possível, em geral, com o Dataset de API.

Outros formatos de entrada suportados

Além matrizes Numpy, tensores ansiosos e TensorFlow Datasets , é possível treinar um modelo Keras usando dataframes pandas, ou de geradores de Python que os lotes de rendimento de dados e etiquetas.

Em particular, os keras.utils.Sequence ofertas de classe de uma interface simples para construir geradores de dados Python que são multiprocessamento-conscientes e podem ser embaralhadas.

Em geral, recomendamos que você use:

  • Dados de entrada NumPy se seus dados forem pequenos e couberem na memória
  • Dataset objetos se você tem grandes conjuntos de dados e você precisa fazer o treinamento distribuídos
  • Sequence objetos se você tem grandes conjuntos de dados e você precisa fazer um monte de costume processamento Python-lado que não pode ser feito em TensorFlow (por exemplo, se você confiar em bibliotecas externas para o carregamento de dados ou pré-processamento).

Usando um keras.utils.Sequence objeto como entrada

keras.utils.Sequence é um utilitário que você pode subclasse para obter um gerador de Python com duas propriedades importantes:

  • Funciona bem com multiprocessamento.
  • Ele pode ser embaralhadas (por exemplo, ao passar shuffle=True no fit() ).

Uma Sequence deve implementar dois métodos:

  • __getitem__
  • __len__

O método __getitem__ deve retornar um lote completo. Se você deseja modificar o conjunto de dados entre épocas, você pode implementar on_epoch_end .

Aqui está um exemplo rápido:

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)

Usando ponderação de amostra e ponderação de classe

Com as configurações padrão, o peso de uma amostra é decidido por sua frequência no conjunto de dados. Existem dois métodos para ponderar os dados, independentemente da frequência da amostra:

  • Pesos de classe
  • Pesos de amostra

Pesos de classe

Isso é definido pela passagem de um dicionário para o class_weight argumento para Model.fit() . Este dicionário mapeia índices de classe para o peso que deve ser usado para amostras pertencentes a esta classe.

Isso pode ser usado para equilibrar classes sem reamostrar ou para treinar um modelo que dê mais importância a uma classe específica.

Por exemplo, se a classe "0" é meio como representado na classe "1" em seus dados, você pode usar Model.fit(..., class_weight={0: 1., 1: 0.5}) .

Aqui está um exemplo NumPy onde usamos pesos de classe ou pesos de amostra para dar mais importância à classificação correta da classe # 5 (que é o dígito "5" no conjunto de dados 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.3809 - sparse_categorical_accuracy: 0.8990
<keras.callbacks.History at 0x7f4af1b95b10>

Pesos de amostra

Para um controle refinado, ou se você não estiver construindo um classificador, você pode usar "pesos de amostra".

  • Quando o treinamento a partir de dados Numpy: Passe o sample_weight argumento para Model.fit() .
  • Ao treinar a partir tf.data ou qualquer outro tipo de iterator: Rendimento (input_batch, label_batch, sample_weight_batch) tuplas.

Uma matriz de "pesos de amostra" é uma matriz de números que especifica quanto peso cada amostra em um lote deve ter no cálculo da perda total. É comumente usado em problemas de classificação desequilibrada (a ideia é dar mais peso a classes raramente vistas).

Quando os pesos são utilizados uns e zeros, a matriz pode ser usado como uma máscara para a função de perda (inteiramente descartando a contribuição de certos amostras para a perda total).

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.3844 - sparse_categorical_accuracy: 0.8997
<keras.callbacks.History at 0x7f4af19ef1d0>

Aqui está uma correspondência Dataset exemplo:

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 3ms/step - loss: 0.3669 - sparse_categorical_accuracy: 0.9033
<keras.callbacks.History at 0x7f4af18a6dd0>

Passando dados para modelos de múltiplas entradas e saídas

Nos exemplos anteriores, foram considerando um modelo com uma única entrada (um tensor de forma (764,) ) e uma saída única (um tensor de predição de forma (10,) ). Mas e quanto aos modelos que têm várias entradas ou saídas?

Considere o seguinte modelo, que tem uma entrada de imagem de forma (32, 32, 3) (que da (height, width, channels) ) e uma entrada de séries cronológicas de forma (None, 10) (que é o (timesteps, features) ). Nosso modelo terá duas saídas computados a partir da combinação dessas entradas: uma "pontuação" (de forma (1,) ) e uma distribuição de probabilidade sobre cinco classes (de forma (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]
)

Vamos plotar este modelo, para que você possa ver claramente o que estamos fazendo aqui (observe que as formas mostradas no gráfico são formas de lote, em vez de formas por amostra).

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

png

No momento da compilação, podemos especificar diferentes perdas para diferentes saídas, passando as funções de perda como uma lista:

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

Se passássemos apenas uma única função de perda para o modelo, a mesma função de perda seria aplicada a todas as saídas (o que não é apropriado aqui).

Da mesma forma para métricas:

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

Como demos nomes às nossas camadas de saída, também podemos especificar perdas por saída e métricas por meio de um 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()],
    },
)

Recomendamos o uso de nomes e dictos explícitos se você tiver mais de 2 saídas.

É possível dar pesos diferentes para diferentes perdas específicas e saída (por exemplo, um pode querer privilegiar a perda de "pontuação" no nosso exemplo, dando a 2x a importância da perda de classe), usando o loss_weights argumento:

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

Você também pode optar por não calcular uma perda para determinadas saídas, se essas saídas forem destinadas para previsão, mas não para treinamento:

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

Passando dados para um multi-entrada ou modelo multi-saída no fit() funciona de forma semelhante como especificar uma função perda de compilação: você pode passar listas de matrizes Numpy (com 1: 1 mapeamento para as saídas que receberam uma função de perda ) ou dicts mapeando nomes de saída para matrizes 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 12ms/step - loss: 17.8110 - score_output_loss: 0.3258 - class_output_loss: 17.4852
4/4 [==============================] - 0s 5ms/step - loss: 20.9269 - score_output_loss: 0.2376 - class_output_loss: 20.6893
<keras.callbacks.History at 0x7f4c70c26bd0>

Aqui está o Dataset de caso de uso: da mesma forma como o que fizemos para arrays numpy, o Dataset deve retornar uma tupla de dicts.

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

model.fit(train_dataset, epochs=1)
2/2 [==============================] - 1s 24ms/step - loss: 20.7151 - score_output_loss: 0.2093 - class_output_loss: 20.5058
<keras.callbacks.History at 0x7f4af1955e10>

Usando callbacks

Callbacks no Keras são objetos que são chamados em diferentes pontos durante o treinamento (no início de uma época, no final de um lote, no final de uma época, etc.). Eles podem ser usados ​​para implementar certos comportamentos, como:

  • Fazer a validação em diferentes pontos durante o treinamento (além da validação integrada por época)
  • Verificar o modelo em intervalos regulares ou quando ele exceder um certo limite de precisão
  • Alterar a taxa de aprendizagem do modelo quando o treinamento parece estar em um patamar
  • Fazer o ajuste fino das camadas superiores quando o treinamento parece estar em um patamar
  • Envio de notificações por e-mail ou mensagem instantânea quando o treinamento termina ou quando um determinado limite de desempenho é excedido
  • Etc.

Retornos de chamada pode ser passado como uma lista para a sua chamada para 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.3584 - sparse_categorical_accuracy: 0.8986 - val_loss: 0.2179 - val_sparse_categorical_accuracy: 0.9345
Epoch 2/20
625/625 [==============================] - 1s 2ms/step - loss: 0.1624 - sparse_categorical_accuracy: 0.9520 - val_loss: 0.1745 - val_sparse_categorical_accuracy: 0.9465
Epoch 3/20
625/625 [==============================] - 1s 2ms/step - loss: 0.1205 - sparse_categorical_accuracy: 0.9642 - val_loss: 0.1472 - val_sparse_categorical_accuracy: 0.9557
Epoch 4/20
625/625 [==============================] - 1s 2ms/step - loss: 0.0962 - sparse_categorical_accuracy: 0.9704 - val_loss: 0.1441 - val_sparse_categorical_accuracy: 0.9572
Epoch 5/20
625/625 [==============================] - 1s 2ms/step - loss: 0.0819 - sparse_categorical_accuracy: 0.9749 - val_loss: 0.1451 - val_sparse_categorical_accuracy: 0.9589
Epoch 00005: early stopping
<keras.callbacks.History at 0x7f4b14273390>

Muitos retornos de chamada integrados estão disponíveis

Existem muitos retornos de chamada integrados já disponíveis no Keras, como:

  • ModelCheckpoint : Periodicamente salvar o modelo.
  • EarlyStopping : formação de parada quando o treinamento não é mais melhorar as métricas de validação.
  • TensorBoard : Registros modelo periodicamente gravação que podem ser visualizados em TensorBoard (mais detalhes no "Visualization" seção).
  • CSVLogger : córregos perda e métricas de dados para um arquivo CSV.
  • etc.

Veja a documentação retornos de chamada para a lista completa.

Escrevendo seu próprio retorno de chamada

Você pode criar um callback personalizada estendendo a classe base keras.callbacks.Callback . Um retorno de chamada tem acesso a seu modelo associado com a propriedade de classe self.model .

Certifique-se de ler o guia completo para escrever callbacks personalizados .

Aqui está um exemplo simples salvando uma lista de valores de perda por lote durante o treinamento:

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

Modelos de checkpoint

Quando você está treinando o modelo em conjuntos de dados relativamente grandes, é crucial salvar os pontos de verificação do seu modelo em intervalos frequentes.

A maneira mais fácil de conseguir isso é com o ModelCheckpoint callback:

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 3ms/step - loss: 0.3701 - sparse_categorical_accuracy: 0.8956 - val_loss: 0.2327 - val_sparse_categorical_accuracy: 0.9291

Epoch 00001: val_loss improved from inf to 0.23265, saving model to mymodel_1
2021-08-25 17:57:17.429907: W tensorflow/python/util/util.cc:348] 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
Epoch 2/2
625/625 [==============================] - 1s 2ms/step - loss: 0.1764 - sparse_categorical_accuracy: 0.9470 - val_loss: 0.1858 - val_sparse_categorical_accuracy: 0.9435

Epoch 00002: val_loss improved from 0.23265 to 0.18579, saving model to mymodel_2
INFO:tensorflow:Assets written to: mymodel_2/assets
<keras.callbacks.History at 0x7f4c71554f90>

O ModelCheckpoint callback pode ser usado para implementar a tolerância a falhas: a capacidade de reiniciar o treinamento do último estado salvo do modelo na formação caso é interrompido aleatoriamente. Aqui está um exemplo básico:

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
  78/1563 [>.............................] - ETA: 2s - loss: 1.1340 - sparse_categorical_accuracy: 0.7011INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=1.01/assets
 197/1563 [==>...........................] - ETA: 5s - loss: 0.7358 - sparse_categorical_accuracy: 0.8006INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.73/assets
 299/1563 [====>.........................] - ETA: 5s - loss: 0.6081 - sparse_categorical_accuracy: 0.8313INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.61/assets
 400/1563 [======>.......................] - ETA: 5s - loss: 0.5317 - sparse_categorical_accuracy: 0.8511INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.53/assets
 495/1563 [========>.....................] - ETA: 5s - loss: 0.4909 - sparse_categorical_accuracy: 0.8622INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.49/assets
 598/1563 [==========>...................] - ETA: 5s - loss: 0.4576 - sparse_categorical_accuracy: 0.8722INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.46/assets
 676/1563 [===========>..................] - ETA: 5s - loss: 0.4326 - sparse_categorical_accuracy: 0.8793INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.43/assets
 775/1563 [=============>................] - ETA: 4s - loss: 0.4063 - sparse_categorical_accuracy: 0.8858INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.40/assets
 900/1563 [================>.............] - ETA: 3s - loss: 0.3810 - sparse_categorical_accuracy: 0.8925INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.38/assets
 976/1563 [=================>............] - ETA: 3s - loss: 0.3710 - sparse_categorical_accuracy: 0.8954INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.37/assets
1076/1563 [===================>..........] - ETA: 2s - loss: 0.3563 - sparse_categorical_accuracy: 0.8991INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.35/assets
1199/1563 [======================>.......] - ETA: 2s - loss: 0.3409 - sparse_categorical_accuracy: 0.9033INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.34/assets
1297/1563 [=======================>......] - ETA: 1s - loss: 0.3281 - sparse_categorical_accuracy: 0.9069INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.33/assets
1396/1563 [=========================>....] - ETA: 0s - loss: 0.3193 - sparse_categorical_accuracy: 0.9092INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.32/assets
1498/1563 [===========================>..] - ETA: 0s - loss: 0.3086 - sparse_categorical_accuracy: 0.9123INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.31/assets
1563/1563 [==============================] - 10s 6ms/step - loss: 0.3029 - sparse_categorical_accuracy: 0.9138
<keras.callbacks.History at 0x7f4c71394b90>

Você também pode escrever seu próprio retorno de chamada para salvar e restaurar modelos.

Para um guia completo sobre serialização e economia, consulte o guia de poupança e serialização Models .

Usando programações de taxa de aprendizagem

Um padrão comum ao treinar modelos de aprendizado profundo é reduzir gradualmente o aprendizado à medida que o treinamento avança. Isso geralmente é conhecido como "redução da taxa de aprendizagem".

O cronograma de declínio de aprendizagem pode ser estático (fixado antecipadamente, em função da época atual ou do índice de lote atual) ou dinâmico (respondendo ao comportamento atual do modelo, em particular a perda de validação).

Passando uma programação para um otimizador

Você pode facilmente usar um cronograma decadência taxa de aprendizagem estática pela passagem de um objeto agenda como a learning_rate argumento em seu otimizador:

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)

Várias agendas built-in estão disponíveis: ExponentialDecay , PiecewiseConstantDecay , PolynomialDecay e InverseTimeDecay .

Usando callbacks para implementar uma programação de taxa de aprendizagem dinâmica

Um cronograma de taxa de aprendizado dinâmico (por exemplo, diminuindo a taxa de aprendizado quando a perda de validação não está mais melhorando) não pode ser alcançado com esses objetos de cronograma, uma vez que o otimizador não tem acesso às métricas de validação.

No entanto, os retornos de chamada têm acesso a todas as métricas, incluindo as métricas de validação! Você pode, portanto, atingir esse padrão usando um retorno de chamada que modifica a taxa de aprendizado atual no otimizador. Na verdade, esta é ainda built-in como o ReduceLROnPlateau callback.

Visualizando perda e métricas durante o treinamento

A melhor maneira de manter um olho em seu modelo durante o treinamento é usar TensorBoard - uma aplicação baseada em browser que pode ser executado localmente que lhe proporciona:

  • Parcelas ao vivo da perda e métricas para treinamento e avaliação
  • (opcionalmente) Visualizações dos histogramas de suas ativações de camada
  • (opcionalmente) 3D visualizações dos espaços incorporação aprendida por seus Embedding camadas

Se você instalou o TensorFlow com pip, poderá iniciar o TensorBoard na linha de comando:

tensorboard --logdir=/full_path_to_your_logs

Usando o retorno de chamada TensorBoard

A maneira mais fácil de usar TensorBoard com um modelo Keras eo fit() método é o TensorBoard callback.

No caso mais simples, apenas especifique onde deseja que o retorno de chamada grave os logs e pronto:

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

Para mais informações, consulte a documentação para o TensorBoard callback .