Formazione e valutazione con i metodi integrati

Mantieni tutto organizzato con le raccolte Salva e classifica i contenuti in base alle tue preferenze.

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

Impostare

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

introduzione

Questa formazione coperture di guida, la valutazione e la previsione (deduzione) modelli quando si utilizza built-in API per la formazione e la validazione (come Model.fit() , Model.evaluate() e Model.predict() ).

Se siete interessati a sfruttare fit() specificando la propria funzione step di formazione, vedere il Personalizzazione di ciò che avviene in fit() guida .

Se siete interessati a scrivere i propri cicli di formazione e di valutazione da zero, consultare la guida "scrivere un ciclo di formazione da zero" .

In generale, sia che tu stia utilizzando loop integrati o che tu stia scrivendo il tuo, l'addestramento e la valutazione del modello funzionano rigorosamente allo stesso modo in ogni tipo di modello Keras: modelli sequenziali, modelli creati con l'API funzionale e modelli scritti da zero tramite sottoclasse del modello.

Questa guida non copre la formazione distribuita, che è coperto nella nostra guida per multi-GPU e formazione distribuita .

Panoramica API: un primo esempio end-to-end

Quando si passa dati al built-in formazione anse di un modello, è necessario utilizzare sia le matrici NumPy (se i dati sono piccolo e si inserisce in memoria) o tf.data Dataset oggetti. 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, integriamo 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]

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 formerà il modello tagliando i dati in "lotti" di dimensioni batch_size , e ripetutamente iterare su tutto il set di dati per un determinato 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.3387 - sparse_categorical_accuracy: 0.9050 - val_loss: 0.1957 - val_sparse_categorical_accuracy: 0.9426
Epoch 2/2
782/782 [==============================] - 2s 3ms/step - loss: 0.1543 - sparse_categorical_accuracy: 0.9548 - val_loss: 0.1425 - val_sparse_categorical_accuracy: 0.9593

La tornato history oggetto detiene un record dei valori di perdita e valori metrici durante l'allenamento:

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

Valutiamo il modello sui dati di 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.1414 - sparse_categorical_accuracy: 0.9569
test loss, test acc: [0.14140386879444122, 0.9569000005722046]
Generate predictions for 3 samples
predictions shape: (3, 10)

Ora, esaminiamo in dettaglio ogni parte di questo flusso di lavoro.

La compile() metodo: specificare una perdita, le metriche e un ottimizzatore

Per addestrare un modello con fit() , è necessario specificare una funzione di perdita, un ottimizzatore, ed eventualmente, alcune metriche da monitorare.

Si passa questi per il modello come argomenti alla compile() Metodo:

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

Il metrics argomento dovrebbe essere una lista - il vostro modello può avere qualsiasi numero di metriche.

Se il tuo modello ha più output, puoi specificare perdite e metriche diverse per ciascun output e puoi modulare il contributo di ciascun output alla perdita totale del modello. Troverete maggiori dettagli su questo nei dati di passare al multi-input, sezione di modelli 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 nostra definizione del modello e compiliamo il passaggio nelle funzioni; li chiameremo più volte in 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 integrati

In generale, non dovrai creare le tue perdite, metriche o ottimizzatori da zero, perché è probabile che ciò di cui hai bisogno faccia già parte dell'API Keras:

Ottimizzatori:

  • SGD() (con o senza moto)
  • RMSprop()
  • Adam()
  • eccetera.

Perdite:

  • MeanSquaredError()
  • KLDivergence()
  • CosineSimilarity()
  • eccetera.

Metrica:

  • AUC()
  • Precision()
  • Recall()
  • eccetera.

Perdite doganali

Se devi creare una perdita personalizzata, Keras offre due modi per farlo.

Il primo metodo implica la creazione di una funzione che accetta ingressi 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 [==============================] - 2s 2ms/step - loss: 0.0162
<keras.callbacks.History at 0x7ff8881ba250>

Se avete bisogno di una funzione di perdita che prende nei parametri accanto y_true e y_pred , è possibile creare una sottoclasse del tf.keras.losses.Loss classe ed implementare i seguenti due metodi:

  • __init__(self) : accettare i parametri da passare durante la chiamata della funzione perdita
  • call(self, y_true, y_pred) : utilizzare i target (y_true) e le previsioni del modello (y_pred) per calcolare la perdita del modello

