Questa pagina è stata tradotta dall'API Cloud Translation.
Switch to English

Formazione e valutazione con i metodi incorporati

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

Impostare

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

introduzione

Questa guida copre i modelli di addestramento, valutazione e previsione (inferenza) quando si utilizzano API integrate per l'addestramento e la convalida (come model.fit() , model.evaluate() , model.predict() ).

Se sei interessato a sfruttare fit() mentre specifichi la tua funzione di fase di allenamento, consulta la guida "personalizzazione di ciò che accade in fit() " .

Se sei interessato a scrivere da zero i tuoi cicli di formazione e valutazione, consulta la guida "Scrivere un ciclo di formazione da zero" .

In generale, sia che tu stia utilizzando loop incorporati o scrivendone uno personalizzato, l'addestramento e la valutazione del modello funzionano esattamente allo stesso modo su ogni tipo di modello Keras: modelli sequenziali, modelli costruiti con l'API funzionale e modelli scritti da zero tramite sottoclasse di modelli.

Questa guida non copre la formazione distribuita. Per la formazione distribuita, consulta la nostra guida alla formazione multi-GPU e distribuita .

Panoramica API: un primo esempio end-to-end

Quando si passano i dati ai cicli di addestramento incorporati di un modello, è necessario utilizzare array NumPy (se i dati sono piccoli e si adattano alla memoria) o oggetti tf.data Dataset . Nei prossimi paragrafi, utilizzeremo il set di dati MNIST come array NumPy, al fine di dimostrare come utilizzare ottimizzatori, perdite e metriche.

