![]() | ![]() | ![]() | ![]() |
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, se você estiver 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, para 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 nos dados do teste
Nós vamos usar 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 de 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.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
O retornado history
objeto mantém um registro dos valores de perda e valores métricas durante o treinamento:
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]}
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.1414 - sparse_categorical_accuracy: 0.9569 test loss, test acc: [0.14140386879444122, 0.9569000005722046] 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 tiver várias saídas, você poderá especificar diferentes perdas e métricas para cada saída e 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 precisará 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, Keras fornece duas maneiras de fazê-lo.
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.0162 <keras.callbacks.History at 0x7ff8881ba250>
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 irá desincentivar os valores de previsão longe de 0,5 (assumimos que os alvos categóricos são codificados em um hot e assumem valores entre 0 e 1). Isso cria um incentivo para que o modelo não seja muito confiante, o que pode ajudar a reduzir o overfitting (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.0388 <keras.callbacks.History at 0x7ff8882130d0>
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_state(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_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>
Lidar com perdas e métricas que não se encaixam 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 é incorporada em todas as camadas Keras -- essa camada é 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.4545 <keras.callbacks.History at 0x7ff87c53f310>
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.3461 - std_of_activation: 0.9929 <keras.callbacks.History at 0x7ff87c3d5bd0>
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 3ms/step - loss: 2.4647 - std_of_activation: 0.0017 <keras.callbacks.History at 0x7ff87c216f90>
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 414ms/step - loss: 0.9889 - binary_accuracy: 0.0000e+00 <keras.callbacks.History at 0x7ff87c0848d0>
Para mais informações sobre o treinamento modelos multi-entrada, consulte a seção Passando dados para multi-entrada, modelos multi-saída.
Definindo 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.3682 - sparse_categorical_accuracy: 0.8957 - val_loss: 0.2276 - val_sparse_categorical_accuracy: 0.9301 <keras.callbacks.History at 0x7ff81c680890>
Treinamento e Avaliação de Datasets 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 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}
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 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>
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 [==============================] - 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>
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 [==============================] - 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>
Observe que o conjunto de dados de validação será redefinido após cada uso (para que você sempre esteja avaliando as 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 são pequenos e cabem 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
nofit()
).
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 os índices de classe para o peso que deve ser usado para amostras pertencentes a esta classe.
Isso pode ser usado para balancear classes sem reamostragem ou para treinar um modelo que dê mais importância a uma determinada classe.
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 3ms/step - loss: 0.3708 - sparse_categorical_accuracy: 0.9032 <keras.callbacks.History at 0x7ff80c7ddd10>
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 paraModel.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 3ms/step - loss: 0.3806 - sparse_categorical_accuracy: 0.9000 <keras.callbacks.History at 0x7ff80c650350>
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 [==============================] - 3s 3ms/step - loss: 0.3588 - sparse_categorical_accuracy: 0.9070 <keras.callbacks.History at 0x7ff80c51cb50>
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 os 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 na plotagem 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)
Em tempo de compilação, podemos especificar perdas diferentes para saídas diferentes, 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 e métricas por saída 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 explícitos e dicts 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 à previsão, mas não ao 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 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>
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 [==============================] - 0s 21ms/step - loss: 4.2451 - score_output_loss: 0.0993 - class_output_loss: 4.1458 <keras.callbacks.History at 0x7ff80c3ed450>
Como usar retornos de chamada
Callbacks em 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:
- Fazendo validação em diferentes pontos durante o treinamento (além da validação integrada por época)
- Verificar o modelo em intervalos regulares ou quando excede um certo limiar de precisão
- Alterar a taxa de aprendizado do modelo quando o treinamento parece estar em um patamar
- Fazer ajuste fino das camadas superiores quando o treinamento parece ser platô
- Envio de e-mail ou notificações de mensagens instantâneas ao treinar termina ou onde um certo 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.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>
Muitos retornos internos estão disponíveis
Existem muitos retornos internos já disponíveis em 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, economizando 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 ponto de verificação
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 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>
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 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>
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 aprendizado
Um padrão comum ao treinar modelos de aprendizado profundo é reduzir gradualmente o aprendizado à medida que o treinamento avança. Isso é geralmente conhecido como "decaimento da taxa de aprendizado".
O cronograma de decaimento de aprendizado 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 à perda de validação).
Passando um agendamento 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
.
Como usar retornos de chamada para implementar uma programação dinâmica de taxa de aprendizado
Uma programação dinâmica de taxa de aprendizado (por exemplo, diminuir a taxa de aprendizado quando a perda de validação não está mais melhorando) não pode ser alcançada com esses objetos de programação, pois 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 métricas de validação! Assim, você pode alcançar 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:
- Gráficos 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 do TensorBoard
A maneira mais fácil de usar TensorBoard com um modelo Keras eo fit()
método é o TensorBoard
callback.
No caso mais simples, basta especificar onde você 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 0x7ff88c8c04d0>
Para mais informações, consulte a documentação para o TensorBoard
callback .