Supponiamo di voler utilizzare l'errore quadratico medio, ma con un termine aggiunto che deincentiverà i valori di previsione lontani da 0,5 (supponiamo che i target categoriali siano codificati a caldo e assumano valori compresi tra 0 e 1). Questo crea un incentivo per il modello a non essere troppo sicuro, il che può aiutare a ridurre l'overfitting (non sapremo se funziona finché non ci 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.0388
<keras.callbacks.History at 0x7ff8882130d0>

Metriche personalizzate

Se avete bisogno di una metrica che non fa parte delle API, è possibile creare facilmente metriche personalizzate dalla sottoclasse della tf.keras.metrics.Metric di classe. Dovrai implementare 4 metodi:

  • __init__(self) , in cui si creerà variabili di stato per la metrica.
  • update_state(self, y_true, y_pred, sample_weight=None) , che utilizza i target 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_state(self) , che reinizializza lo stato della metrica.

Aggiornamento dello stato e risultati di calcolo sono tenute separate (in update_state() e result() , rispettivamente) perché in alcuni casi, i risultati del calcolo può essere molto costoso e sarebbe fatto solo periodicamente.

Ecco un semplice esempio che mostra come implementare una CategoricalTruePositives metrica che conta quanti campioni sono stati correttamente classificati come appartenenti ad una determinata classe:

class CategoricalTruePositives(keras.metrics.Metric):
    def __init__(self, name="categorical_true_positives", **kwargs):
        super(CategoricalTruePositives, self).__init__(name=name, **kwargs)
        self.true_positives = self.add_weight(name="ctp", initializer="zeros")

    def update_state(self, y_true, y_pred, sample_weight=None):
        y_pred = tf.reshape(tf.argmax(y_pred, axis=1), shape=(-1, 1))
        values = tf.cast(y_true, "int32") == tf.cast(y_pred, "int32")
        values = tf.cast(values, "float32")
        if sample_weight is not None:
            sample_weight = tf.cast(sample_weight, "float32")
            values = tf.multiply(values, sample_weight)
        self.true_positives.assign_add(tf.reduce_sum(values))

    def result(self):
        return self.true_positives

    def reset_state(self):
        # The state of the metric will be reset at the start of each epoch.
        self.true_positives.assign(0.0)


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

Gestione delle perdite e delle 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'uscita del modello - ma non tutti. Ad esempio, una perdita di regolarizzazione può richiedere solo l'attivazione di un livello (in questo caso non ci sono obiettivi) e questa attivazione potrebbe non essere un output del modello.

In questi casi, è possibile chiamare self.add_loss(loss_value) dall'interno della chiamata al metodo di un livello personalizzato. Le perdite aggiunti in questo modo vengono aggiunti alla perdita "principale" durante l'allenamento (quello passato 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 serve 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: 2.4545
<keras.callbacks.History at 0x7ff87c53f310>

Si può fare lo stesso per l'accesso valori metrici, 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.3461 - std_of_activation: 0.9929
<keras.callbacks.History at 0x7ff87c3d5bd0>

Nel API funzionale , è anche possibile 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 3ms/step - loss: 2.4647 - std_of_activation: 0.0017
<keras.callbacks.History at 0x7ff87c216f90>

Si noti che quando si passa perdite tramite add_loss() , diventa possibile chiamata compile() senza funzione di perdita, dal momento che il modello ha già una perdita per ridurre al minimo.

Si consideri il seguente LogisticEndpoint strato: prende come ingressi obiettivi e logit, e tiene traccia una perdita crossentropy via add_loss() . Tiene traccia anche la precisione di 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)

Si può usare in un modello con due ingressi (dati e obiettivi di ingresso), compilate senza loss argomento, come questo:

import numpy as np

inputs = keras.Input(shape=(3,), name="inputs")
targets = keras.Input(shape=(10,), name="targets")
logits = keras.layers.Dense(10)(inputs)
predictions = LogisticEndpoint(name="predictions")(logits, targets)

model = keras.Model(inputs=[inputs, targets], outputs=predictions)
model.compile(optimizer="adam")  # No loss argument!

data = {
    "inputs": np.random.random((3, 3)),
    "targets": np.random.random((3, 10)),
}
model.fit(data)
1/1 [==============================] - 0s 414ms/step - loss: 0.9889 - binary_accuracy: 0.0000e+00
<keras.callbacks.History at 0x7ff87c0848d0>

Per ulteriori informazioni sulla formazione modelli multi-input, vedere la sezione Passaggio di dati multi-input, modelli multi-output.

Distinguere automaticamente un set di controlli di convalida

Nel primo esempio end-to-end che avete visto, abbiamo usato il validation_data argomento per passare una tupla di array NumPy (x_val, y_val) al modello per la valutazione di una perdita di convalida e metriche di validazione alla fine di ogni epoca.

Ecco un'altra opzione: l'argomento validation_split permette di parte automaticamente di riserva dei tuoi dati di allenamento per la convalida. Il valore di 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 20% dei dati per la validazione", e validation_split=0.6 significa "usa il 60% dei dati per la convalida".

Il modo in cui la validazione viene calcolato è prendendo i campioni% ultimi x delle schiere ricevuti dal fit() chiamata prima di ogni mescolamento.

Si noti che è possibile utilizzare solo validation_split quando la formazione con i dati NumPy.

model = get_compiled_model()
model.fit(x_train, y_train, batch_size=64, validation_split=0.2, epochs=1)
625/625 [==============================] - 2s 3ms/step - loss: 0.3682 - sparse_categorical_accuracy: 0.8957 - val_loss: 0.2276 - val_sparse_categorical_accuracy: 0.9301
<keras.callbacks.History at 0x7ff81c680890>

Formazione e valutazione da tf.data Datasets

Negli ultimi paragrafi, hai visto come gestire le perdite, metriche e ottimizzatori, e avete visto come utilizzare le validation_data e validation_split argomenti in fit() , quando i dati viene passato come array numpy.

Diamo ora uno sguardo al caso in cui i dati si presenta sotto forma di un tf.data.Dataset oggetto.

Il tf.data API è un insieme di utility in tensorflow 2.0 per il caricamento dei dati e pre-elaborazione in un modo che è veloce e scalabile.

Per una guida completa su come creare Datasets , consultare la documentazione di tf.data .

È possibile passare un Dataset un'istanza diretta 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 3ms/step - loss: 0.3372 - sparse_categorical_accuracy: 0.9047
Epoch 2/3
782/782 [==============================] - 2s 3ms/step - loss: 0.1596 - sparse_categorical_accuracy: 0.9523
Epoch 3/3
782/782 [==============================] - 2s 3ms/step - loss: 0.1171 - sparse_categorical_accuracy: 0.9655
Evaluate
157/157 [==============================] - 0s 2ms/step - loss: 0.1211 - sparse_categorical_accuracy: 0.9648
{'loss': 0.12107347697019577,
 'sparse_categorical_accuracy': 0.9648000001907349}

Si noti che il set di dati viene ripristinato alla fine di ogni epoca, quindi può essere riutilizzato dell'epoca successiva.

Se si desidera eseguire la formazione solo su un determinato numero di lotti da questo set di dati, è possibile passare l' steps_per_epoch argomento, che specifica quanti formazione passi il modello dovrebbe essere eseguito utilizzando questo set di dati prima di passare a quella successiva epoca.

Se lo fai, il set di dati non viene ripristinato alla fine di ogni epoca, invece 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 3ms/step - loss: 0.7937 - sparse_categorical_accuracy: 0.7894
Epoch 2/3
100/100 [==============================] - 0s 3ms/step - loss: 0.3699 - sparse_categorical_accuracy: 0.8938
Epoch 3/3
100/100 [==============================] - 0s 3ms/step - loss: 0.3155 - sparse_categorical_accuracy: 0.9061
<keras.callbacks.History at 0x7ff81c587e90>

Utilizzo di un set di dati di convalida

È possibile passare un Dataset esempio come il validation_data argomento fit() :

model = get_compiled_model()

# Prepare the training dataset
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)