Consideriamo il seguente modello (qui, incorporiamo l'API funzionale, ma potrebbe anche essere un modello sequenziale o anche 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 addestrerà il modello suddividendo i dati in "batch" di dimensione "batch_size", e ripetutamente iterando sull'intero set di dati per un dato numero di "epoche".

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 [==============================] - 2s 2ms/step - loss: 0.3425 - sparse_categorical_accuracy: 0.9034 - val_loss: 0.1827 - val_sparse_categorical_accuracy: 0.9478
Epoch 2/2
782/782 [==============================] - 2s 2ms/step - loss: 0.1618 - sparse_categorical_accuracy: 0.9513 - val_loss: 0.1282 - val_sparse_categorical_accuracy: 0.9651

L'oggetto "cronologia" restituito contiene una registrazione dei valori di perdita e dei valori metrici durante l'allenamento:

history.history
{'loss': [0.3424801528453827, 0.16180744767189026],
 'sparse_categorical_accuracy': [0.903439998626709, 0.9512799978256226],
 'val_loss': [0.18268445134162903, 0.12816601991653442],
 'val_sparse_categorical_accuracy': [0.9477999806404114, 0.9650999903678894]}

Valutiamo il modello sui dati del test tramite evaluate() :

# Evaluate the model on the test data using `evaluate`
print("Evaluate on test data")
results = model.evaluate(x_test, y_test, batch_size=128)
print("test loss, test acc:", results)

# Generate predictions (probabilities -- the output of the last layer)
# on new data using `predict`
print("Generate predictions for 3 samples")
predictions = model.predict(x_test[:3])
print("predictions shape:", predictions.shape)
Evaluate on test data
79/79 [==============================] - 0s 1ms/step - loss: 0.1310 - sparse_categorical_accuracy: 0.9637
test loss, test acc: [0.1309928148984909, 0.963699996471405]
Generate predictions for 3 samples
predictions shape: (3, 10)

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

Il metodo compile() : specifica di una perdita, metriche e un ottimizzatore

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

Li passi al modello come argomenti al metodo compile() :

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

L'argomento delle metrics dovrebbe essere un elenco: il tuo modello può avere un numero qualsiasi di metriche.

Se il modello ha più output, è possibile specificare diverse perdite e metriche per ogni output e modulare il contributo di ogni output alla perdita totale del modello. Ulteriori dettagli su questo argomento sono disponibili nella sezione "Passaggio di dati a modelli multi-input e multi-output" .

Tieni presente che se sei soddisfatto delle impostazioni predefinite, in molti casi l'ottimizzatore, la perdita e le metriche possono essere specificati tramite identificatori di stringa come scorciatoia:

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

Per un successivo riutilizzo, inseriamo la definizione del modello e la fase di compilazione in functions; li chiameremo più volte attraverso diversi esempi in questa guida.

def get_uncompiled_model():
    inputs = keras.Input(shape=(784,), name="digits")
    x = layers.Dense(64, activation="relu", name="dense_1")(inputs)
    x = layers.Dense(64, activation="relu", name="dense_2")(x)
    outputs = layers.Dense(10, activation="softmax", name="predictions")(x)
    model = keras.Model(inputs=inputs, outputs=outputs)
    return model


def get_compiled_model():
    model = get_uncompiled_model()
    model.compile(
        optimizer="rmsprop",
        loss="sparse_categorical_crossentropy",
        metrics=["sparse_categorical_accuracy"],
    )
    return model

Sono disponibili molti ottimizzatori, perdite e metriche incorporati

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

Ottimizzatori:

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

Perdite:

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

Metrica:

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

Perdite personalizzate

Esistono due modi per fornire perdite personalizzate con Keras. Il primo esempio crea una funzione che accetta gli input y_true e y_pred . L'esempio seguente mostra una funzione di perdita che calcola l'errore quadratico medio tra i dati reali e le previsioni:

def custom_mean_squared_error(y_true, y_pred):
    return tf.math.reduce_mean(tf.square(y_true - y_pred))


model = get_uncompiled_model()
model.compile(optimizer=keras.optimizers.Adam(), loss=custom_mean_squared_error)

# We need to one-hot encode the labels to use MSE
y_train_one_hot = tf.one_hot(y_train, depth=10)
model.fit(x_train, y_train_one_hot, batch_size=64, epochs=1)
782/782 [==============================] - 1s 1ms/step - loss: 0.0168

<tensorflow.python.keras.callbacks.History at 0x7f75581d56a0>

Se hai bisogno di una funzione di perdita che accetta parametri oltre a y_true e y_pred , puoi sottoclassare la classe tf.keras.losses.Loss e implementare i seguenti due metodi:

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

Supponiamo che tu voglia utilizzare l'errore quadratico medio, ma con un termine aggiunto che deincentiverà i valori di previsione lontani da 0,5 (assumiamo che gli obiettivi categoriali siano codificati a un punto e assumano valori compresi tra 0 e 1). Questo crea un incentivo per il modello a non essere troppo fiducioso, il che può aiutare a ridurre l'overfitting (non sapremo se funziona finché non proveremo!).

Ecco come lo faresti:

class CustomMSE(keras.losses.Loss):
    def __init__(self, regularization_factor=0.1, name="custom_mse"):
        super().__init__(name=name)
        self.regularization_factor = regularization_factor

    def call(self, y_true, y_pred):
        mse = tf.math.reduce_mean(tf.square(y_true - y_pred))
        reg = tf.math.reduce_mean(tf.square(0.5 - y_pred))
        return mse + reg * self.regularization_factor


model = get_uncompiled_model()
model.compile(optimizer=keras.optimizers.Adam(), loss=CustomMSE())

y_train_one_hot = tf.one_hot(y_train, depth=10)
model.fit(x_train, y_train_one_hot, batch_size=64, epochs=1)
782/782 [==============================] - 1s 2ms/step - loss: 0.0390

<tensorflow.python.keras.callbacks.History at 0x7f7558184c88>

Metriche personalizzate

Se hai bisogno di una metrica che non fa parte dell'API, puoi creare facilmente metriche personalizzate creando una sottoclasse della classe tf.keras.metrics.Metric . Dovrai implementare 4 metodi:

  • __init__(self) , in cui creerai variabili di stato per la tua metrica.
  • update_state(self, y_true, y_pred, sample_weight=None) , che utilizza gli obiettivi y_true e le previsioni del modello y_pred per aggiornare le variabili di stato.
  • result(self) , che utilizza le variabili di stato per calcolare i risultati finali.
  • reset_states(self) , che reinizializza lo stato della metrica.

L'aggiornamento dello stato e il calcolo dei risultati sono tenuti separati (rispettivamente in update_state() e result() ) perché in alcuni casi, il calcolo dei risultati potrebbe essere molto costoso e verrebbe eseguito solo periodicamente.

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

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

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

    def result(self):
        return self.true_positives

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


model = get_uncompiled_model()
model.compile(
    optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
    loss=keras.losses.SparseCategoricalCrossentropy(),
    metrics=[CategoricalTruePositives()],
)
model.fit(x_train, y_train, batch_size=64, epochs=3)
Epoch 1/3
782/782 [==============================] - 1s 2ms/step - loss: 0.3429 - categorical_true_positives: 45146.0000
Epoch 2/3
782/782 [==============================] - 1s 2ms/step - loss: 0.1560 - categorical_true_positives: 47637.0000
Epoch 3/3
782/782 [==============================] - 1s 2ms/step - loss: 0.1155 - categorical_true_positives: 48237.0000

<tensorflow.python.keras.callbacks.History at 0x7f755801bfd0>

Gestione di perdite e metriche che non si adattano alla firma standard

La stragrande maggioranza delle perdite e delle metriche può essere calcolata da y_true e y_pred , dove y_pred è un output del tuo modello. Ma non 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, puoi chiamare self.add_loss(loss_value) dall'interno del metodo di chiamata di un livello personalizzato. Le perdite aggiunte in questo modo vengono aggiunte alla perdita "principale" durante l'addestramento (quella passata a compile() ). Ecco un semplice esempio che aggiunge la regolarizzazione dell'attività (nota che la regolarizzazione dell'attività è incorporata in tutti i livelli di Keras - questo livello è solo per fornire un esempio concreto):

class ActivityRegularizationLayer(layers.Layer):
    def call(self, inputs):
        self.add_loss(tf.reduce_sum(inputs) * 0.1)
        return inputs  # Pass-through layer.


inputs = keras.Input(shape=(784,), name="digits")
x = layers.Dense(64, activation="relu", name="dense_1")(inputs)

# Insert activity regularization as a layer
x = ActivityRegularizationLayer()(x)

x = layers.Dense(64, activation="relu", name="dense_2")(x)
outputs = layers.Dense(10, name="predictions")(x)

model = keras.Model(inputs=inputs, outputs=outputs)
model.compile(
    optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
    loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
)

# The displayed loss will be much higher than before
# due to the regularization component.
model.fit(x_train, y_train, batch_size=64, epochs=1)
782/782 [==============================] - 1s 2ms/step - loss: 2.4756

<tensorflow.python.keras.callbacks.History at 0x7f75501e1f98>

Puoi fare lo stesso per registrare i valori delle metriche, utilizzando add_metric() :

