Formazione e valutazione con i metodi integrati

Visualizza su TensorFlow.org Esegui in Google Colab Visualizza la fonte su GitHub Scarica il 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 incorporati o scrivendo il tuo, il training e la valutazione del modello funzionano rigorosamente allo stesso modo su 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 delle 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, per dimostrare come utilizzare ottimizzatori, perdite e metriche.

Consideriamo il seguente modello (qui, costruiamo 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:

  • Addestramento
  • Convalida su un set di controllo generato dai dati di addestramento originali
  • Valutazione sui dati del test

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 del training (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.3483 - sparse_categorical_accuracy: 0.9025 - val_loss: 0.1949 - val_sparse_categorical_accuracy: 0.9443
Epoch 2/2
782/782 [==============================] - 2s 3ms/step - loss: 0.1611 - sparse_categorical_accuracy: 0.9519 - val_loss: 0.1420 - val_sparse_categorical_accuracy: 0.9612

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

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

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.1485 - sparse_categorical_accuracy: 0.9542
test loss, test acc: [0.1484519988298416, 0.954200029373169]
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 ogni output e puoi modulare il contributo di ogni 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 specificate tramite identificatori di stringa come scorciatoia:

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

Per un successivo riutilizzo, mettiamo la definizione del nostro modello e compiliamo il passo in functions; 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 da zero perdite, metriche o ottimizzatori personali, 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 personalizzate

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

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 che tu voglia utilizzare l'errore quadratico medio, ma con un termine aggiunto che disincentiverà i valori di previsione lontani da 0,5 (supponiamo che gli obiettivi categoriali siano codificati a caldo e assuma valori compresi tra 0 e 1). Questo crea un incentivo per il modello a non essere troppo sicuro di sé, il che può aiutare a ridurre il sovradattamento (non sapremo se funziona finché non ci proviamo!).

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

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_states(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_states(self):
        # The state of the metric will be reset at the start of each epoch.
        self.true_positives.assign(0.0)


model = get_uncompiled_model()
model.compile(
    optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
    loss=keras.losses.SparseCategoricalCrossentropy(),
    metrics=[CategoricalTruePositives()],
)
model.fit(x_train, y_train, batch_size=64, epochs=3)
Epoch 1/3
782/782 [==============================] - 2s 2ms/step - loss: 0.3441 - categorical_true_positives: 45120.0000
Epoch 2/3
 70/782 [=>............................] - ETA: 1s - loss: 0.1721 - categorical_true_positives: 4247.0000
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/metrics.py:257: UserWarning: Metric CategoricalTruePositives implements a `reset_states()` method; rename it to `reset_state()` (without the final "s"). The name `reset_states()` has been deprecated to improve API consistency.
  'consistency.' % (self.__class__.__name__,))
782/782 [==============================] - 2s 2ms/step - loss: 0.1625 - categorical_true_positives: 47585.0000
Epoch 3/3
782/782 [==============================] - 2s 2ms/step - loss: 0.1202 - categorical_true_positives: 48190.0000
<keras.callbacks.History at 0x7f4b14228910>

Gestire 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'uscita del modello - ma non tutti. 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, è 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 delle attività (nota che la regolarizzazione delle attività è incorporata in tutti i livelli 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: 2.5364
<keras.callbacks.History at 0x7f4b140acc50>

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.3495 - std_of_activation: 0.9820
<keras.callbacks.History at 0x7f4af21e3bd0>

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 2ms/step - loss: 2.4347 - std_of_activation: 0.0016
<keras.callbacks.History at 0x7f4af216d810>

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

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

Separazione automatica di un set di controllo della 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.3737 - sparse_categorical_accuracy: 0.8947 - val_loss: 0.2427 - val_sparse_categorical_accuracy: 0.9249
<keras.callbacks.History at 0x7f4af1847610>

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 2ms/step - loss: 0.3280 - sparse_categorical_accuracy: 0.9088
Epoch 2/3
782/782 [==============================] - 2s 2ms/step - loss: 0.1550 - sparse_categorical_accuracy: 0.9525
Epoch 3/3
782/782 [==============================] - 2s 2ms/step - loss: 0.1143 - sparse_categorical_accuracy: 0.9650
Evaluate
157/157 [==============================] - 0s 2ms/step - loss: 0.1126 - sparse_categorical_accuracy: 0.9659
{'loss': 0.11255467683076859,
 'sparse_categorical_accuracy': 0.9659000039100647}

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, ma continuiamo a disegnare i batch successivi. Il set di dati finirà per esaurire i dati (a meno che non sia 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: 0.8098 - sparse_categorical_accuracy: 0.8011
Epoch 2/3
100/100 [==============================] - 0s 2ms/step - loss: 0.3844 - sparse_categorical_accuracy: 0.8933
Epoch 3/3
100/100 [==============================] - 0s 2ms/step - loss: 0.3357 - sparse_categorical_accuracy: 0.9002
<keras.callbacks.History at 0x7f4af1f95150>

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 [==============================] - 2s 3ms/step - loss: 0.3319 - sparse_categorical_accuracy: 0.9069 - val_loss: 0.1979 - val_sparse_categorical_accuracy: 0.9418
<keras.callbacks.History at 0x7f4af1e3ce50>

Alla fine di ogni epoca, il modello itera sul set di dati di convalida e calcola 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 [==============================] - 2s 3ms/step - loss: 0.3502 - sparse_categorical_accuracy: 0.9024 - val_loss: 0.3006 - val_sparse_categorical_accuracy: 0.9125
<keras.callbacks.History at 0x7f4af1c9b050>

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:

  • NumPy immette 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
  • 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 classe

Con le impostazioni predefinite 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 associa gli indici di classe al peso che dovrebbe essere utilizzato per i campioni appartenenti a questa classe.

Questo può essere usato per bilanciare le classi senza ricampionare, o per addestrare un modello che dia più importanza a una particolare classe.

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 campione per dare più 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.3809 - sparse_categorical_accuracy: 0.8990
<keras.callbacks.History at 0x7f4af1b95b10>

Pesi campione

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 specifica quanto peso dovrebbe avere ciascun campione in un batch nel calcolo della perdita totale. È comunemente usato nei problemi di classificazione squilibrata (l'idea è di dare più peso alle 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 2ms/step - loss: 0.3844 - sparse_categorical_accuracy: 0.8997
<keras.callbacks.History at 0x7f4af19ef1d0>

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

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 per quanto riguarda i 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, in modo che tu possa 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

Al momento della compilazione, possiamo specificare perdite diverse su output diversi, passando le funzioni di perdita come 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 non è appropriato 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 i 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'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()},
)

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 12ms/step - loss: 17.8110 - score_output_loss: 0.3258 - class_output_loss: 17.4852
4/4 [==============================] - 0s 5ms/step - loss: 20.9269 - score_output_loss: 0.2376 - class_output_loss: 20.6893
<keras.callbacks.History at 0x7f4c70c26bd0>

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 [==============================] - 1s 24ms/step - loss: 20.7151 - score_output_loss: 0.2093 - class_output_loss: 20.5058
<keras.callbacks.History at 0x7f4af1955e10>

Utilizzo dei callback

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

  • Eseguire la convalida in diversi punti durante l'allenamento (oltre alla convalida per epoca integrata)
  • Checkpoint del modello a intervalli regolari o quando supera una certa soglia di precisione
  • Modificare il tasso di apprendimento del modello quando l'allenamento sembra stabilizzarsi
  • Eseguire la messa a punto degli strati superiori quando l'allenamento sembra stabilizzarsi
  • Invio di e-mail o notifiche di messaggi istantanei al termine dell'allenamento o al superamento di una determinata soglia di prestazione
  • 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.3584 - sparse_categorical_accuracy: 0.8986 - val_loss: 0.2179 - val_sparse_categorical_accuracy: 0.9345
Epoch 2/20
625/625 [==============================] - 1s 2ms/step - loss: 0.1624 - sparse_categorical_accuracy: 0.9520 - val_loss: 0.1745 - val_sparse_categorical_accuracy: 0.9465
Epoch 3/20
625/625 [==============================] - 1s 2ms/step - loss: 0.1205 - sparse_categorical_accuracy: 0.9642 - val_loss: 0.1472 - val_sparse_categorical_accuracy: 0.9557
Epoch 4/20
625/625 [==============================] - 1s 2ms/step - loss: 0.0962 - sparse_categorical_accuracy: 0.9704 - val_loss: 0.1441 - val_sparse_categorical_accuracy: 0.9572
Epoch 5/20
625/625 [==============================] - 1s 2ms/step - loss: 0.0819 - sparse_categorical_accuracy: 0.9749 - val_loss: 0.1451 - val_sparse_categorical_accuracy: 0.9589
Epoch 00005: early stopping
<keras.callbacks.History at 0x7f4b14273390>

Sono disponibili molti callback integrati

Ci sono molti callback incorporati già disponibili in Keras, come:

  • 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 il proprio callback

È 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 lotto 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 esegui il training del modello su set di dati relativamente grandi, è fondamentale salvare i checkpoint del tuo 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
625/625 [==============================] - 2s 3ms/step - loss: 0.3701 - sparse_categorical_accuracy: 0.8956 - val_loss: 0.2327 - val_sparse_categorical_accuracy: 0.9291

Epoch 00001: val_loss improved from inf to 0.23265, saving model to mymodel_1
2021-08-25 17:57:17.429907: W tensorflow/python/util/util.cc:348] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
INFO:tensorflow:Assets written to: mymodel_1/assets
Epoch 2/2
625/625 [==============================] - 1s 2ms/step - loss: 0.1764 - sparse_categorical_accuracy: 0.9470 - val_loss: 0.1858 - val_sparse_categorical_accuracy: 0.9435

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

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

Si chiama anche scrivere la propria richiamata per salvare e ripristinare i modelli.

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

Utilizzo delle pianificazioni del tasso di apprendimento

Un modello comune durante l'addestramento dei modelli di deep learning consiste nel ridurre gradualmente l'apprendimento man mano che l'addestramento progredisce. 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 (rispondente al comportamento corrente del modello, in particolare alla perdita di convalida).

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 un programma di tasso di apprendimento dinamico

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

Visualizzazione di perdite e 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 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)
<keras.callbacks.TensorBoard at 0x7f4bd50d7910>

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