# Prepare the validation dataset
val_dataset = tf.data.Dataset.from_tensor_slices((x_val, y_val))
val_dataset = val_dataset.batch(64)

model.fit(train_dataset, epochs=1, validation_data=val_dataset)
782/782 [==============================] - 3s 3ms/step - loss: 0.3380 - sparse_categorical_accuracy: 0.9035 - val_loss: 0.2015 - val_sparse_categorical_accuracy: 0.9405
<keras.callbacks.History at 0x7ff81c30e450>

Alla fine di ogni epoca, il modello eseguirà un'iterazione 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 determinato numero di lotti da questo insieme di dati, è possibile passare l' validation_steps argomento, che specifica quanti convalida passi il modello dovrebbe funzionare con il set di dati di validazione prima di interrompere la convalida e di passare alla successiva epoca:

model = get_compiled_model()

# Prepare the training dataset
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)

# Prepare the validation dataset
val_dataset = tf.data.Dataset.from_tensor_slices((x_val, y_val))
val_dataset = val_dataset.batch(64)

model.fit(
    train_dataset,
    epochs=1,
    # Only run validation using the first 10 batches of the dataset
    # using the `validation_steps` argument
    validation_data=val_dataset,
    validation_steps=10,
)
782/782 [==============================] - 3s 3ms/step - loss: 0.3369 - sparse_categorical_accuracy: 0.9036 - val_loss: 0.2953 - val_sparse_categorical_accuracy: 0.9187
<keras.callbacks.History at 0x7ff81c30e310>