class MetricLoggingLayer(layers.Layer):
    def call(self, inputs):
        # The `aggregation` argument defines
        # how to aggregate the per-batch values
        # over each epoch:
        # in this case we simply average them.
        self.add_metric(
            keras.backend.std(inputs), name="std_of_activation", aggregation="mean"
        )
        return inputs  # Pass-through layer.


inputs = keras.Input(shape=(784,), name="digits")
x = layers.Dense(64, activation="relu", name="dense_1")(inputs)

# Insert std logging as a layer.
x = MetricLoggingLayer()(x)

x = layers.Dense(64, activation="relu", name="dense_2")(x)
outputs = layers.Dense(10, name="predictions")(x)

model = keras.Model(inputs=inputs, outputs=outputs)
model.compile(
    optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
    loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
)
model.fit(x_train, y_train, batch_size=64, epochs=1)
782/782 [==============================] - 1s 2ms/step - loss: 0.3493 - std_of_activation: 0.9813

<tensorflow.python.keras.callbacks.History at 0x7f75500321d0>

Nell'API funzionale , puoi anche chiamare model.add_loss(loss_tensor) o model.add_metric(metric_tensor, name, aggregation) .

Ecco un semplice esempio:

inputs = keras.Input(shape=(784,), name="digits")
x1 = layers.Dense(64, activation="relu", name="dense_1")(inputs)
x2 = layers.Dense(64, activation="relu", name="dense_2")(x1)
outputs = layers.Dense(10, name="predictions")(x2)
model = keras.Model(inputs=inputs, outputs=outputs)

model.add_loss(tf.reduce_sum(x1) * 0.1)

model.add_metric(keras.backend.std(x1), name="std_of_activation", aggregation="mean")

model.compile(
    optimizer=keras.optimizers.RMSprop(1e-3),
    loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
)
model.fit(x_train, y_train, batch_size=64, epochs=1)
782/782 [==============================] - 1s 2ms/step - loss: 2.5230 - std_of_activation: 0.0020

<tensorflow.python.keras.callbacks.History at 0x7f74ec71d828>

Si noti che quando si passano le perdite tramite add_loss() , diventa possibile chiamare compile() senza una funzione di perdita, poiché il modello ha già una perdita da minimizzare.

Considera il seguente livello LogisticEndpoint : prende come input obiettivi e logit e tiene traccia di una perdita di add_loss() tramite add_loss() . add_metric() traccia anche dell'accuratezza della classificazione tramite add_metric() .

class LogisticEndpoint(keras.layers.Layer):
    def __init__(self, name=None):
        super(LogisticEndpoint, self).__init__(name=name)
        self.loss_fn = keras.losses.BinaryCrossentropy(from_logits=True)
        self.accuracy_fn = keras.metrics.BinaryAccuracy()

    def call(self, targets, logits, sample_weights=None):
        # Compute the training-time loss value and add it
        # to the layer using `self.add_loss()`.
        loss = self.loss_fn(targets, logits, sample_weights)
        self.add_loss(loss)

        # Log accuracy as a metric and add it
        # to the layer using `self.add_metric()`.
        acc = self.accuracy_fn(targets, logits, sample_weights)
        self.add_metric(acc, name="accuracy")

        # Return the inference-time prediction tensor (for `.predict()`).
        return tf.nn.softmax(logits)

Puoi usarlo in un modello con due input (dati di input e obiettivi), compilato senza un argomento di loss , in questo modo:

import numpy as np

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

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

data = {
    "inputs": np.random.random((3, 3)),
    "targets": np.random.random((3, 10)),
}
model.fit(data)
1/1 [==============================] - 0s 1ms/step - loss: 0.9344 - binary_accuracy: 0.0000e+00

<tensorflow.python.keras.callbacks.History at 0x7f7558339f28>

Per ulteriori informazioni sull'addestramento di modelli multi-input, vedere la sezione Passaggio di dati a modelli multi-input e multi-output .

Messa a parte automatica di un set di esclusione di convalida

Nel primo esempio end-to-end che hai visto, abbiamo utilizzato l'argomento validation_data per passare una tupla di array NumPy (x_val, y_val) al modello per valutare una perdita di convalida e metriche di convalida alla fine di ogni epoca.

Ecco un'altra opzione: l'argomento validation_split ti consente di riservare automaticamente parte dei tuoi dati di addestramento per la convalida. Il valore dell'argomento rappresenta la frazione dei dati da riservare per la convalida, quindi dovrebbe essere impostato su un numero maggiore di 0 e minore di 1. Ad esempio, validation_split=0.2 significa "usa il 20% dei dati per la convalida" e validation_split=0.6 significa "usa il 60% dei dati per la convalida".

Il modo in cui viene calcolata la convalida consiste nel prendere gli ultimi x% di campioni degli array ricevuti dalla chiamata fit, prima di qualsiasi mescolamento.

Nota che puoi usare validation_split solo quando ti alleni con i dati NumPy.

model = get_compiled_model()
model.fit(x_train, y_train, batch_size=64, validation_split=0.2, epochs=1)
625/625 [==============================] - 1s 2ms/step - loss: 0.3753 - sparse_categorical_accuracy: 0.8927 - val_loss: 0.2252 - val_sparse_categorical_accuracy: 0.9344

<tensorflow.python.keras.callbacks.History at 0x7f755826f160>

Formazione e valutazione da tf.data Dataset

Negli ultimi paragrafi, hai visto come gestire perdite, metriche e ottimizzatori e hai visto come utilizzare gli argomenti validation_data e validation_split in modo appropriato, quando i tuoi dati vengono passati come array NumPy.

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

