![]() | ![]() | ![]() | ![]() |
Impostare
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
introduzione
Questa guida copre i modelli di addestramento, valutazione e previsione (inferenza) quando si utilizzano API integrate per l'addestramento e la convalida (come Model.fit()
, Model.evaluate()
e Model.predict()
).
Se sei interessato a sfruttare fit()
mentre specifichi la tua funzione di fase di allenamento, consulta la guida Personalizzazione di ciò che accade in fit()
.
Se sei interessato a scrivere da zero i tuoi cicli di formazione e valutazione, consulta la guida "Scrivere un ciclo di formazione da zero" .
In generale, sia che tu stia utilizzando loop incorporati o scrivendone uno personalizzato, l'addestramento e la valutazione del modello funzionano esattamente allo stesso modo su ogni tipo di modello Keras: modelli sequenziali, modelli costruiti con l'API funzionale e modelli scritti da zero tramite sottoclasse di modelli.
Questa guida non copre la formazione distribuita, che è trattata nella nostra guida alla formazione multi-GPU e distribuita .
Panoramica API: un primo esempio end-to-end
Quando si passano i dati ai cicli di addestramento incorporati di un modello, è necessario utilizzare gli array NumPy (se i dati sono piccoli e si adattano alla memoria) o tf.data Dataset
oggetti tf.data Dataset
. Nei prossimi paragrafi, utilizzeremo il set di dati MNIST come array NumPy, al fine di dimostrare come utilizzare ottimizzatori, perdite e metriche.
Consideriamo il seguente modello (qui, lo incorporiamo con l'API funzionale, ma potrebbe essere anche un modello sequenziale o un modello sottoclasse):
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)
Ecco come appare il tipico flusso di lavoro end-to-end, composto da:
- Formazione
- Convalida su un set di controllo generato dai dati di addestramento originali
- Valutazione sui dati di prova
Useremo i dati MNIST per questo esempio.
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
# Preprocess the data (these are NumPy arrays)
x_train = x_train.reshape(60000, 784).astype("float32") / 255
x_test = x_test.reshape(10000, 784).astype("float32") / 255
y_train = y_train.astype("float32")
y_test = y_test.astype("float32")
# Reserve 10,000 samples for validation
x_val = x_train[-10000:]
y_val = y_train[-10000:]
x_train = x_train[:-10000]
y_train = y_train[:-10000]
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz 11493376/11490434 [==============================] - 0s 0us/step
Specifichiamo la configurazione dell'allenamento (ottimizzatore, perdita, metriche):
model.compile(
optimizer=keras.optimizers.RMSprop(), # Optimizer
# Loss function to minimize
loss=keras.losses.SparseCategoricalCrossentropy(),
# List of metrics to monitor
metrics=[keras.metrics.SparseCategoricalAccuracy()],
)
Chiamiamo fit()
, che addestrerà il modello suddividendo i dati in "batch" di dimensione batch_size
, e ripetutamente iterando sull'intero set di dati per un dato numero di epochs
.
print("Fit model on training data")
history = model.fit(
x_train,
y_train,
batch_size=64,
epochs=2,
# We pass some validation for
# monitoring validation loss and metrics
# at the end of each epoch
validation_data=(x_val, y_val),
)
Fit model on training data Epoch 1/2 782/782 [==============================] - 3s 3ms/step - loss: 0.5769 - sparse_categorical_accuracy: 0.8386 - val_loss: 0.1833 - val_sparse_categorical_accuracy: 0.9464 Epoch 2/2 782/782 [==============================] - 2s 2ms/step - loss: 0.1621 - sparse_categorical_accuracy: 0.9518 - val_loss: 0.1467 - val_sparse_categorical_accuracy: 0.9579
L'oggetto della history
restituito contiene un record dei valori di perdita e dei valori di metrica durante l'addestramento:
history.history
{'loss': [0.3323673903942108, 0.15159013867378235], 'sparse_categorical_accuracy': [0.9050800204277039, 0.9542400240898132], 'val_loss': [0.18328842520713806, 0.14667865633964539], 'val_sparse_categorical_accuracy': [0.946399986743927, 0.9578999876976013]}
Valutiamo il modello sui dati del test tramite evaluate()
:
# Evaluate the model on the test data using `evaluate`
print("Evaluate on test data")
results = model.evaluate(x_test, y_test, batch_size=128)
print("test loss, test acc:", results)
# Generate predictions (probabilities -- the output of the last layer)
# on new data using `predict`
print("Generate predictions for 3 samples")
predictions = model.predict(x_test[:3])
print("predictions shape:", predictions.shape)
Evaluate on test data 79/79 [==============================] - 0s 2ms/step - loss: 0.1449 - sparse_categorical_accuracy: 0.9539 test loss, test acc: [0.14493884146213531, 0.9538999795913696] Generate predictions for 3 samples predictions shape: (3, 10)
Ora, esaminiamo in dettaglio ogni parte di questo flusso di lavoro.
Il metodo compile()
: specifica di una perdita, metriche e un ottimizzatore
Per addestrare un modello con fit()
, è necessario specificare una funzione di perdita, un ottimizzatore e, facoltativamente, alcune metriche da monitorare.
Li passi al modello come argomenti al metodo compile()
:
model.compile(
optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
loss=keras.losses.SparseCategoricalCrossentropy(),
metrics=[keras.metrics.SparseCategoricalAccuracy()],
)
L'argomento delle metrics
dovrebbe essere un elenco: il tuo modello può avere un numero qualsiasi di metriche.
Se il tuo modello ha più output, puoi specificare diverse perdite e metriche per ogni output e puoi modulare il contributo di ogni output alla perdita totale del modello. Ulteriori dettagli su questo argomento sono disponibili nella sezione Passaggio di dati a modelli multi-input e multi-output .
Tieni presente che se sei soddisfatto delle impostazioni predefinite, in molti casi l'ottimizzatore, la perdita e le metriche possono essere specificati tramite identificatori di stringa come scorciatoia:
model.compile(
optimizer="rmsprop",
loss="sparse_categorical_crossentropy",
metrics=["sparse_categorical_accuracy"],
)
Per un successivo riutilizzo, inseriamo la definizione del modello e la fase di compilazione in functions; li chiameremo più volte attraverso diversi esempi in questa guida.
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
Sono disponibili molti ottimizzatori, perdite e metriche incorporati
In generale, non dovrai creare da zero le tue perdite, metriche o ottimizzatori, perché è probabile che ciò di cui hai bisogno faccia già parte dell'API di Keras:
Ottimizzatori:
-
SGD()
(con o senza quantità di moto) -
RMSprop()
-
Adam()
- eccetera.
Perdite:
-
MeanSquaredError()
-
KLDivergence()
-
CosineSimilarity()
- eccetera.
Metrica:
-
AUC()
-
Precision()
-
Recall()
- eccetera.
Perdite personalizzate
Se è necessario creare una perdita personalizzata, Keras fornisce due modi per farlo.
Il primo metodo prevede la creazione di una funzione che accetta gli input y_true
e y_pred
. L'esempio seguente mostra una funzione di perdita che calcola l'errore quadratico medio tra i dati reali e le previsioni:
def custom_mean_squared_error(y_true, y_pred):
return tf.math.reduce_mean(tf.square(y_true - y_pred))
model = get_uncompiled_model()
model.compile(optimizer=keras.optimizers.Adam(), loss=custom_mean_squared_error)
# We need to one-hot encode the labels to use MSE
y_train_one_hot = tf.one_hot(y_train, depth=10)
model.fit(x_train, y_train_one_hot, batch_size=64, epochs=1)
782/782 [==============================] - 1s 1ms/step - loss: 0.0272 <tensorflow.python.keras.callbacks.History at 0x7fb6b01c09e8>
Se hai bisogno di una funzione di perdita che accetta parametri accanto a y_true
e y_pred
, puoi sottoclassare la classe tf.keras.losses.Loss
e implementare i seguenti due metodi:
-
__init__(self)
: accetta i parametri da passare durante la chiamata della funzione di perdita -
call(self, y_true, y_pred)
: usa i target (y_true) e le previsioni del modello (y_pred) per calcolare la perdita del modello
Supponiamo che tu voglia utilizzare l'errore quadratico medio, ma con un termine aggiunto che deincentiverà i valori di previsione lontani da 0,5 (assumiamo che gli obiettivi categoriali siano codificati con una sola codifica e assumano valori compresi tra 0 e 1). Questo crea un incentivo per il modello a non essere troppo fiducioso, il che può aiutare a ridurre l'overfitting (non sapremo se funziona fino a quando non proveremo!).
Ecco come lo faresti:
class CustomMSE(keras.losses.Loss):
def __init__(self, regularization_factor=0.1, name="custom_mse"):
super().__init__(name=name)
self.regularization_factor = regularization_factor
def call(self, y_true, y_pred):
mse = tf.math.reduce_mean(tf.square(y_true - y_pred))
reg = tf.math.reduce_mean(tf.square(0.5 - y_pred))
return mse + reg * self.regularization_factor
model = get_uncompiled_model()
model.compile(optimizer=keras.optimizers.Adam(), loss=CustomMSE())
y_train_one_hot = tf.one_hot(y_train, depth=10)
model.fit(x_train, y_train_one_hot, batch_size=64, epochs=1)
782/782 [==============================] - 2s 2ms/step - loss: 0.0489 <tensorflow.python.keras.callbacks.History at 0x7fb6b00725f8>
Metriche personalizzate
Se hai bisogno di una metrica che non fa parte dell'API, puoi creare facilmente metriche personalizzate creando una sottoclasse della classe tf.keras.metrics.Metric
. Dovrai implementare 4 metodi:
-
__init__(self)
, in cui creerai variabili di stato per la tua metrica. -
update_state(self, y_true, y_pred, sample_weight=None)
, che utilizza gli obiettivi y_true e le previsioni del modello y_pred per aggiornare le variabili di stato. -
result(self)
, che utilizza le variabili di stato per calcolare i risultati finali. -
reset_states(self)
, che reinizializza lo stato della metrica.
L'aggiornamento dello stato e il calcolo dei risultati sono tenuti separati (rispettivamente in update_state()
e result()
) perché in alcuni casi il calcolo dei risultati potrebbe essere molto costoso e verrebbe eseguito solo periodicamente.
Ecco un semplice esempio che mostra come implementare una metrica CategoricalTruePositives
che conta quanti campioni sono stati correttamente classificati come appartenenti a una data 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.5782 - categorical_true_positives: 22110.9323 Epoch 2/3 782/782 [==============================] - 2s 2ms/step - loss: 0.1737 - categorical_true_positives: 23825.8212 Epoch 3/3 782/782 [==============================] - 2s 2ms/step - loss: 0.1254 - categorical_true_positives: 24152.4547 <tensorflow.python.keras.callbacks.History at 0x7fb6a42a55f8>
Gestione di perdite e metriche che non si adattano alla firma standard
La stragrande maggioranza delle perdite e delle metriche può essere calcolata da y_true
e y_pred
, dove y_pred
è un output del tuo modello, ma non tutte. Ad esempio, una perdita di regolarizzazione può richiedere solo l'attivazione di un livello (non ci sono obiettivi in questo caso) e questa attivazione potrebbe non essere un output del modello.
In questi casi, puoi chiamare self.add_loss(loss_value)
dall'interno del metodo di chiamata di un livello personalizzato. Le perdite aggiunte in questo modo vengono aggiunte alla perdita "principale" durante l'addestramento (quella passata a compile()
). Ecco un semplice esempio che aggiunge la regolarizzazione dell'attività (nota che la regolarizzazione dell'attività è incorporata in tutti i livelli di Keras - questo livello è solo per fornire un esempio 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: 3.4140 <tensorflow.python.keras.callbacks.History at 0x7fb6a4233748>
Puoi fare lo stesso per la registrazione dei valori delle metriche, utilizzando add_metric()
:
class MetricLoggingLayer(layers.Layer):
def call(self, inputs):
# The `aggregation` argument defines
# how to aggregate the per-batch values
# over each epoch:
# in this case we simply average them.
self.add_metric(
keras.backend.std(inputs), name="std_of_activation", aggregation="mean"
)
return inputs # Pass-through layer.
inputs = keras.Input(shape=(784,), name="digits")
x = layers.Dense(64, activation="relu", name="dense_1")(inputs)
# Insert std logging as a layer.
x = MetricLoggingLayer()(x)
x = layers.Dense(64, activation="relu", name="dense_2")(x)
outputs = layers.Dense(10, name="predictions")(x)
model = keras.Model(inputs=inputs, outputs=outputs)
model.compile(
optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
)
model.fit(x_train, y_train, batch_size=64, epochs=1)
782/782 [==============================] - 2s 2ms/step - loss: 0.5646 - std_of_activation: 0.9702 <tensorflow.python.keras.callbacks.History at 0x7fb6a40cf6a0>
Nell'API funzionale , puoi anche chiamare model.add_loss(loss_tensor)
o model.add_metric(metric_tensor, name, aggregation)
.
Ecco un semplice esempio:
inputs = keras.Input(shape=(784,), name="digits")
x1 = layers.Dense(64, activation="relu", name="dense_1")(inputs)
x2 = layers.Dense(64, activation="relu", name="dense_2")(x1)
outputs = layers.Dense(10, name="predictions")(x2)
model = keras.Model(inputs=inputs, outputs=outputs)
model.add_loss(tf.reduce_sum(x1) * 0.1)
model.add_metric(keras.backend.std(x1), name="std_of_activation", aggregation="mean")
model.compile(
optimizer=keras.optimizers.RMSprop(1e-3),
loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
)
model.fit(x_train, y_train, batch_size=64, epochs=1)
782/782 [==============================] - 2s 2ms/step - loss: 3.6195 - std_of_activation: 0.0020 <tensorflow.python.keras.callbacks.History at 0x7fb6a07d42b0>
Nota che quando passi le perdite tramite add_loss()
, diventa possibile chiamare compile()
senza una funzione di perdita, poiché il modello ha già una perdita da minimizzare.
Considera il seguente livello LogisticEndpoint
: prende come input obiettivi e logit e tiene traccia di una perdita di add_loss()
tramite add_loss()
. add_metric()
traccia anche dell'accuratezza della classificazione tramite 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)
Puoi usarlo in un modello con due input (dati di input e obiettivi), compilato senza un argomento di loss
, in questo modo:
import numpy as np
inputs = keras.Input(shape=(3,), name="inputs")
targets = keras.Input(shape=(10,), name="targets")
logits = keras.layers.Dense(10)(inputs)
predictions = LogisticEndpoint(name="predictions")(logits, targets)
model = keras.Model(inputs=[inputs, targets], outputs=predictions)
model.compile(optimizer="adam") # No loss argument!
data = {
"inputs": np.random.random((3, 3)),
"targets": np.random.random((3, 10)),
}
model.fit(data)
1/1 [==============================] - 0s 222ms/step - loss: 0.9652 - binary_accuracy: 0.0000e+00 <tensorflow.python.keras.callbacks.History at 0x7fb6a05e01d0>
Per ulteriori informazioni sull'addestramento di modelli con più input, vedere la sezione Passaggio di dati a modelli con più input e più output .
Messa a parte automatica di un set di esclusione di convalida
Nel primo esempio end-to-end che hai visto, abbiamo utilizzato l'argomento validation_data
per passare una tupla di array NumPy (x_val, y_val)
al modello per valutare una perdita di convalida e metriche di convalida alla fine di ogni epoca.
Ecco un'altra opzione: l'argomento validation_split
ti consente di riservare automaticamente parte dei tuoi dati di addestramento per la convalida. Il valore dell'argomento rappresenta la frazione dei dati da riservare per la convalida, quindi dovrebbe essere impostato su un numero maggiore di 0 e minore di 1. Ad esempio, validation_split=0.2
significa "usa il 20% dei dati per la convalida" e validation_split=0.6
significa "usa il 60% dei dati per la convalida".
Il modo in cui viene calcolata la convalida è prendendo gli ultimi x% di campioni degli array ricevuti dalla chiamata fit()
, prima di qualsiasi mescolamento.
Nota che puoi usare validation_split
solo quando ti alleni con i dati di NumPy.
model = get_compiled_model()
model.fit(x_train, y_train, batch_size=64, validation_split=0.2, epochs=1)
625/625 [==============================] - 2s 2ms/step - loss: 0.6075 - sparse_categorical_accuracy: 0.8389 - val_loss: 0.2291 - val_sparse_categorical_accuracy: 0.9322 <tensorflow.python.keras.callbacks.History at 0x7fb6a0504240>
Formazione e valutazione da tf.data Dataset
Negli ultimi paragrafi, hai visto come gestire perdite, metriche e ottimizzatori e hai visto come utilizzare gli argomenti validation_data
e validation_split
in fit()
, quando i tuoi dati vengono passati come array NumPy.
Diamo ora un'occhiata al caso in cui i tuoi dati arrivano sotto forma di un oggettotf.data.Dataset
.
L'API tf.data
è un set di utilità in TensorFlow 2.0 per il caricamento e la preelaborazione dei dati in modo veloce e scalabile.
Per una guida completa sulla creazione di Datasets
, vedere la documentazione di tf.data .
È possibile passare un'istanza del Dataset
direttamente ai metodi 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.5652 - sparse_categorical_accuracy: 0.8404 Epoch 2/3 782/782 [==============================] - 2s 2ms/step - loss: 0.1721 - sparse_categorical_accuracy: 0.9497 Epoch 3/3 782/782 [==============================] - 2s 2ms/step - loss: 0.1170 - sparse_categorical_accuracy: 0.9645 Evaluate 157/157 [==============================] - 0s 2ms/step - loss: 0.1308 - sparse_categorical_accuracy: 0.9602 {'loss': 0.13075917959213257, 'sparse_categorical_accuracy': 0.9602000117301941}
Notare che il set di dati viene ripristinato alla fine di ogni epoca, quindi può essere riutilizzato per l'epoca successiva.
Se si desidera eseguire l'addestramento solo su un numero specifico di batch da questo set di dati, è possibile passare l'argomento steps_per_epoch
, che specifica il numero di passaggi di addestramento che il modello deve eseguire utilizzando questo set di dati prima di passare all'epoca successiva.
Se lo fai, il set di dati non viene ripristinato alla fine di ogni epoca, ma continuiamo a disegnare i batch successivi. Il set di dati finirà per esaurire i dati (a meno che non si tratti di un set di dati a ciclo 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: 1.2664 - sparse_categorical_accuracy: 0.6389 Epoch 2/3 100/100 [==============================] - 0s 2ms/step - loss: 0.3868 - sparse_categorical_accuracy: 0.8875 Epoch 3/3 100/100 [==============================] - 0s 2ms/step - loss: 0.3578 - sparse_categorical_accuracy: 0.8981 <tensorflow.python.keras.callbacks.History at 0x7fb6a02a5358>
Utilizzo di un set di dati di convalida
Puoi passare un'istanza del Dataset
come argomento validation_data
in fit()
:
model = get_compiled_model()
# Prepare the training dataset
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)
# Prepare the validation dataset
val_dataset = tf.data.Dataset.from_tensor_slices((x_val, y_val))
val_dataset = val_dataset.batch(64)
model.fit(train_dataset, epochs=1, validation_data=val_dataset)
782/782 [==============================] - 2s 3ms/step - loss: 0.5754 - sparse_categorical_accuracy: 0.8384 - val_loss: 0.1829 - val_sparse_categorical_accuracy: 0.9465 <tensorflow.python.keras.callbacks.History at 0x7fb6a01651d0>
Alla fine di ogni epoca, il modello itererà sul set di dati di convalida e calcolerà la perdita di convalida e le metriche di convalida.
Se si desidera eseguire la convalida solo su un numero specifico di batch da questo set di dati, è possibile passare l'argomento validation_steps
, che specifica il numero di passaggi di convalida che il modello deve eseguire con il set di dati di convalida prima di interrompere la convalida e passare all'epoca successiva:
model = get_compiled_model()
# Prepare the training dataset
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)
# Prepare the validation dataset
val_dataset = tf.data.Dataset.from_tensor_slices((x_val, y_val))
val_dataset = val_dataset.batch(64)
model.fit(
train_dataset,
epochs=1,
# Only run validation using the first 10 batches of the dataset
# using the `validation_steps` argument
validation_data=val_dataset,
validation_steps=10,
)
782/782 [==============================] - 2s 2ms/step - loss: 0.5503 - sparse_categorical_accuracy: 0.8507 - val_loss: 0.3296 - val_sparse_categorical_accuracy: 0.9062 <tensorflow.python.keras.callbacks.History at 0x7fb6a02e4630>
Si noti che il set di dati di convalida verrà reimpostato dopo ogni utilizzo (in modo da valutare sempre gli stessi campioni da un'epoca all'altra).
L'argomento validation_split
(generando una serie di ritenuta da dati di addestramento) non è supportato quando formazione da Dataset
oggetti, poiché questa caratteristica richiede la capacità di indicizzare i campioni dei set di dati, che non è possibile in generale con il Dataset
API.
Altri formati di input supportati
Oltre agli array NumPy, ai tensori desiderosi e ai Datasets
TensorFlow, è possibile addestrare un modello Keras utilizzando i dataframe Pandas o da generatori Python che producono batch di dati ed etichette.
In particolare, la classe keras.utils.Sequence
offre una semplice interfaccia per creare generatori di dati Python che sono consapevoli del multiprocessing e possono essere mescolati.
In generale, ti consigliamo di utilizzare:
- NumPy inserisce i dati se i tuoi dati sono piccoli e si adattano alla memoria
-
Dataset
oggetti se si dispone di grandi quantità di dati ed è necessario fare formazione distribuita - Oggetti
Sequence
se si dispone di set di dati di grandi dimensioni ed è necessario eseguire molte elaborazioni lato Python personalizzate che non possono essere eseguite in TensorFlow (ad esempio, se si fa affidamento su librerie esterne per il caricamento o la preelaborazione dei dati).
Utilizzo di un oggetto keras.utils.Sequence
come input
keras.utils.Sequence
è un'utilità che puoi sottoclassare per ottenere un generatore Python con due importanti proprietà:
- Funziona bene con il multiprocessing.
- Può essere mescolato (es. Quando si passa
shuffle=True
infit()
).
Una Sequence
deve implementare due metodi:
-
__getitem__
-
__len__
Il metodo __getitem__
dovrebbe restituire un batch completo. Se vuoi modificare il tuo set di dati tra le epoche, puoi implementare on_epoch_end
.
Ecco un rapido esempio:
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)
Utilizzo della ponderazione del campione e della ponderazione della classe
Con le impostazioni di default il peso di un campione è deciso dalla sua frequenza nel dataset. Esistono due metodi per pesare i dati, indipendentemente dalla frequenza di campionamento:
- Pesi di classe
- Pesi campione
Pesi di classe
Questo è impostato passando un dizionario alla class_weight
argomento di Model.fit()
. Questo dizionario mappa gli indici di classe sul peso che dovrebbe essere usato per i campioni appartenenti a questa classe.
Questo può essere utilizzato per bilanciare le classi senza ricampionare o per addestrare un modello che dà più importanza a una particolare classe.
Ad esempio, se la classe "0" è rappresentata per metà dalla classe "1" nei dati, potresti utilizzare Model.fit(..., class_weight={0: 1., 1: 0.5})
.
Ecco un esempio di NumPy in cui usiamo pesi di classe o pesi campione per dare maggiore importanza alla corretta classificazione della classe # 5 (che è la cifra "5" nel set di dati MNIST).
import numpy as np
class_weight = {
0: 1.0,
1: 1.0,
2: 1.0,
3: 1.0,
4: 1.0,
# Set weight "2" for class "5",
# making this class 2x more important
5: 2.0,
6: 1.0,
7: 1.0,
8: 1.0,
9: 1.0,
}
print("Fit with class weight")
model = get_compiled_model()
model.fit(x_train, y_train, class_weight=class_weight, batch_size=64, epochs=1)
Fit with class weight 782/782 [==============================] - 2s 2ms/step - loss: 0.6269 - sparse_categorical_accuracy: 0.8396 <tensorflow.python.keras.callbacks.History at 0x7fb6ca2479b0>
Pesi campione
Per un controllo granulare o se non stai creando un classificatore, puoi utilizzare "pesi campione".
- Quando la formazione dai dati numpy: Passa la
sample_weight
argomento perModel.fit()
. - Durante l'addestramento da
tf.data
o qualsiasi altro tipo di iteratore: tuple di rendimento(input_batch, label_batch, sample_weight_batch)
.
Un array di "pesi campione" è un array di numeri che specifica quanto peso dovrebbe avere ciascun campione in un batch nel calcolo della perdita totale. È comunemente usato nei problemi di classificazione sbilanciata (l'idea è di dare più peso alle classi raramente viste).
Quando i pesi utilizzati sono uno e zero, l'array può essere utilizzato come maschera per la funzione di perdita (scartando completamente il contributo di alcuni campioni alla perdita totale).
sample_weight = np.ones(shape=(len(y_train),))
sample_weight[y_train == 5] = 2.0
print("Fit with sample weight")
model = get_compiled_model()
model.fit(x_train, y_train, sample_weight=sample_weight, batch_size=64, epochs=1)
Fit with sample weight 782/782 [==============================] - 2s 2ms/step - loss: 0.6540 - sparse_categorical_accuracy: 0.8302 <tensorflow.python.keras.callbacks.History at 0x7fb6b03db128>
Ecco un esempio di Dataset
corrispondente:
sample_weight = np.ones(shape=(len(y_train),))
sample_weight[y_train == 5] = 2.0
# Create a Dataset that includes sample weights
# (3rd element in the return tuple).
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train, sample_weight))
# Shuffle and slice the dataset.
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)
model = get_compiled_model()
model.fit(train_dataset, epochs=1)
782/782 [==============================] - 2s 2ms/step - loss: 0.6052 - sparse_categorical_accuracy: 0.8477 <tensorflow.python.keras.callbacks.History at 0x7fb6a40cc908>
Passaggio di dati a modelli multi-input e multi-output
Negli esempi precedenti, stavamo considerando un modello con un singolo input (un tensore di forma (764,)
) e un singolo output (un tensore di predizione di forma (10,)
). Ma per quanto riguarda i modelli che hanno più input o output?
Considera il seguente modello, che ha un input di immagine di forma (32, 32, 3)
(ovvero (height, width, channels)
) e un input di serie temporale di forma (None, 10)
(ovvero (timesteps, features)
). Il nostro modello avrà due output calcolati dalla combinazione di questi input: un "punteggio" (di forma (1,)
) e una distribuzione di probabilità su cinque classi (di 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]
)
Tracciamo questo modello, così puoi vedere chiaramente cosa stiamo facendo qui (nota che le forme mostrate nel grafico sono forme batch, piuttosto che forme per campione).
keras.utils.plot_model(model, "multi_input_and_output_model.png", show_shapes=True)
In fase di compilazione, possiamo specificare diverse perdite per diversi output, passando le funzioni di perdita come un elenco:
model.compile(
optimizer=keras.optimizers.RMSprop(1e-3),
loss=[keras.losses.MeanSquaredError(), keras.losses.CategoricalCrossentropy()],
)
Se passassimo solo una singola funzione di perdita al modello, la stessa funzione di perdita sarebbe applicata a ogni output (cosa non appropriata qui).
Allo stesso modo per le metriche:
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()],
],
)
Poiché abbiamo dato nomi ai nostri livelli di output, potremmo anche specificare perdite e metriche per output tramite un 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()],
},
)
Si consiglia di utilizzare nomi e dettami espliciti se si hanno più di 2 output.
È possibile assegnare pesi diversi a perdite specifiche di output differenti (ad esempio, si potrebbe desiderare di privilegiare la perdita di "punteggio" nel nostro esempio, dando a 2x l'importanza della perdita di classe), utilizzando l'argomento loss_weights
:
model.compile(
optimizer=keras.optimizers.RMSprop(1e-3),
loss={
"score_output": keras.losses.MeanSquaredError(),
"class_output": keras.losses.CategoricalCrossentropy(),
},
metrics={
"score_output": [
keras.metrics.MeanAbsolutePercentageError(),
keras.metrics.MeanAbsoluteError(),
],
"class_output": [keras.metrics.CategoricalAccuracy()],
},
loss_weights={"score_output": 2.0, "class_output": 1.0},
)
Puoi anche scegliere di non calcolare una perdita per determinati output, se questi output sono destinati alla previsione ma non all'addestramento:
# 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()},
)
Il passaggio di dati a un modello multi-input o multi-output in fit()
funziona in modo simile alla specifica di una funzione di perdita in compilazione: puoi passare elenchi di array NumPy (con mappatura 1: 1 agli output che hanno ricevuto una funzione di perdita ) o impone di mappare i nomi di output agli array NumPy .
model.compile(
optimizer=keras.optimizers.RMSprop(1e-3),
loss=[keras.losses.MeanSquaredError(), keras.losses.CategoricalCrossentropy()],
)
# Generate dummy NumPy data
img_data = np.random.random_sample(size=(100, 32, 32, 3))
ts_data = np.random.random_sample(size=(100, 20, 10))
score_targets = np.random.random_sample(size=(100, 1))
class_targets = np.random.random_sample(size=(100, 5))
# Fit on lists
model.fit([img_data, ts_data], [score_targets, class_targets], batch_size=32, epochs=1)
# Alternatively, fit on dicts
model.fit(
{"img_input": img_data, "ts_input": ts_data},
{"score_output": score_targets, "class_output": class_targets},
batch_size=32,
epochs=1,
)
4/4 [==============================] - 10s 10ms/step - loss: 12.4255 - score_output_loss: 0.7638 - class_output_loss: 11.6617 4/4 [==============================] - 0s 5ms/step - loss: 11.1176 - score_output_loss: 0.6303 - class_output_loss: 10.4873 <tensorflow.python.keras.callbacks.History at 0x7fb6a02ed828>
Ecco il Dataset
caso d'uso: allo stesso modo come quello che abbiamo fatto per gli array numpy, il Dataset
deve restituire una tupla di 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 27ms/step - loss: 10.9011 - score_output_loss: 0.4919 - class_output_loss: 10.4092 <tensorflow.python.keras.callbacks.History at 0x7fb6b00ae9e8>
Utilizzo dei callback
I callback in Keras sono oggetti che vengono richiamati in diversi punti durante l'allenamento (all'inizio di un'epoca, alla fine di un batch, alla fine di un'epoca, ecc.). Possono essere utilizzati per implementare determinati comportamenti, come ad esempio:
- Effettuare la convalida in diversi punti durante l'addestramento (oltre la convalida incorporata per epoca)
- Checkpoint del modello a intervalli regolari o quando supera una certa soglia di precisione
- Cambiare il tasso di apprendimento del modello quando la formazione sembra stabilizzarsi
- Fare la regolazione fine degli strati superiori quando l'allenamento sembra essere in plateau
- Invio di notifiche tramite posta elettronica o messaggi istantanei al termine della formazione o quando viene superata una determinata soglia di prestazioni
- Eccetera.
Le richiamate possono essere passate come elenco alla chiamata a fit()
:
model = get_compiled_model()
callbacks = [
keras.callbacks.EarlyStopping(
# Stop training when `val_loss` is no longer improving
monitor="val_loss",
# "no longer improving" being defined as "no better than 1e-2 less"
min_delta=1e-2,
# "no longer improving" being further defined as "for at least 2 epochs"
patience=2,
verbose=1,
)
]
model.fit(
x_train,
y_train,
epochs=20,
batch_size=64,
callbacks=callbacks,
validation_split=0.2,
)
Epoch 1/20 625/625 [==============================] - 2s 3ms/step - loss: 0.6076 - sparse_categorical_accuracy: 0.8350 - val_loss: 0.2323 - val_sparse_categorical_accuracy: 0.9306 Epoch 2/20 625/625 [==============================] - 1s 2ms/step - loss: 0.1925 - sparse_categorical_accuracy: 0.9436 - val_loss: 0.1828 - val_sparse_categorical_accuracy: 0.9446 Epoch 3/20 625/625 [==============================] - 1s 2ms/step - loss: 0.1310 - sparse_categorical_accuracy: 0.9616 - val_loss: 0.1580 - val_sparse_categorical_accuracy: 0.9510 Epoch 4/20 625/625 [==============================] - 1s 2ms/step - loss: 0.0967 - sparse_categorical_accuracy: 0.9700 - val_loss: 0.1681 - val_sparse_categorical_accuracy: 0.9490 Epoch 5/20 625/625 [==============================] - 1s 2ms/step - loss: 0.0841 - sparse_categorical_accuracy: 0.9742 - val_loss: 0.1482 - val_sparse_categorical_accuracy: 0.9568 Epoch 00005: early stopping <tensorflow.python.keras.callbacks.History at 0x7fb63c5945c0>
Sono disponibili molti callback incorporati
Ci sono molti callback incorporati già disponibili in Keras, come ad esempio:
-
ModelCheckpoint
: salva periodicamente il modello. -
EarlyStopping
: interrompi la formazione quando la formazione non migliora più le metriche di convalida. -
TensorBoard
: scrive periodicamente i log del modello che possono essere visualizzati in TensorBoard (maggiori dettagli nella sezione "Visualizzazione"). -
CSVLogger
: trasmette i dati di perdita e metriche a un file CSV. - eccetera.
Vedere la documentazione sui callback per l'elenco completo.
Scrivendo la tua richiamata
È possibile creare una richiamata personalizzata estendendo la classe di base keras.callbacks.Callback
. Un callback ha accesso al modello associato tramite la proprietà della classe self.model
.
Assicurati di leggere la guida completa alla scrittura di callback personalizzati .
Ecco un semplice esempio di salvataggio di un elenco di valori di perdita per batch durante l'addestramento:
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"))
Modelli di checkpoint
Quando si esegue l'addestramento del modello su set di dati relativamente grandi, è fondamentale salvare i punti di controllo del modello a intervalli frequenti.
Il modo più semplice per ottenere ciò è con il callback ModelCheckpoint
:
model = get_compiled_model()
callbacks = [
keras.callbacks.ModelCheckpoint(
# Path where to save the model
# The two parameters below mean that we will overwrite
# the current checkpoint if and only if
# the `val_loss` score has improved.
# The saved model name will include the current epoch.
filepath="mymodel_{epoch}",
save_best_only=True, # Only save a model if `val_loss` has improved.
monitor="val_loss",
verbose=1,
)
]
model.fit(
x_train, y_train, epochs=2, batch_size=64, callbacks=callbacks, validation_split=0.2
)
Epoch 1/2 625/625 [==============================] - 2s 2ms/step - loss: 0.6397 - sparse_categorical_accuracy: 0.8210 - val_loss: 0.2310 - val_sparse_categorical_accuracy: 0.9326 Epoch 00001: val_loss improved from inf to 0.23098, saving model to mymodel_1 INFO:tensorflow:Assets written to: mymodel_1/assets Epoch 2/2 625/625 [==============================] - 1s 2ms/step - loss: 0.1885 - sparse_categorical_accuracy: 0.9454 - val_loss: 0.1851 - val_sparse_categorical_accuracy: 0.9435 Epoch 00002: val_loss improved from 0.23098 to 0.18510, saving model to mymodel_2 INFO:tensorflow:Assets written to: mymodel_2/assets <tensorflow.python.keras.callbacks.History at 0x7fb6a04271d0>
Il callback ModelCheckpoint
può essere utilizzato per implementare la tolleranza agli errori: la capacità di riavviare l'addestramento dall'ultimo stato salvato del modello nel caso in cui l'addestramento venga interrotto in modo casuale. Ecco un esempio di base:
import os
# Prepare a directory to store all the checkpoints.
checkpoint_dir = "./ckpt"
if not os.path.exists(checkpoint_dir):
os.makedirs(checkpoint_dir)
def make_or_restore_model():
# Either restore the latest model, or create a fresh one
# if there is no checkpoint available.
checkpoints = [checkpoint_dir + "/" + name for name in os.listdir(checkpoint_dir)]
if checkpoints:
latest_checkpoint = max(checkpoints, key=os.path.getctime)
print("Restoring from", latest_checkpoint)
return keras.models.load_model(latest_checkpoint)
print("Creating a new model")
return get_compiled_model()
model = make_or_restore_model()
callbacks = [
# This callback saves a SavedModel every 100 batches.
# We include the training loss in the saved model name.
keras.callbacks.ModelCheckpoint(
filepath=checkpoint_dir + "/ckpt-loss={loss:.2f}", save_freq=100
)
]
model.fit(x_train, y_train, epochs=1, callbacks=callbacks)
Creating a new model 85/1563 [>.............................] - ETA: 2s - loss: 1.4465 - sparse_categorical_accuracy: 0.5717INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.93/assets 185/1563 [==>...........................] - ETA: 5s - loss: 1.1118 - sparse_categorical_accuracy: 0.6784INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.69/assets 284/1563 [====>.........................] - ETA: 5s - loss: 0.9495 - sparse_categorical_accuracy: 0.7266INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.58/assets 385/1563 [======>.......................] - ETA: 5s - loss: 0.8464 - sparse_categorical_accuracy: 0.7569INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.52/assets 485/1563 [========>.....................] - ETA: 5s - loss: 0.7749 - sparse_categorical_accuracy: 0.7776INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.47/assets 585/1563 [==========>...................] - ETA: 4s - loss: 0.7210 - sparse_categorical_accuracy: 0.7930INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.44/assets 685/1563 [============>.................] - ETA: 4s - loss: 0.6788 - sparse_categorical_accuracy: 0.8050INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.42/assets 785/1563 [==============>...............] - ETA: 4s - loss: 0.6445 - sparse_categorical_accuracy: 0.8149INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.40/assets 883/1563 [===============>..............] - ETA: 3s - loss: 0.6165 - sparse_categorical_accuracy: 0.8229INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.38/assets 984/1563 [=================>............] - ETA: 3s - loss: 0.5917 - sparse_categorical_accuracy: 0.8299INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.37/assets 1082/1563 [===================>..........] - ETA: 2s - loss: 0.5709 - sparse_categorical_accuracy: 0.8358INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.35/assets 1185/1563 [=====================>........] - ETA: 1s - loss: 0.5517 - sparse_categorical_accuracy: 0.8413INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.34/assets 1282/1563 [=======================>......] - ETA: 1s - loss: 0.5356 - sparse_categorical_accuracy: 0.8459INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.33/assets 1384/1563 [=========================>....] - ETA: 0s - loss: 0.5202 - sparse_categorical_accuracy: 0.8503INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.32/assets 1484/1563 [===========================>..] - ETA: 0s - loss: 0.5065 - sparse_categorical_accuracy: 0.8542INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.31/assets 1563/1563 [==============================] - 9s 5ms/step - loss: 0.4965 - sparse_categorical_accuracy: 0.8570 <tensorflow.python.keras.callbacks.History at 0x7fb6a036f5c0>
Chiami anche scrivi la tua richiamata per salvare e ripristinare i modelli.
Per una guida completa alla serializzazione e al salvataggio, vedere la guida al salvataggio e alla serializzazione dei modelli .
Utilizzo delle pianificazioni dei tassi di apprendimento
Un modello comune durante l'addestramento di modelli di apprendimento profondo consiste nel ridurre gradualmente l'apprendimento man mano che la formazione procede. Questo è generalmente noto come "decadimento del tasso di apprendimento".
Il programma di decadimento dell'apprendimento potrebbe essere statico (fissato in anticipo, in funzione dell'epoca corrente o dell'indice batch corrente), o dinamico (rispondendo al comportamento corrente del modello, in particolare alla perdita di convalida).
Passaggio di una pianificazione a un ottimizzatore
Puoi facilmente utilizzare un programma di decadimento della velocità di apprendimento statico passando un oggetto di pianificazione come argomento learning_rate
nel tuo ottimizzatore:
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)
Sono disponibili diversi programmi integrati: ExponentialDecay
, PiecewiseConstantDecay
, PolynomialDecay
e InverseTimeDecay
.
Utilizzo dei callback per implementare un programma di frequenza di apprendimento dinamico
Non è possibile ottenere un programma dinamico del tasso di apprendimento (ad esempio, diminuire il tasso di apprendimento quando la perdita di convalida non sta più migliorando) con questi oggetti di pianificazione, poiché l'ottimizzatore non ha accesso alle metriche di convalida.
Tuttavia, i callback hanno accesso a tutte le metriche, comprese le metriche di convalida! È quindi possibile ottenere questo modello utilizzando un callback che modifica la velocità di apprendimento corrente sull'ottimizzatore. In effetti, questo è anche integrato come callback ReduceLROnPlateau
.
Visualizzazione di perdite e metriche durante l'allenamento
Il modo migliore per tenere d'occhio il tuo modello durante l'addestramento è usare TensorBoard , un'applicazione basata su browser che puoi eseguire localmente che ti fornisce:
- Grafici in tempo reale della perdita e metriche per l'addestramento e la valutazione
- (facoltativamente) Visualizzazioni degli istogrammi delle attivazioni dei livelli
- (facoltativamente) visualizzazioni 3D degli spazi di incorporamento apprese dai livelli di
Embedding
Se hai installato TensorFlow con pip, dovresti essere in grado di avviare TensorBoard dalla riga di comando:
tensorboard --logdir=/full_path_to_your_logs
Utilizzo della richiamata TensorBoard
Il modo più semplice per utilizzare TensorBoard con un modello Keras e il metodo fit()
è il callback TensorBoard
.
Nel caso più semplice, specifica semplicemente dove vuoi che il callback scriva i log e sei a posto:
keras.callbacks.TensorBoard(
log_dir="/full_path_to_your_logs",
histogram_freq=0, # How often to log histogram visualizations
embeddings_freq=0, # How often to log embedding visualizations
update_freq="epoch",
) # How often to write logs (default: once per epoch)
<tensorflow.python.keras.callbacks.TensorBoard at 0x7fb6a422a748>
Per ulteriori informazioni, vedere la documentazione per il callback di TensorBoard
.