Si noti che il set di dati di convalida verrà ripristinato 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 array NumPy, tensori ansiosi e tensorflow Datasets , è possibile formare un modello Keras utilizzando dataframes Pandas, o da generatori Python che i lotti rendimento di dati e etichette.

In particolare, le keras.utils.Sequence offerte di classe una semplice interfaccia per costruire generatori di dati Python che sono multiprocessing-aware e può essere mischiate.

In generale, ti consigliamo di utilizzare:

  • Dati di input NumPy 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
  • Sequence oggetti se si dispone di grandi quantità di dati e avete bisogno di fare un sacco di elaborazione personalizzata Python-side che non può essere fatto in tensorflow (ad esempio, se si basano su librerie esterne per il caricamento di dati o pre-elaborazione).

Utilizzando una keras.utils.Sequence oggetto come input

keras.utils.Sequence è un programma di utilità che si può sottoclasse di ottenere un generatore di Python con due proprietà importanti:

  • Funziona bene con il multiprocessing.
  • Può essere mischiato (ad esempio, quando si passa shuffle=True in fit() ).

Una Sequence deve implementare due metodi:

  • __getitem__
  • __len__

Il metodo __getitem__ deve restituire un lotto completo. Se si desidera modificare il set di dati tra le epoche, è possibile 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 predefinite il peso di un campione è deciso dalla sua frequenza nel set di dati. Esistono due metodi per ponderare i dati, indipendentemente dalla frequenza di campionamento:

  • Pesi di classe
  • Campioni di pesi

Pesi di classe

Questo è impostato passando un dizionario alla class_weight argomento di Model.fit() . Questo dizionario associa gli indici di classe al peso che dovrebbe essere utilizzato per i campioni appartenenti a questa classe.

Questo può essere utilizzato per bilanciare le classi senza ricampionare o per addestrare un modello che dia maggiore importanza a una classe particolare.

Per esempio, se la classe "0" è la metà rappresentato come classe "1" nei dati, è possibile utilizzare Model.fit(..., class_weight={0: 1., 1: 0.5}) .

Ecco un esempio NumPy in cui utilizziamo pesi di classe o pesi di esempio per dare maggiore importanza alla corretta classificazione della classe n. 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 3ms/step - loss: 0.3708 - sparse_categorical_accuracy: 0.9032
<keras.callbacks.History at 0x7ff80c7ddd10>

Campioni di pesi

Per un controllo a grana fine, o se non stai costruendo un classificatore, puoi usare "pesi campione".

  • Quando la formazione dai dati numpy: Passa la sample_weight argomento per Model.fit() .
  • Quando la formazione da tf.data o di qualsiasi altro tipo di iteratore: Yield (input_batch, label_batch, sample_weight_batch) tuple.

Un array di "pesi campione" è un array di numeri che specificano quanto peso dovrebbe avere ogni campione in un batch nel calcolo della perdita totale. È comunemente usato nei problemi di classificazione sbilanciati (l'idea è di dare più peso a classi raramente viste).

Quando i pesi utilizzati sono uno e zero, la matrice può essere utilizzata come maschera per la funzione di perdita (interamente scartando 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 3ms/step - loss: 0.3806 - sparse_categorical_accuracy: 0.9000
<keras.callbacks.History at 0x7ff80c650350>

Ecco un corrispondente Dataset Esempio:

sample_weight = np.ones(shape=(len(y_train),))
sample_weight[y_train == 5] = 2.0

# Create a Dataset that includes sample weights
# (3rd element in the return tuple).
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train, sample_weight))

# Shuffle and slice the dataset.
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)

model = get_compiled_model()
model.fit(train_dataset, epochs=1)
782/782 [==============================] - 3s 3ms/step - loss: 0.3588 - sparse_categorical_accuracy: 0.9070
<keras.callbacks.History at 0x7ff80c51cb50>