L'API tf.data è un set di utilità in TensorFlow 2.0 per il caricamento e la preelaborazione dei dati in modo rapido e scalabile.

Per una guida completa sulla creazione di Datasets , vedere la documentazione di tf.data .

È possibile passare un'istanza del Dataset direttamente ai metodi fit() , evaluate() e predict() :

model = get_compiled_model()

# First, let's create a training Dataset instance.
# For the sake of our example, we'll use the same MNIST data as before.
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
# Shuffle and slice the dataset.
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)

# Now we get a test dataset.
test_dataset = tf.data.Dataset.from_tensor_slices((x_test, y_test))
test_dataset = test_dataset.batch(64)

# Since the dataset already takes care of batching,
# we don't pass a `batch_size` argument.
model.fit(train_dataset, epochs=3)

# You can also evaluate or predict on a dataset.
print("Evaluate")
result = model.evaluate(test_dataset)
dict(zip(model.metrics_names, result))
Epoch 1/3
782/782 [==============================] - 2s 2ms/step - loss: 0.3404 - sparse_categorical_accuracy: 0.9048
Epoch 2/3
782/782 [==============================] - 2s 2ms/step - loss: 0.1596 - sparse_categorical_accuracy: 0.9529
Epoch 3/3
782/782 [==============================] - 2s 2ms/step - loss: 0.1165 - sparse_categorical_accuracy: 0.9658
Evaluate
157/157 [==============================] - 0s 1ms/step - loss: 0.1147 - sparse_categorical_accuracy: 0.9659

{'loss': 0.11471886932849884,
 'sparse_categorical_accuracy': 0.9659000039100647}

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

Se si desidera eseguire l'addestramento solo su un numero specifico di batch da questo set di dati, è possibile passare l'argomento steps_per_epoch , che specifica il numero di passaggi di addestramento che il modello deve eseguire utilizzando questo set di dati prima di passare all'epoca successiva.

Se lo fai, il set di dati non viene ripristinato alla fine di ogni epoca, ma continuiamo a disegnare i batch successivi. Il set di dati finirà per esaurire i dati (a meno che non si tratti di un set di dati a ciclo continuo).

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 [==============================] - 0s 2ms/step - loss: 0.8448 - sparse_categorical_accuracy: 0.7734
Epoch 2/3
100/100 [==============================] - 0s 2ms/step - loss: 0.3912 - sparse_categorical_accuracy: 0.8922
Epoch 3/3
100/100 [==============================] - 0s 2ms/step - loss: 0.3399 - sparse_categorical_accuracy: 0.9011

<tensorflow.python.keras.callbacks.History at 0x7f74ec5cf7f0>

Utilizzo di un set di dati di convalida

Puoi passare un'istanza del Dataset come argomento validation_data in fit() :

model = get_compiled_model()

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

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

model.fit(train_dataset, epochs=1, validation_data=val_dataset)
782/782 [==============================] - 2s 2ms/step - loss: 0.3384 - sparse_categorical_accuracy: 0.9032 - val_loss: 0.1752 - val_sparse_categorical_accuracy: 0.9518

<tensorflow.python.keras.callbacks.History at 0x7f74ec4d2ba8>

Alla fine di ogni epoca, il modello itererà sul set di dati di convalida e calcolerà la perdita di convalida e le metriche di convalida.

Se si desidera eseguire la convalida solo su un numero specifico di batch da questo set di dati, è possibile passare l'argomento validation_steps , che specifica il numero di passaggi di convalida che il modello deve eseguire con il set di dati di convalida prima di interrompere la convalida e passare all'epoca successiva:

model = get_compiled_model()

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

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

model.fit(
    train_dataset,
    epochs=1,
    # Only run validation using the first 10 batches of the dataset
    # using the `validation_steps` argument
    validation_data=val_dataset,
    validation_steps=10,
)
782/782 [==============================] - 2s 2ms/step - loss: 0.3503 - sparse_categorical_accuracy: 0.9021 - val_loss: 0.3226 - val_sparse_categorical_accuracy: 0.9156

<tensorflow.python.keras.callbacks.History at 0x7f74ec4caa58>

Si noti che il set di dati di convalida verrà reimpostato dopo ogni utilizzo (in modo da valutare sempre gli stessi campioni da un'epoca all'altra).

L'argomento validation_split (generando una serie di ritenuta da dati di addestramento) non è supportato quando formazione da Dataset oggetti, poiché questa caratteristica richiede la capacità di indicizzare i campioni dei set di dati, che non è possibile in generale con il Dataset API.

Altri formati di input supportati

Oltre agli array NumPy, ai tensori desiderosi e ai Datasets TensorFlow, è possibile addestrare un modello Keras utilizzando i dataframe Pandas o da generatori Python che producono batch di dati ed etichette.

In particolare, la classe keras.utils.Sequence offre una semplice interfaccia per costruire generatori di dati Python che sono consapevoli del multiprocessing e possono essere mescolati.

In generale, ti consigliamo di utilizzare:

  • NumPy inserisce i dati se i tuoi dati sono piccoli e si adattano alla memoria
  • Dataset oggetti se si dispone di grandi quantità di dati ed è necessario fare formazione distribuita
  • Oggetti Sequence se si dispone di set di dati di grandi dimensioni ed è necessario eseguire molte elaborazioni lato Python personalizzate che non possono essere eseguite in TensorFlow (ad esempio, se si fa affidamento su librerie esterne per il caricamento o la preelaborazione dei dati).

