Salva la data! Google I / O ritorna dal 18 al 20 maggio Registrati ora
Questa pagina è stata tradotta dall'API Cloud Translation.
Switch to English

Formazione e valutazione con i metodi incorporati

Visualizza su TensorFlow.org Esegui in Google Colab Visualizza sorgente su GitHub Scarica taccuino

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 in fit() ).

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 per Model.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)

png

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 .