Passaggio di dati a modelli multi-input e multi-output

Negli esempi precedenti, stavamo considerando un modello con un solo ingresso (un tensore di forma (764,) ) ed una sola uscita (una previsione tensore di forma (10,) ). Ma che dire dei modelli che hanno più ingressi o uscite?

Si consideri il seguente modello, che ha un ingresso di immagini di forma (32, 32, 3) (che di (height, width, channels) ) e un ingresso di serie temporale di forma (None, 10) (che è (timesteps, features) ). Il nostro modello avrà due uscite calcolati dalla combinazione di questi ingressi: 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 perdite diverse a uscite diverse, 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 verrebbe applicata a ogni output (che qui non è appropriato).

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

Dato che abbiamo dato nomi ai nostri livelli di output, potremmo anche specificare le perdite e le 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 l'uso di nomi e dict espliciti se si dispone di più di 2 output.

E 'possibile dare peso diverso alle diverse perdite di uscita-specifici (per esempio, si potrebbe desiderare di privilegiare la perdita di "punteggio" nel nostro esempio, dando a 2x l'importanza della perdita di classe), utilizzando il loss_weights argomento:

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 pensati per la previsione ma non per l'allenamento:

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

# Or dict loss version
model.compile(
    optimizer=keras.optimizers.RMSprop(1e-3),
    loss={"class_output": keras.losses.CategoricalCrossentropy()},
)

Passando dati di un multi-ingresso o modello multi-output in fit() funziona in modo simile come specificare una funzione perdita di compilazione: è possibile passare elenchi di matrici NumPy (con 1: 1 mapping alle uscite che hanno ricevuto una funzione di perdita ) o dicts mappatura nomi di output per gli 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 [==============================] - 2s 9ms/step - loss: 5.6917 - score_output_loss: 0.1031 - class_output_loss: 5.5886
4/4 [==============================] - 0s 6ms/step - loss: 4.4108 - score_output_loss: 0.0999 - class_output_loss: 4.3109
<keras.callbacks.History at 0x7ff80c3b4110>

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 21ms/step - loss: 4.2451 - score_output_loss: 0.0993 - class_output_loss: 4.1458
<keras.callbacks.History at 0x7ff80c3ed450>

Utilizzo delle richiamate

I callback in Keras sono oggetti che vengono chiamati in punti diversi 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:

  • Esecuzione della convalida in diversi punti durante l'addestramento (oltre alla convalida per epoca incorporata)
  • Checkpoint del modello a intervalli regolari o quando supera una certa soglia di accuratezza
  • La modifica del tasso di apprendimento del modello quando l'allenamento sembra stabilizzarsi
  • La messa a punto degli strati superiori durante l'allenamento sembra stabilizzarsi
  • Invio di notifiche tramite e-mail o messaggi istantanei al termine della formazione o al superamento di una determinata soglia di prestazioni
  • Eccetera.

Callback possono essere passate come una lista al tuo invito fit() :

model = get_compiled_model()

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

Sono disponibili molte richiamate integrate

Ci sono molti callback integrati già disponibili in Keras, come ad esempio:

  • ModelCheckpoint : Periodicamente salvare il modello.
  • EarlyStopping : la formazione di arresto quando la formazione non è più migliorare le metriche di validazione.
  • TensorBoard : tronchi modello periodicamente scrittura che possono essere visualizzati in TensorBoard (maggiori dettagli nella sezione "Visualizzazione").
  • CSVLogger : flussi di dati di perdita e metriche in un file CSV.
  • eccetera.

Vedere la documentazione di callback per l'elenco completo.

Scrivere la propria richiamata

È possibile creare un callback personalizzata estendendo la classe base keras.callbacks.Callback . Una callback ha accesso al suo modello associato tramite la proprietà di classe self.model .

Assicurarsi di leggere la guida completa alla scrittura callback personalizzati .

Ecco un semplice esempio di salvataggio di un elenco di valori di perdita per batch durante l'allenamento:

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 il training del modello su set di dati relativamente grandi, è fondamentale salvare i checkpoint del modello a intervalli frequenti.

Il modo più semplice per raggiungere questo obiettivo è con il ModelCheckpoint callback:

model = get_compiled_model()

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