Utilizzo di un oggetto keras.utils.Sequence come input

keras.utils.Sequence è un'utilità che puoi sottoclassare per ottenere un generatore Python con due importanti proprietà:

  • Funziona bene con il multiprocessing.
  • Può essere mescolato (es. Quando si passa shuffle=True in fit() ).

Una Sequence deve implementare due metodi:

  • __getitem__
  • __len__

Il metodo __getitem__ dovrebbe restituire un batch completo. Se vuoi modificare il tuo set di dati tra le epoche, puoi implementare on_epoch_end .

Ecco un rapido esempio:

from skimage.io import imread
from skimage.transform import resize
import numpy as np

# Here, `filenames` is list of path to the images
# and `labels` are the associated labels.

class CIFAR10Sequence(Sequence):
    def __init__(self, filenames, labels, batch_size):
        self.filenames, self.labels = filenames, labels
        self.batch_size = batch_size

    def __len__(self):
        return int(np.ceil(len(self.filenames) / float(self.batch_size)))

    def __getitem__(self, idx):
        batch_x = self.filenames[idx * self.batch_size:(idx + 1) * self.batch_size]
        batch_y = self.labels[idx * self.batch_size:(idx + 1) * self.batch_size]
        return np.array([
            resize(imread(filename), (200, 200))
               for filename in batch_x]), np.array(batch_y)

sequence = CIFAR10Sequence(filenames, labels, batch_size)
model.fit(sequence, epochs=10)

Utilizzo della ponderazione del campione e della ponderazione della classe

Con le impostazioni predefinite il peso di un campione è deciso dalla sua frequenza nel set di dati. Esistono due metodi per pesare i dati, indipendentemente dalla frequenza di campionamento:

  • Pesi di classe
  • Pesi campione

Pesi di classe

Questo è impostato passando un dizionario alla class_weight argomento di Model.fit() . Questo dizionario mappa gli indici delle classi sul peso che dovrebbe essere usato per i campioni appartenenti a questa classe.

Questo può essere utilizzato per bilanciare le classi senza ricampionare o per addestrare un modello che dà più importanza a una particolare classe.

Ad esempio, se la classe "0" è rappresentata per metà dalla classe "1" nei dati, puoi utilizzare Model.fit(..., class_weight={0: 1., 1: 0.5}) .

Ecco un esempio di NumPy in cui usiamo pesi di classe o pesi campione per dare maggiore importanza alla corretta classificazione della classe # 5 (che è la cifra "5" nel set di dati MNIST).

import numpy as np

class_weight = {
    0: 1.0,
    1: 1.0,
    2: 1.0,
    3: 1.0,
    4: 1.0,
    # Set weight "2" for class "5",
    # making this class 2x more important
    5: 2.0,
    6: 1.0,
    7: 1.0,
    8: 1.0,
    9: 1.0,
}

print("Fit with class weight")
model = get_compiled_model()
model.fit(x_train, y_train, class_weight=class_weight, batch_size=64, epochs=1)
Fit with class weight
782/782 [==============================] - 2s 2ms/step - loss: 0.3729 - sparse_categorical_accuracy: 0.9025

<tensorflow.python.keras.callbacks.History at 0x7f74ec265358>

Pesi campione

Per un controllo granulare o se non stai creando un classificatore, puoi utilizzare "pesi campione".

  • Quando la formazione dai dati numpy: Passa la sample_weight argomento per Model.fit() .
  • Durante l'addestramento da tf.data o da 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 viste raramente).

Quando i pesi utilizzati sono uno e zero, l'array può essere utilizzato come maschera per la funzione di perdita (scartando completamente il contributo di alcuni campioni alla perdita totale).

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

print("Fit with sample weight")
model = get_compiled_model()
model.fit(x_train, y_train, sample_weight=sample_weight, batch_size=64, epochs=1)
Fit with sample weight
782/782 [==============================] - 2s 2ms/step - loss: 0.3837 - sparse_categorical_accuracy: 0.8984

<tensorflow.python.keras.callbacks.History at 0x7f74ec11afd0>

Ecco un esempio di Dataset corrispondente:

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

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

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

model = get_compiled_model()
model.fit(train_dataset, epochs=1)
782/782 [==============================] - 2s 2ms/step - loss: 0.3792 - sparse_categorical_accuracy: 0.9030

<tensorflow.python.keras.callbacks.History at 0x7f74d47f2208>

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

Negli esempi precedenti, stavamo considerando un modello con un singolo input (un tensore di forma (764,) ) e un singolo output (un tensore di previsione (10,) ). Ma per quanto riguarda i modelli che hanno più input o output?

Considera il seguente modello, che ha un input di immagine di forma (32, 32, 3) (ovvero (height, width, channels) ) e un input di sequenza temporale di forma (None, 10) (ovvero (timesteps, features) ). Il nostro modello avrà due output calcolati dalla combinazione di questi input: un "punteggio" (di forma (1,) ) e una distribuzione di probabilità su cinque classi (di forma (5,) ).

image_input = keras.Input(shape=(32, 32, 3), name="img_input")
timeseries_input = keras.Input(shape=(None, 10), name="ts_input")

x1 = layers.Conv2D(3, 3)(image_input)
x1 = layers.GlobalMaxPooling2D()(x1)

x2 = layers.Conv1D(3, 3)(timeseries_input)
x2 = layers.GlobalMaxPooling1D()(x2)

x = layers.concatenate([x1, x2])

score_output = layers.Dense(1, name="score_output")(x)
class_output = layers.Dense(5, name="class_output")(x)

model = keras.Model(
    inputs=[image_input, timeseries_input], outputs=[score_output, class_output]
)

Tracciamo questo modello 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

In fase di compilazione, possiamo specificare diverse perdite per diversi output, 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 sarebbe applicata a ogni output (cosa non appropriata qui).

Allo stesso modo per le metriche:

model.compile(
    optimizer=keras.optimizers.RMSprop(1e-3),
    loss=[keras.losses.MeanSquaredError(), keras.losses.CategoricalCrossentropy()],
    metrics=[
        [
            keras.metrics.MeanAbsolutePercentageError(),
            keras.metrics.MeanAbsoluteError(),
        ],
        [keras.metrics.CategoricalAccuracy()],
    ],
)

Poiché abbiamo dato nomi ai nostri livelli di output, potremmo anche specificare 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 di utilizzare nomi e dettami espliciti se si hanno più di 2 output.

È possibile assegnare pesi diversi a diverse perdite specifiche dell'output (ad esempio, si potrebbe desiderare di privilegiare la perdita di "punteggio" nel nostro esempio, attribuendo a 2x l'importanza della perdita di classe), utilizzando l'argomento loss_weights :

model.compile(
    optimizer=keras.optimizers.RMSprop(1e-3),
    loss={
        "score_output": keras.losses.MeanSquaredError(),
        "class_output": keras.losses.CategoricalCrossentropy(),
    },
    metrics={
        "score_output": [
            keras.metrics.MeanAbsolutePercentageError(),
            keras.metrics.MeanAbsoluteError(),
        ],
        "class_output": [keras.metrics.CategoricalAccuracy()],
    },
    loss_weights={"score_output": 2.0, "class_output": 1.0},
)

È anche possibile scegliere di non calcolare una perdita per determinati output, se questi output sono destinati alla previsione ma non all'addestramento:

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

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

Il passaggio di dati a un modello multi-input o multi-output in modalità fit funziona in modo simile alla specifica di una funzione di perdita in compilazione: puoi passare elenchi di array NumPy (con mappatura 1: 1 agli output che hanno ricevuto una funzione di perdita) o detta la mappatura dei nomi di output agli array NumPy .

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

# Generate dummy NumPy data
img_data = np.random.random_sample(size=(100, 32, 32, 3))
ts_data = np.random.random_sample(size=(100, 20, 10))
score_targets = np.random.random_sample(size=(100, 1))
class_targets = np.random.random_sample(size=(100, 5))

# Fit on lists
model.fit([img_data, ts_data], [score_targets, class_targets], batch_size=32, epochs=1)

# Alternatively, fit on dicts
model.fit(
    {"img_input": img_data, "ts_input": ts_data},
    {"score_output": score_targets, "class_output": class_targets},
    batch_size=32,
    epochs=1,
)
4/4 [==============================] - 0s 6ms/step - loss: 20.0184 - score_output_loss: 0.5383 - class_output_loss: 19.4800
4/4 [==============================] - 0s 4ms/step - loss: 17.7266 - score_output_loss: 0.3122 - class_output_loss: 17.4145

<tensorflow.python.keras.callbacks.History at 0x7f755022feb8>

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 8ms/step - loss: 17.2156 - score_output_loss: 0.2522 - class_output_loss: 16.9634

<tensorflow.python.keras.callbacks.History at 0x7f75c56c1128>

Utilizzo dei callback

I callback in Keras sono oggetti che vengono chiamati in diversi punti durante l'allenamento (all'inizio di un'epoca, alla fine di un batch, alla fine di un'epoca, ecc.) E che possono essere utilizzati per implementare comportamenti come:

  • Effettuare la convalida in diversi punti durante l'addestramento (oltre la convalida incorporata per epoca)
  • Checkpoint del modello a intervalli regolari o quando supera una certa soglia di precisione
  • Cambiare il tasso di apprendimento del modello quando la formazione sembra stabilizzarsi
  • Fare la regolazione fine degli strati superiori quando l'allenamento sembra essere in plateau
  • Invio di notifiche tramite posta elettronica o messaggi istantanei al termine della formazione o quando viene superata una determinata soglia di prestazioni
  • Eccetera.

I callback possono essere passati come elenco alla chiamata a fit() :

model = get_compiled_model()

callbacks = [
    keras.callbacks.EarlyStopping(
        # Stop training when `val_loss` is no longer improving
        monitor="val_loss",
        # "no longer improving" being defined as "no better than 1e-2 less"
        min_delta=1e-2,
        # "no longer improving" being further defined as "for at least 2 epochs"
        patience=2,
        verbose=1,
    )
]
model.fit(
    x_train,
    y_train,
    epochs=20,
    batch_size=64,
    callbacks=callbacks,
    validation_split=0.2,
)
Epoch 1/20
625/625 [==============================] - 1s 2ms/step - loss: 0.3816 - sparse_categorical_accuracy: 0.8913 - val_loss: 0.2325 - val_sparse_categorical_accuracy: 0.9304
Epoch 2/20
625/625 [==============================] - 1s 2ms/step - loss: 0.1773 - sparse_categorical_accuracy: 0.9477 - val_loss: 0.2088 - val_sparse_categorical_accuracy: 0.9343
Epoch 3/20
625/625 [==============================] - 1s 2ms/step - loss: 0.1293 - sparse_categorical_accuracy: 0.9606 - val_loss: 0.1515 - val_sparse_categorical_accuracy: 0.9568
Epoch 4/20
625/625 [==============================] - 1s 2ms/step - loss: 0.1009 - sparse_categorical_accuracy: 0.9700 - val_loss: 0.1376 - val_sparse_categorical_accuracy: 0.9607
Epoch 5/20
625/625 [==============================] - 1s 2ms/step - loss: 0.0821 - sparse_categorical_accuracy: 0.9747 - val_loss: 0.1533 - val_sparse_categorical_accuracy: 0.9545
Epoch 6/20
625/625 [==============================] - 1s 2ms/step - loss: 0.0704 - sparse_categorical_accuracy: 0.9794 - val_loss: 0.1319 - val_sparse_categorical_accuracy: 0.9616
Epoch 00006: early stopping