Il ModelCheckpoint richiamata può essere utilizzato per implementare la tolleranza d'errore: la capacità di formazione riavvio dall'ultimo stato salvato del modello nel caso in cui la formazione viene 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
  88/1563 [>.............................] - ETA: 3s - loss: 1.1203 - sparse_categorical_accuracy: 0.6911INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=1.04/assets
 185/1563 [==>...........................] - ETA: 6s - loss: 0.7768 - sparse_categorical_accuracy: 0.7858INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.75/assets
 286/1563 [====>.........................] - ETA: 6s - loss: 0.6382 - sparse_categorical_accuracy: 0.8211INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.63/assets
 383/1563 [======>.......................] - ETA: 6s - loss: 0.5584 - sparse_categorical_accuracy: 0.8433INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.55/assets
 484/1563 [========>.....................] - ETA: 6s - loss: 0.5032 - sparse_categorical_accuracy: 0.8578INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.50/assets
 586/1563 [==========>...................] - ETA: 5s - loss: 0.4644 - sparse_categorical_accuracy: 0.8684INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.46/assets
 685/1563 [============>.................] - ETA: 5s - loss: 0.4356 - sparse_categorical_accuracy: 0.8762INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.43/assets
 783/1563 [==============>...............] - ETA: 5s - loss: 0.4127 - sparse_categorical_accuracy: 0.8825INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.41/assets
 883/1563 [===============>..............] - ETA: 4s - loss: 0.3958 - sparse_categorical_accuracy: 0.8868INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.39/assets
 985/1563 [=================>............] - ETA: 3s - loss: 0.3766 - sparse_categorical_accuracy: 0.8918INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.38/assets
1086/1563 [===================>..........] - ETA: 3s - loss: 0.3624 - sparse_categorical_accuracy: 0.8958INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.36/assets
1184/1563 [=====================>........] - ETA: 2s - loss: 0.3498 - sparse_categorical_accuracy: 0.8994INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.35/assets
1283/1563 [=======================>......] - ETA: 1s - loss: 0.3383 - sparse_categorical_accuracy: 0.9029INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.34/assets
1386/1563 [=========================>....] - ETA: 1s - loss: 0.3265 - sparse_categorical_accuracy: 0.9058INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.33/assets
1485/1563 [===========================>..] - ETA: 0s - loss: 0.3184 - sparse_categorical_accuracy: 0.9081INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.32/assets
1563/1563 [==============================] - 11s 7ms/step - loss: 0.3122 - sparse_categorical_accuracy: 0.9097
<keras.callbacks.History at 0x7ff8b53e1dd0>

Si chiama anche scrivere la propria richiamata per il salvataggio e il ripristino dei modelli.

Per una guida completa su serializzazione e risparmio, consultare la guida al risparmio e serializzazione Models .

Utilizzo dei programmi del tasso di apprendimento

Un modello comune durante l'addestramento di modelli di deep learning è 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 può essere statico (fissato in anticipo, in funzione dell'epoca corrente o dell'indice batch corrente), o dinamico (in risposta al comportamento attuale del modello, in particolare alla perdita di validazione).

Passare una pianificazione a un ottimizzatore

Si può facilmente utilizzare un programma di tasso di decadimento di apprendimento statica passando un oggetto di pianificazione come il learning_rate argomento a vostra 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)

Varie pianificazioni incorporati sono disponibili: ExponentialDecay , PiecewiseConstantDecay , PolynomialDecay e InverseTimeDecay .

Utilizzo dei callback per implementare una pianificazione dinamica del tasso di apprendimento

Non è possibile ottenere una pianificazione dinamica della velocità di apprendimento (ad esempio, diminuendo la velocità di apprendimento quando la perdita di convalida non migliora) 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 realtà, questo è anche built-in come il ReduceLROnPlateau callback.

Visualizzazione della perdita e delle metriche durante l'allenamento

Il modo migliore per tenere d'occhio il vostro modello durante l'allenamento è quello di utilizzare TensorBoard - un'applicazione basata su browser che è possibile eseguire in locale che fornisce:

  • Grafici in tempo reale della perdita e metriche per la formazione e la valutazione
  • (opzionalmente) Visualizzazioni degli istogrammi delle attivazioni dei livelli
  • (opzionalmente) 3D visualizzazioni degli spazi embedding imparato dai vostri Embedding strati

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 fit() metodo è il TensorBoard callback.

Nel caso più semplice, specifica dove vuoi che la richiamata 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)
<keras.callbacks.TensorBoard at 0x7ff88c8c04d0>

Per ulteriori informazioni, consultare la documentazione per il TensorBoard callback .