<tensorflow.python.keras.callbacks.History at 0x7f74d46abdd8>

Sono disponibili molti callback incorporati

  • ModelCheckpoint : salva periodicamente il modello.
  • EarlyStopping : interrompi la formazione quando la formazione non migliora più le metriche di convalida.
  • TensorBoard : scrivi periodicamente log del modello che possono essere visualizzati in TensorBoard (maggiori dettagli nella sezione "Visualizzazione").
  • CSVLogger : trasmette i dati di perdita e metriche a un file CSV.
  • eccetera.

Vedere la documentazione sui callback per l'elenco completo.

Scrivendo la tua richiamata

È possibile creare una richiamata personalizzata estendendo la classe di base keras.callbacks.Callback . Un callback ha accesso al modello associato tramite la proprietà della classe self.model .

Assicurati di leggere la guida completa alla scrittura di callback personalizzati .

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

class LossHistory(keras.callbacks.Callback):
    def on_train_begin(self, logs):
        self.per_batch_losses = []

    def on_batch_end(self, batch, logs):
        self.per_batch_losses.append(logs.get("loss"))

Modelli di checkpoint

Quando si esegue l'addestramento del modello su set di dati relativamente grandi, è fondamentale salvare i punti di controllo del modello a intervalli frequenti.

Il modo più semplice per ottenere ciò è con il callback ModelCheckpoint :

model = get_compiled_model()

callbacks = [
    keras.callbacks.ModelCheckpoint(
        # Path where to save the model
        # The two parameters below mean that we will overwrite
        # the current checkpoint if and only if
        # the `val_loss` score has improved.
        # The saved model name will include the current epoch.
        filepath="mymodel_{epoch}",
        save_best_only=True,  # Only save a model if `val_loss` has improved.
        monitor="val_loss",
        verbose=1,
    )
]
model.fit(
    x_train, y_train, epochs=2, batch_size=64, callbacks=callbacks, validation_split=0.2
)
Epoch 1/2
608/625 [============================>.] - ETA: 0s - loss: 0.3797 - sparse_categorical_accuracy: 0.8940
Epoch 00001: val_loss improved from inf to 0.23986, saving model to mymodel_1
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/training/tracking/tracking.py:111: Model.state_updates (from tensorflow.python.keras.engine.training) is deprecated and will be removed in a future version.
Instructions for updating:
This property should not be used in TensorFlow 2.0, as updates are applied automatically.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/training/tracking/tracking.py:111: Layer.updates (from tensorflow.python.keras.engine.base_layer) is deprecated and will be removed in a future version.
Instructions for updating:
This property should not be used in TensorFlow 2.0, as updates are applied automatically.
INFO:tensorflow:Assets written to: mymodel_1/assets
625/625 [==============================] - 2s 3ms/step - loss: 0.3765 - sparse_categorical_accuracy: 0.8949 - val_loss: 0.2399 - val_sparse_categorical_accuracy: 0.9276
Epoch 2/2
606/625 [============================>.] - ETA: 0s - loss: 0.1758 - sparse_categorical_accuracy: 0.9474
Epoch 00002: val_loss improved from 0.23986 to 0.19765, saving model to mymodel_2
INFO:tensorflow:Assets written to: mymodel_2/assets
625/625 [==============================] - 2s 3ms/step - loss: 0.1751 - sparse_categorical_accuracy: 0.9477 - val_loss: 0.1976 - val_sparse_categorical_accuracy: 0.9409

<tensorflow.python.keras.callbacks.History at 0x7f7550171f28>

Il callback ModelCheckpoint può essere utilizzato per implementare la tolleranza agli errori: la capacità di riavviare l'addestramento dall'ultimo stato salvato del modello nel caso in cui l'addestramento venga interrotto in modo casuale. Ecco un esempio di base:

import os

# Prepare a directory to store all the checkpoints.
checkpoint_dir = "./ckpt"
if not os.path.exists(checkpoint_dir):
    os.makedirs(checkpoint_dir)


def make_or_restore_model():
    # Either restore the latest model, or create a fresh one
    # if there is no checkpoint available.
    checkpoints = [checkpoint_dir + "/" + name for name in os.listdir(checkpoint_dir)]
    if checkpoints:
        latest_checkpoint = max(checkpoints, key=os.path.getctime)
        print("Restoring from", latest_checkpoint)
        return keras.models.load_model(latest_checkpoint)
    print("Creating a new model")
    return get_compiled_model()


model = make_or_restore_model()
callbacks = [
    # This callback saves a SavedModel every 100 batches.
    # We include the training loss in the saved model name.
    keras.callbacks.ModelCheckpoint(
        filepath=checkpoint_dir + "/ckpt-loss={loss:.2f}", save_freq=100
    )
]
model.fit(x_train, y_train, epochs=1, callbacks=callbacks)
Creating a new model
  94/1563 [>.............................] - ETA: 3s - loss: 0.9261 - sparse_categorical_accuracy: 0.7420INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.90/assets
 192/1563 [==>...........................] - ETA: 6s - loss: 0.6734 - sparse_categorical_accuracy: 0.8097INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.66/assets
 292/1563 [====>.........................] - ETA: 6s - loss: 0.5676 - sparse_categorical_accuracy: 0.8390INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.56/assets
 393/1563 [======>.......................] - ETA: 6s - loss: 0.5077 - sparse_categorical_accuracy: 0.8543INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.51/assets
 490/1563 [========>.....................] - ETA: 5s - loss: 0.4665 - sparse_categorical_accuracy: 0.8652INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.46/assets
 589/1563 [==========>...................] - ETA: 5s - loss: 0.4356 - sparse_categorical_accuracy: 0.8735INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.43/assets
 690/1563 [============>.................] - ETA: 4s - loss: 0.4077 - sparse_categorical_accuracy: 0.8813INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.41/assets
 791/1563 [==============>...............] - ETA: 4s - loss: 0.3883 - sparse_categorical_accuracy: 0.8873INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.39/assets
 892/1563 [================>.............] - ETA: 3s - loss: 0.3715 - sparse_categorical_accuracy: 0.8921INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.37/assets
 992/1563 [==================>...........] - ETA: 3s - loss: 0.3569 - sparse_categorical_accuracy: 0.8964INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.36/assets
1092/1563 [===================>..........] - ETA: 2s - loss: 0.3444 - sparse_categorical_accuracy: 0.8994INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.34/assets
1194/1563 [=====================>........] - ETA: 2s - loss: 0.3315 - sparse_categorical_accuracy: 0.9025INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.33/assets
1293/1563 [=======================>......] - ETA: 1s - loss: 0.3217 - sparse_categorical_accuracy: 0.9056INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.32/assets
1383/1563 [=========================>....] - ETA: 1s - loss: 0.3145 - sparse_categorical_accuracy: 0.9077INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.31/assets
1478/1563 [===========================>..] - ETA: 0s - loss: 0.3057 - sparse_categorical_accuracy: 0.9102INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.30/assets
1563/1563 [==============================] - 9s 6ms/step - loss: 0.2996 - sparse_categorical_accuracy: 0.9119

<tensorflow.python.keras.callbacks.History at 0x7f74ec20d668>

Chiami anche scrivi la tua richiamata per salvare e ripristinare i modelli.

Per una guida completa alla serializzazione e al salvataggio, vedere la guida al salvataggio e alla serializzazione dei modelli .

Utilizzo dei programmi dei tassi di apprendimento

Un modello comune durante l'addestramento di modelli di apprendimento profondo consiste nel ridurre gradualmente l'apprendimento man mano che la formazione 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 di batch corrente), o dinamico (rispondendo al comportamento corrente del modello, in particolare alla perdita di convalida).

Passaggio di una pianificazione a un ottimizzatore

Puoi facilmente utilizzare un programma di decadimento del tasso di apprendimento statico passando un oggetto di pianificazione come argomento learning_rate nel tuo ottimizzatore:

initial_learning_rate = 0.1
lr_schedule = keras.optimizers.schedules.ExponentialDecay(
    initial_learning_rate, decay_steps=100000, decay_rate=0.96, staircase=True
)

optimizer = keras.optimizers.RMSprop(learning_rate=lr_schedule)

Sono disponibili diverse pianificazioni integrate: ExponentialDecay , PiecewiseConstantDecay , PolynomialDecay e InverseTimeDecay .

Utilizzo dei callback per implementare un programma di frequenza di apprendimento dinamico

Non è possibile ottenere un programma dinamico del tasso di apprendimento (ad esempio, diminuire il tasso di apprendimento quando la perdita di convalida non 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 effetti, questo è anche integrato come callback ReduceLROnPlateau .

Visualizzazione di perdite e metriche durante l'allenamento

Il modo migliore per tenere d'occhio il tuo modello durante l'addestramento è usare TensorBoard , un'applicazione basata su browser che puoi eseguire localmente che ti fornisce:

  • Grafici in tempo reale della perdita e metriche per l'addestramento e la valutazione
  • (facoltativo) Visualizzazioni degli istogrammi delle attivazioni dei livelli
  • (facoltativamente) visualizzazioni 3D degli spazi di incorporamento apprese dai livelli di Embedding

Se hai installato TensorFlow con pip, dovresti essere in grado di avviare TensorBoard dalla riga di comando:

tensorboard --logdir=/full_path_to_your_logs

Utilizzo della richiamata TensorBoard

Il modo più semplice per utilizzare TensorBoard con un modello Keras e il metodo di adattamento è il callback TensorBoard .

Nel caso più semplice, specifica semplicemente dove vuoi che il callback scriva i log e sei a posto:

keras.callbacks.TensorBoard(
    log_dir="/full_path_to_your_logs",
    histogram_freq=0,  # How often to log histogram visualizations
    embeddings_freq=0,  # How often to log embedding visualizations
    update_freq="epoch",
)  # How often to write logs (default: once per epoch)
<tensorflow.python.keras.callbacks.TensorBoard at 0x7f74ec5179e8>

Per ulteriori informazioni, vedere la documentazione per il callback di TensorBoard .