![]() | ![]() | ![]() | ![]() |
Ustawiać
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
Wstęp
Obejmuje prowadzące szkolenia, oceny i przewidywania (wnioskowanie) modele podczas korzystania z wbudowanej API do szkolenia i walidacji (takich jak Model.fit()
, Model.evaluate()
i Model.predict()
).
Jeśli jesteś zainteresowany w wykorzystaniu fit()
, określając swoją funkcję krok szkolenie, zobacz Dostosowywanie co dzieje się w fit()
przewodnika .
Jeśli jesteś zainteresowany pisania własnych pętli szkoleniowe i oceny od podstaw, można znaleźć w podręczniku „Zapis pętlę szkolenia od podstaw” .
Ogólnie rzecz biorąc, niezależnie od tego, czy używasz wbudowanych pętli, czy piszesz własne, uczenie i ocena modeli działa dokładnie w ten sam sposób we wszystkich modelach Keras — modele sekwencyjne, modele zbudowane za pomocą interfejsu API funkcjonalnego i modele napisane od podstaw za pomocą podklasy modeli.
Podręcznik ten nie obejmuje rozproszoną szkolenie, które zostało opisane w naszym przewodniku do multi-GPU i rozproszonej szkolenia .
Przegląd API: pierwszy kompleksowy przykład
Podczas przekazywania danych do wbudowanej w szkoleniu pętle modelu, należy użyć tablic numpy (jeśli dane jest mały i zmieści się w pamięci) lub tf.data Dataset
obiektów. W następnych kilku akapitach użyjemy zestawu danych MNIST jako tablic NumPy, aby zademonstrować, jak używać optymalizatorów, strat i metryk.
Rozważmy następujący model (tutaj wbudowujemy w Functional API, ale może to być również model sekwencyjny lub model podklasowy):
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)
Oto jak wygląda typowy przepływ pracy typu end-to-end, składający się z:
- Trening
- Walidacja na zestawie wstrzymania wygenerowanym z oryginalnych danych treningowych
- Ocena na danych testowych
W tym przykładzie użyjemy danych MNIST.
(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]
Określamy konfigurację treningu (optymalizator, strata, metryki):
model.compile(
optimizer=keras.optimizers.RMSprop(), # Optimizer
# Loss function to minimize
loss=keras.losses.SparseCategoricalCrossentropy(),
# List of metrics to monitor
metrics=[keras.metrics.SparseCategoricalAccuracy()],
)
Nazywamy fit()
, która będzie szkolić modelu przez cięcie dane do „partii” o rozmiarze batch_size
i wielokrotnie iteracji przez cały zbiór danych dla danej liczby epochs
.
print("Fit model on training data")
history = model.fit(
x_train,
y_train,
batch_size=64,
epochs=2,
# We pass some validation for
# monitoring validation loss and metrics
# at the end of each epoch
validation_data=(x_val, y_val),
)
Fit model on training data Epoch 1/2 782/782 [==============================] - 3s 3ms/step - loss: 0.3387 - sparse_categorical_accuracy: 0.9050 - val_loss: 0.1957 - val_sparse_categorical_accuracy: 0.9426 Epoch 2/2 782/782 [==============================] - 2s 3ms/step - loss: 0.1543 - sparse_categorical_accuracy: 0.9548 - val_loss: 0.1425 - val_sparse_categorical_accuracy: 0.9593
Zwracany history
obiekt posiada zapis wartości strat i wartości metrycznych podczas treningu:
history.history
{'loss': [0.3386789858341217, 0.1543138176202774], 'sparse_categorical_accuracy': [0.9050400257110596, 0.9548400044441223], 'val_loss': [0.19569723308086395, 0.14253544807434082], 'val_sparse_categorical_accuracy': [0.9426000118255615, 0.9592999815940857]}
Oceniamy modelu na danych testowych za pomocą evaluate()
:
# Evaluate the model on the test data using `evaluate`
print("Evaluate on test data")
results = model.evaluate(x_test, y_test, batch_size=128)
print("test loss, test acc:", results)
# Generate predictions (probabilities -- the output of the last layer)
# on new data using `predict`
print("Generate predictions for 3 samples")
predictions = model.predict(x_test[:3])
print("predictions shape:", predictions.shape)
Evaluate on test data 79/79 [==============================] - 0s 2ms/step - loss: 0.1414 - sparse_categorical_accuracy: 0.9569 test loss, test acc: [0.14140386879444122, 0.9569000005722046] Generate predictions for 3 samples predictions shape: (3, 10)
Przyjrzyjmy się teraz szczegółowo każdemu elementowi tego przepływu pracy.
compile()
Sposób: Określanie straty, dane i optymalizator
Trenować model z fit()
, trzeba określić funkcję strat, optymalizator i ewentualnie jakieś metryki monitorować.
Przekazać je do modelu jako argumentów do compile()
metody:
model.compile(
optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
loss=keras.losses.SparseCategoricalCrossentropy(),
metrics=[keras.metrics.SparseCategoricalAccuracy()],
)
metrics
argument powinien być lista - model może mieć dowolną liczbę metryk.
Jeśli Twój model ma wiele wyników, możesz określić różne straty i metryki dla każdego wyniku, a także możesz modulować udział każdego wyniku w całkowitej stracie modelu. Znajdziesz więcej szczegółów na ten temat w przekazywanie danych do wielu wejść, multi-wyjścia sekcji modeli.
Zwróć uwagę, że jeśli jesteś zadowolony z ustawień domyślnych, w wielu przypadkach optymalizator, stratę i metryki można określić za pomocą identyfikatorów ciągów jako skrótu:
model.compile(
optimizer="rmsprop",
loss="sparse_categorical_crossentropy",
metrics=["sparse_categorical_accuracy"],
)
Do późniejszego ponownego wykorzystania, umieśćmy naszą definicję modelu i krok kompilacji w funkcjach; nazwiemy je kilka razy w różnych przykładach w tym przewodniku.
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
Dostępnych jest wiele wbudowanych optymalizatorów, strat i metryk
Ogólnie rzecz biorąc, nie będziesz musiał tworzyć od podstaw własnych strat, metryk lub optymalizatorów, ponieważ to, czego potrzebujesz, prawdopodobnie jest już częścią API Keras:
Optymalizatory:
-
SGD()
(z lub bez pędu) -
RMSprop()
-
Adam()
- itp.
Straty:
-
MeanSquaredError()
-
KLDivergence()
-
CosineSimilarity()
- itp.
Metryka:
-
AUC()
-
Precision()
-
Recall()
- itp.
Straty niestandardowe
Jeśli potrzebujesz stworzyć niestandardową stratę, Keras oferuje dwa sposoby, aby to zrobić.
Pierwsza metoda polega na tworzeniu się funkcję, która przyjmuje wejścia y_true
i y_pred
. Poniższy przykład przedstawia funkcję straty, która oblicza błąd średniokwadratowy między danymi rzeczywistymi a przewidywaniami:
def custom_mean_squared_error(y_true, y_pred):
return tf.math.reduce_mean(tf.square(y_true - y_pred))
model = get_uncompiled_model()
model.compile(optimizer=keras.optimizers.Adam(), loss=custom_mean_squared_error)
# We need to one-hot encode the labels to use MSE
y_train_one_hot = tf.one_hot(y_train, depth=10)
model.fit(x_train, y_train_one_hot, batch_size=64, epochs=1)
782/782 [==============================] - 2s 2ms/step - loss: 0.0162 <keras.callbacks.History at 0x7ff8881ba250>
Jeśli potrzebujesz funkcji straty, które odbywają się w parametrach obok y_true
i y_pred
można podklasy tf.keras.losses.Loss
klasę i wdrożenie następujących dwóch metod:
-
__init__(self)
: akceptować parametry przekazać podczas rozmowy swojej funkcji straty -
call(self, y_true, y_pred)
: użyj cele (y_true) oraz model przewidywania (y_pred) obliczyć straty modelki
Załóżmy, że chcesz użyć błędu średniokwadratowego, ale z dodanym terminem, który zmniejszy predykcję na wartości dalekie od 0,5 (zakładamy, że cele jakościowe są zakodowane jednorazowo i przyjmują wartości od 0 do 1). Stwarza to zachętę do tego, aby model nie był zbyt pewny siebie, co może pomóc w zmniejszeniu nadmiernego dopasowania (nie będziemy wiedzieć, czy to działa, dopóki nie spróbujemy!).
Oto jak byś to zrobił:
class CustomMSE(keras.losses.Loss):
def __init__(self, regularization_factor=0.1, name="custom_mse"):
super().__init__(name=name)
self.regularization_factor = regularization_factor
def call(self, y_true, y_pred):
mse = tf.math.reduce_mean(tf.square(y_true - y_pred))
reg = tf.math.reduce_mean(tf.square(0.5 - y_pred))
return mse + reg * self.regularization_factor
model = get_uncompiled_model()
model.compile(optimizer=keras.optimizers.Adam(), loss=CustomMSE())
y_train_one_hot = tf.one_hot(y_train, depth=10)
model.fit(x_train, y_train_one_hot, batch_size=64, epochs=1)
782/782 [==============================] - 2s 2ms/step - loss: 0.0388 <keras.callbacks.History at 0x7ff8882130d0>
Dane niestandardowe
Jeśli potrzebujesz metryki, które nie jest częścią interfejsu API, można łatwo tworzyć niestandardowe dane przez instacji tf.keras.metrics.Metric
klasę. Będziesz musiał zaimplementować 4 metody:
-
__init__(self)
, w którym można tworzyć zmienne stanu na swoją metrykę. -
update_state(self, y_true, y_pred, sample_weight=None)
, który wykorzystuje cele y_true i model przewidywania y_pred aktualizację zmiennych stanu. -
result(self)
, która wykorzystuje zmienne stanu, aby obliczyć wyniki końcowe. -
reset_state(self)
, który reinicjalizuje stanu metrykę.
Aktualizacja stanu i wyniki obliczeń są przechowywane oddzielnie (w update_state()
i result()
, odpowiednio), ponieważ w niektórych przypadkach obliczanie wyników może być bardzo kosztowne i będzie okresowo wykonywane tylko.
Oto prosty przykład pokazujący jak zaimplementować CategoricalTruePositives
metryczny, że liczy, ile Próbki prawidłowo sklasyfikowanych jako należące do danej klasy:
class CategoricalTruePositives(keras.metrics.Metric):
def __init__(self, name="categorical_true_positives", **kwargs):
super(CategoricalTruePositives, self).__init__(name=name, **kwargs)
self.true_positives = self.add_weight(name="ctp", initializer="zeros")
def update_state(self, y_true, y_pred, sample_weight=None):
y_pred = tf.reshape(tf.argmax(y_pred, axis=1), shape=(-1, 1))
values = tf.cast(y_true, "int32") == tf.cast(y_pred, "int32")
values = tf.cast(values, "float32")
if sample_weight is not None:
sample_weight = tf.cast(sample_weight, "float32")
values = tf.multiply(values, sample_weight)
self.true_positives.assign_add(tf.reduce_sum(values))
def result(self):
return self.true_positives
def reset_state(self):
# The state of the metric will be reset at the start of each epoch.
self.true_positives.assign(0.0)
model = get_uncompiled_model()
model.compile(
optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
loss=keras.losses.SparseCategoricalCrossentropy(),
metrics=[CategoricalTruePositives()],
)
model.fit(x_train, y_train, batch_size=64, epochs=3)
Epoch 1/3 782/782 [==============================] - 2s 3ms/step - loss: 0.3404 - categorical_true_positives: 45217.0000 Epoch 2/3 782/782 [==============================] - 2s 3ms/step - loss: 0.1588 - categorical_true_positives: 47606.0000 Epoch 3/3 782/782 [==============================] - 2s 3ms/step - loss: 0.1168 - categorical_true_positives: 48278.0000 <keras.callbacks.History at 0x7ff8880a3610>
Obsługa strat i wskaźników, które nie pasują do standardowego podpisu
Zdecydowana większość strat i metryk można obliczyć z y_true
i y_pred
, gdzie y_pred
jest sygnałem wyjściowym modelu - ale nie wszystkie z nich. Na przykład utrata regularyzacji może wymagać jedynie aktywacji warstwy (w tym przypadku nie ma celów), a ta aktywacja może nie być wynikiem modelu.
W takich przypadkach można nazwać self.add_loss(loss_value)
od wewnątrz metody połączenia warstwy niestandardowej. Straty dodane w ten sposób dodane do „głównego” straty podczas treningu (jeden przeszedł do compile()
). Oto prosty przykład, który dodaje regularyzację aktywności (zauważ, że regularyzacja aktywności jest wbudowana we wszystkie warstwy Keras — ta warstwa służy tylko do dostarczenia konkretnego przykładu):
class ActivityRegularizationLayer(layers.Layer):
def call(self, inputs):
self.add_loss(tf.reduce_sum(inputs) * 0.1)
return inputs # Pass-through layer.
inputs = keras.Input(shape=(784,), name="digits")
x = layers.Dense(64, activation="relu", name="dense_1")(inputs)
# Insert activity regularization as a layer
x = ActivityRegularizationLayer()(x)
x = layers.Dense(64, activation="relu", name="dense_2")(x)
outputs = layers.Dense(10, name="predictions")(x)
model = keras.Model(inputs=inputs, outputs=outputs)
model.compile(
optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
)
# The displayed loss will be much higher than before
# due to the regularization component.
model.fit(x_train, y_train, batch_size=64, epochs=1)
782/782 [==============================] - 2s 2ms/step - loss: 2.4545 <keras.callbacks.History at 0x7ff87c53f310>
Można zrobić to samo dla zalogowaniu wartości metryki, używając add_metric()
:
class MetricLoggingLayer(layers.Layer):
def call(self, inputs):
# The `aggregation` argument defines
# how to aggregate the per-batch values
# over each epoch:
# in this case we simply average them.
self.add_metric(
keras.backend.std(inputs), name="std_of_activation", aggregation="mean"
)
return inputs # Pass-through layer.
inputs = keras.Input(shape=(784,), name="digits")
x = layers.Dense(64, activation="relu", name="dense_1")(inputs)
# Insert std logging as a layer.
x = MetricLoggingLayer()(x)
x = layers.Dense(64, activation="relu", name="dense_2")(x)
outputs = layers.Dense(10, name="predictions")(x)
model = keras.Model(inputs=inputs, outputs=outputs)
model.compile(
optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
)
model.fit(x_train, y_train, batch_size=64, epochs=1)
782/782 [==============================] - 2s 2ms/step - loss: 0.3461 - std_of_activation: 0.9929 <keras.callbacks.History at 0x7ff87c3d5bd0>
W API Funkcjonalnej , można również zadzwonić model.add_loss(loss_tensor)
lub model.add_metric(metric_tensor, name, aggregation)
.
Oto prosty przykład:
inputs = keras.Input(shape=(784,), name="digits")
x1 = layers.Dense(64, activation="relu", name="dense_1")(inputs)
x2 = layers.Dense(64, activation="relu", name="dense_2")(x1)
outputs = layers.Dense(10, name="predictions")(x2)
model = keras.Model(inputs=inputs, outputs=outputs)
model.add_loss(tf.reduce_sum(x1) * 0.1)
model.add_metric(keras.backend.std(x1), name="std_of_activation", aggregation="mean")
model.compile(
optimizer=keras.optimizers.RMSprop(1e-3),
loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
)
model.fit(x_train, y_train, batch_size=64, epochs=1)
782/782 [==============================] - 2s 3ms/step - loss: 2.4647 - std_of_activation: 0.0017 <keras.callbacks.History at 0x7ff87c216f90>
Zauważ, że kiedy przechodzą straty poprzez add_loss()
, staje się możliwe, aby zadzwonić do compile()
bez funkcji strat, ponieważ model ma już stratę do minimalizowania.
Rozważmy następujący LogisticEndpoint
warstwy: trwa jako wejścia celów i logits, i śledzi crossentropy straty poprzez add_loss()
. Śledzi również dokładność klasyfikacji poprzez 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)
Można go używać w modelu z dwoma wejściami i cele (dane wejściowe), zestawionych bez loss
argumentu, na przykład:
import numpy as np
inputs = keras.Input(shape=(3,), name="inputs")
targets = keras.Input(shape=(10,), name="targets")
logits = keras.layers.Dense(10)(inputs)
predictions = LogisticEndpoint(name="predictions")(logits, targets)
model = keras.Model(inputs=[inputs, targets], outputs=predictions)
model.compile(optimizer="adam") # No loss argument!
data = {
"inputs": np.random.random((3, 3)),
"targets": np.random.random((3, 10)),
}
model.fit(data)
1/1 [==============================] - 0s 414ms/step - loss: 0.9889 - binary_accuracy: 0.0000e+00 <keras.callbacks.History at 0x7ff87c0848d0>
Aby uzyskać więcej informacji na temat szkolenia modeli multi-wejściowe, patrz sekcja Przekazywanie danych do multi-wejściowych modeli wielo-wyjściowych.
Automatyczne rozdzielenie zestawu wstrzymania walidacji
W pierwszym przykładzie end-to-end widziałeś, użyliśmy validation_data
argument przekazać krotki tablic numpy (x_val, y_val)
do modelu oceny utraty walidacji i weryfikacji wskaźników na koniec każdej epoki.
Oto kolejna opcja: argument validation_split
pozwala automatycznie rezerwowy część danych treningowych do walidacji. Wartość argumentów reprezentuje część danych, które są zarezerwowane dla walidacji, więc powinien on być ustawiony na wartość wyższą niż 0 i mniejszy niż 1. Na przykład, validation_split=0.2
oznacza „stosowanie 20% danych walidacji” i validation_split=0.6
oznacza „stosowanie 60% danych walidacji”.
Sposób walidacja jest obliczany jest poprzez ostatniej x% próbek tablic otrzymanych przez fit()
połączenia, zanim jakiekolwiek tasowanie.
Należy pamiętać, że można używać tylko validation_split
gdy szkolenie z danymi NumPy.
model = get_compiled_model()
model.fit(x_train, y_train, batch_size=64, validation_split=0.2, epochs=1)
625/625 [==============================] - 2s 3ms/step - loss: 0.3682 - sparse_categorical_accuracy: 0.8957 - val_loss: 0.2276 - val_sparse_categorical_accuracy: 0.9301 <keras.callbacks.History at 0x7ff81c680890>
Szkolenie i ocena z zestawów danych tf.data
W ciągu ostatnich kilku akapitach, widziałeś, jak radzić sobie straty, metryk i optymalizujące i widziałem, jak korzystać z validation_data
i validation_split
argumentów w fit()
, gdy dane są przekazywane w postaci tablic numpy.
Załóżmy teraz przyjrzeć się w przypadku, gdy dane jest w postaci tf.data.Dataset
obiektu.
tf.data
API to zestaw narzędzi w TensorFlow 2,0 do załadunku i przerób danych w sposób, który jest szybki i skalowalne.
Na kompletny przewodnik na temat tworzenia Datasets
, zobacz dokumentację tf.data .
Można przekazać Dataset
instancji bezpośrednio do metody fit()
, evaluate()
, a predict()
:
model = get_compiled_model()
# First, let's create a training Dataset instance.
# For the sake of our example, we'll use the same MNIST data as before.
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
# Shuffle and slice the dataset.
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)
# Now we get a test dataset.
test_dataset = tf.data.Dataset.from_tensor_slices((x_test, y_test))
test_dataset = test_dataset.batch(64)
# Since the dataset already takes care of batching,
# we don't pass a `batch_size` argument.
model.fit(train_dataset, epochs=3)
# You can also evaluate or predict on a dataset.
print("Evaluate")
result = model.evaluate(test_dataset)
dict(zip(model.metrics_names, result))
Epoch 1/3 782/782 [==============================] - 2s 3ms/step - loss: 0.3372 - sparse_categorical_accuracy: 0.9047 Epoch 2/3 782/782 [==============================] - 2s 3ms/step - loss: 0.1596 - sparse_categorical_accuracy: 0.9523 Epoch 3/3 782/782 [==============================] - 2s 3ms/step - loss: 0.1171 - sparse_categorical_accuracy: 0.9655 Evaluate 157/157 [==============================] - 0s 2ms/step - loss: 0.1211 - sparse_categorical_accuracy: 0.9648 {'loss': 0.12107347697019577, 'sparse_categorical_accuracy': 0.9648000001907349}
Zwróć uwagę, że zestaw danych jest resetowany na koniec każdej epoki, więc można go ponownie użyć w następnej epoce.
Jeśli chcesz uruchomić szkolenie tylko na liczbie określonej partii ze zbioru danych, można zdać steps_per_epoch
argument, który określa ile szkolenie kroki model powinien być uruchomiony za pomocą zbioru danych przed przejściem do następnej epoki.
Jeśli to zrobisz, zestaw danych nie zostanie zresetowany pod koniec każdej epoki, zamiast tego po prostu rysujemy kolejne partie. W zestawie danych w końcu zabraknie danych (chyba że jest to zestaw danych zapętlony w nieskończoność).
model = get_compiled_model()
# Prepare the training dataset
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)
# Only use the 100 batches per epoch (that's 64 * 100 samples)
model.fit(train_dataset, epochs=3, steps_per_epoch=100)
Epoch 1/3 100/100 [==============================] - 1s 3ms/step - loss: 0.7937 - sparse_categorical_accuracy: 0.7894 Epoch 2/3 100/100 [==============================] - 0s 3ms/step - loss: 0.3699 - sparse_categorical_accuracy: 0.8938 Epoch 3/3 100/100 [==============================] - 0s 3ms/step - loss: 0.3155 - sparse_categorical_accuracy: 0.9061 <keras.callbacks.History at 0x7ff81c587e90>
Korzystanie ze zbioru danych walidacyjnych
Można przekazać Dataset
instancji jako validation_data
argument fit()
:
model = get_compiled_model()
# Prepare the training dataset
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)
# Prepare the validation dataset
val_dataset = tf.data.Dataset.from_tensor_slices((x_val, y_val))
val_dataset = val_dataset.batch(64)
model.fit(train_dataset, epochs=1, validation_data=val_dataset)
782/782 [==============================] - 3s 3ms/step - loss: 0.3380 - sparse_categorical_accuracy: 0.9035 - val_loss: 0.2015 - val_sparse_categorical_accuracy: 0.9405 <keras.callbacks.History at 0x7ff81c30e450>
Pod koniec każdej epoki model będzie iterować po zbiorze danych walidacyjnych i obliczy metryki utraty walidacji i walidacji.
Jeśli chcesz uruchomić sprawdzanie tylko w liczbie określonej partii z tego zestawu danych, można zdać validation_steps
argument, który określa ile walidacja kroki model powinien uruchomić przy zbiorze walidacji przed przerywania walidacji i przejściem do następnej epoki:
model = get_compiled_model()
# Prepare the training dataset
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)
# Prepare the validation dataset
val_dataset = tf.data.Dataset.from_tensor_slices((x_val, y_val))
val_dataset = val_dataset.batch(64)
model.fit(
train_dataset,
epochs=1,
# Only run validation using the first 10 batches of the dataset
# using the `validation_steps` argument
validation_data=val_dataset,
validation_steps=10,
)
782/782 [==============================] - 3s 3ms/step - loss: 0.3369 - sparse_categorical_accuracy: 0.9036 - val_loss: 0.2953 - val_sparse_categorical_accuracy: 0.9187 <keras.callbacks.History at 0x7ff81c30e310>
Należy pamiętać, że zestaw danych walidacyjnych zostanie zresetowany po każdym użyciu (aby zawsze dokonywać oceny na tych samych próbkach od epoki do epoki).
Argument validation_split
(generowanie wstrzymanie zestaw danych z treningu) nie jest obsługiwana, gdy szkolenie z Dataset
obiektów, ponieważ ta funkcja wymaga zdolności do indeksu próbek zestawów danych, co nie jest możliwe w ogóle z Dataset
API.
Obsługiwane inne formaty wejściowe
Poza tym, macierze NumPy żądnych tensorów i TensorFlow Datasets
, to możliwe do trenowania modelu Keras pomocą dataframes PANDAS lub z generatorów Pythona że partie wydajność danych i etykiet.
W szczególności, keras.utils.Sequence
Class oferuje prosty interfejs Pythona zbudować generatory danych, które są Multiprocessing świadomy i może być tasuje.
Ogólnie zalecamy używanie:
- Dane wejściowe NumPy, jeśli dane są małe i mieszczą się w pamięci
-
Dataset
obiektów, jeśli masz duże zbiory danych i trzeba zrobić rozproszoną szkolenia -
Sequence
obiektów jeśli masz duże zbiory danych i trzeba zrobić wiele niestandardowego przetwarzania Python-bocznej, które nie mogą być wykonane w TensorFlow (np jeśli opierają się na zewnętrznych bibliotek do załadunku danych lub przerób).
Korzystanie z keras.utils.Sequence
obiekt jako wejście
keras.utils.Sequence
to narzędzie, które można podklasy, aby uzyskać generator Pythona z dwóch istotnych właściwości:
- Działa dobrze z przetwarzaniem wieloprocesowym.
- Może być tasuje (np podczas przechodzenia
shuffle=True
wfit()
).
Sequence
musi realizować na dwa sposoby:
-
__getitem__
-
__len__
Metoda __getitem__
powinien zwrócić kompletną partię. Jeśli chcesz zmodyfikować zbiór danych między epokami, można wdrożyć on_epoch_end
.
Oto krótki przykład:
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)
Korzystanie z ważenia próbek i ważenia klas
Przy ustawieniach domyślnych o wadze próbki decyduje jej częstotliwość w zbiorze danych. Istnieją dwie metody ważenia danych, niezależnie od częstotliwości próbkowania:
- Wagi klas
- Odważniki próbek
Wagi klas
To jest ustalana przez przechodzącą słownika do class_weight
argument Model.fit()
. Słownik ten odwzorowuje indeksy klas na wagi, które powinny być używane dla próbek należących do tej klasy.
Można to wykorzystać do zrównoważenia klas bez ponownego próbkowania lub do trenowania modelu, który nadaje większą wagę określonej klasie.
Na przykład, jeśli klasa "0" jest w połowie tak reprezentowane klasy "1" w swoich danych, można użyć Model.fit(..., class_weight={0: 1., 1: 0.5})
.
Oto przykład NumPy, w którym używamy wag klas lub wag próbek, aby nadać większą wagę prawidłowej klasyfikacji klasy nr 5 (która jest cyfrą „5” w zestawie danych MNIST).
import numpy as np
class_weight = {
0: 1.0,
1: 1.0,
2: 1.0,
3: 1.0,
4: 1.0,
# Set weight "2" for class "5",
# making this class 2x more important
5: 2.0,
6: 1.0,
7: 1.0,
8: 1.0,
9: 1.0,
}
print("Fit with class weight")
model = get_compiled_model()
model.fit(x_train, y_train, class_weight=class_weight, batch_size=64, epochs=1)
Fit with class weight 782/782 [==============================] - 2s 3ms/step - loss: 0.3708 - sparse_categorical_accuracy: 0.9032 <keras.callbacks.History at 0x7ff80c7ddd10>
Odważniki próbek
Aby uzyskać drobnoziarnistą kontrolę lub jeśli nie budujesz klasyfikatora, możesz użyć „wagi próbek”.
- Podczas szkolenia z danych NumPy: Przełóż
sample_weight
argumentModel.fit()
. - Podczas szkolenia z
tf.data
lub innego rodzaju iteracyjnej: Wydajność(input_batch, label_batch, sample_weight_batch)
krotki.
Tablica „wagi próbek” to tablica liczb, które określają, jaką wagę powinna mieć każda próbka w partii przy obliczaniu całkowitej straty. Jest powszechnie stosowany w problemach z niezrównoważoną klasyfikacją (pomysł polega na tym, aby nadać większą wagę rzadko spotykanym klasom).
Gdy wagi będą zer i jedynek, tablica może być stosowany jako maska dla funkcji strat (całkowicie wyrzucaniu wkład niektórych próbek do całkowitej utraty).
sample_weight = np.ones(shape=(len(y_train),))
sample_weight[y_train == 5] = 2.0
print("Fit with sample weight")
model = get_compiled_model()
model.fit(x_train, y_train, sample_weight=sample_weight, batch_size=64, epochs=1)
Fit with sample weight 782/782 [==============================] - 2s 3ms/step - loss: 0.3806 - sparse_categorical_accuracy: 0.9000 <keras.callbacks.History at 0x7ff80c650350>
Oto dopasowanie Dataset
Przykład:
sample_weight = np.ones(shape=(len(y_train),))
sample_weight[y_train == 5] = 2.0
# Create a Dataset that includes sample weights
# (3rd element in the return tuple).
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train, sample_weight))
# Shuffle and slice the dataset.
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)
model = get_compiled_model()
model.fit(train_dataset, epochs=1)
782/782 [==============================] - 3s 3ms/step - loss: 0.3588 - sparse_categorical_accuracy: 0.9070 <keras.callbacks.History at 0x7ff80c51cb50>
Przekazywanie danych do modeli z wieloma wejściami i wieloma wyjściami
W poprzednich przykładach, my za model z jednego wejścia (tensora kształt (764,)
) i jednym wyjściem (tensora przewidywania kształtu (10,)
). Ale co z modelami, które mają wiele wejść lub wyjść?
Rozważmy następujący wzór, który ma wejście obrazu kształcie (32, 32, 3)
(to jest (height, width, channels)
) i wejście serii czas kształtu (None, 10)
(to jest (timesteps, features)
). Nasz model mają dwa wyjścia obliczone z kombinacji tych wejść: „punktów” (kształt (1,)
), a rozkład prawdopodobieństwa dla pięciu grup (kształtu (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]
)
Narysujmy ten model, aby wyraźnie zobaczyć, co tutaj robimy (zwróć uwagę, że kształty pokazane na wykresie są kształtami wsadowymi, a nie kształtami przypadającymi na próbkę).
keras.utils.plot_model(model, "multi_input_and_output_model.png", show_shapes=True)
W czasie kompilacji możemy określić różne straty na różnych wyjściach, przekazując funkcje strat jako listę:
model.compile(
optimizer=keras.optimizers.RMSprop(1e-3),
loss=[keras.losses.MeanSquaredError(), keras.losses.CategoricalCrossentropy()],
)
Gdybyśmy przekazali do modelu tylko jedną funkcję straty, ta sama funkcja straty zostałaby zastosowana do każdego wyniku (co nie jest właściwe w tym przypadku).
Podobnie dla metryk:
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()],
],
)
Ponieważ nadaliśmy nazwy naszym warstwom wyjściowym, mogliśmy również określić straty i metryki na dane wyjściowe za pomocą dyktatu:
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()],
},
)
Zalecamy używanie wyraźnych nazw i podpowiedzi, jeśli masz więcej niż 2 wyjścia.
Jest to możliwe, aby dać różne wagi do różnych specyficznych strat wyjście (na przykład, może sobie życzyć, aby przywilej „Wynik” stratę w naszym przykładzie, dając do 2x znaczenie utraty klasy), stosując loss_weights
argumentu:
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},
)
Możesz również zdecydować, aby nie obliczać straty dla niektórych wyników, jeśli te wyniki są przeznaczone do przewidywania, ale nie do uczenia:
# 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()},
)
Przekazywanie danych do multi-input lub modelu multi-wyjścia w fit()
działa w podobny sposób, jak określenie funkcji straty w kompilacji: można przekazać list tablic numpy (1: 1 mapowanie do wyjść, które otrzymały funkcję strat ) lub dicts odwzorowujące nazwy wyjściowe tablic numPy.
model.compile(
optimizer=keras.optimizers.RMSprop(1e-3),
loss=[keras.losses.MeanSquaredError(), keras.losses.CategoricalCrossentropy()],
)
# Generate dummy NumPy data
img_data = np.random.random_sample(size=(100, 32, 32, 3))
ts_data = np.random.random_sample(size=(100, 20, 10))
score_targets = np.random.random_sample(size=(100, 1))
class_targets = np.random.random_sample(size=(100, 5))
# Fit on lists
model.fit([img_data, ts_data], [score_targets, class_targets], batch_size=32, epochs=1)
# Alternatively, fit on dicts
model.fit(
{"img_input": img_data, "ts_input": ts_data},
{"score_output": score_targets, "class_output": class_targets},
batch_size=32,
epochs=1,
)
4/4 [==============================] - 2s 9ms/step - loss: 5.6917 - score_output_loss: 0.1031 - class_output_loss: 5.5886 4/4 [==============================] - 0s 6ms/step - loss: 4.4108 - score_output_loss: 0.0999 - class_output_loss: 4.3109 <keras.callbacks.History at 0x7ff80c3b4110>
Oto Dataset
przypadek użycia: podobnie jak to, co zrobiliśmy dla tablic numpy The Dataset
powinien wrócić krotka dicts.
train_dataset = tf.data.Dataset.from_tensor_slices(
(
{"img_input": img_data, "ts_input": ts_data},
{"score_output": score_targets, "class_output": class_targets},
)
)
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)
model.fit(train_dataset, epochs=1)
2/2 [==============================] - 0s 21ms/step - loss: 4.2451 - score_output_loss: 0.0993 - class_output_loss: 4.1458 <keras.callbacks.History at 0x7ff80c3ed450>
Korzystanie z wywołań zwrotnych
Wywołania zwrotne w Keras to obiekty, które są wywoływane w różnych punktach uczenia się (na początku epoki, na końcu wsadu, na końcu epoki itp.). Mogą służyć do realizacji określonych zachowań, takich jak:
- Wykonywanie walidacji w różnych punktach podczas treningu (poza wbudowaną walidacją na epokę)
- Sprawdzanie modelu w regularnych odstępach czasu lub gdy przekracza określony próg dokładności
- Zmiana szybkości uczenia się modelu, gdy trening wydaje się stabilizować
- Dostrajanie górnych warstw, gdy trening wydaje się stabilizować
- Wysyłanie powiadomień e-mail lub wiadomości błyskawicznych po zakończeniu szkolenia lub przekroczeniu określonego progu wydajności
- Itp.
Wywołania zwrotne mogą być przekazywane w formie listy na wezwanie do fit()
:
model = get_compiled_model()
callbacks = [
keras.callbacks.EarlyStopping(
# Stop training when `val_loss` is no longer improving
monitor="val_loss",
# "no longer improving" being defined as "no better than 1e-2 less"
min_delta=1e-2,
# "no longer improving" being further defined as "for at least 2 epochs"
patience=2,
verbose=1,
)
]
model.fit(
x_train,
y_train,
epochs=20,
batch_size=64,
callbacks=callbacks,
validation_split=0.2,
)
Epoch 1/20 625/625 [==============================] - 2s 3ms/step - loss: 0.3725 - sparse_categorical_accuracy: 0.8939 - val_loss: 0.2314 - val_sparse_categorical_accuracy: 0.9321 Epoch 2/20 625/625 [==============================] - 2s 3ms/step - loss: 0.1805 - sparse_categorical_accuracy: 0.9471 - val_loss: 0.2012 - val_sparse_categorical_accuracy: 0.9379 Epoch 3/20 625/625 [==============================] - 2s 3ms/step - loss: 0.1346 - sparse_categorical_accuracy: 0.9603 - val_loss: 0.1651 - val_sparse_categorical_accuracy: 0.9505 Epoch 4/20 625/625 [==============================] - 2s 3ms/step - loss: 0.1065 - sparse_categorical_accuracy: 0.9684 - val_loss: 0.1510 - val_sparse_categorical_accuracy: 0.9571 Epoch 5/20 625/625 [==============================] - 2s 3ms/step - loss: 0.0884 - sparse_categorical_accuracy: 0.9734 - val_loss: 0.1505 - val_sparse_categorical_accuracy: 0.9538 Epoch 6/20 625/625 [==============================] - 2s 3ms/step - loss: 0.0746 - sparse_categorical_accuracy: 0.9778 - val_loss: 0.1508 - val_sparse_categorical_accuracy: 0.9575 Epoch 00006: early stopping <keras.callbacks.History at 0x7ff80c64cad0>
Dostępnych jest wiele wbudowanych wywołań zwrotnych
W Keras dostępnych jest już wiele wbudowanych wywołań zwrotnych, takich jak:
-
ModelCheckpoint
: Okresowo zapisać model. -
EarlyStopping
: szkolenia zatrzyma się, gdy szkolenie nie jest już poprawa wskaźników walidacji. -
TensorBoard
: okresowo zapisu modelu dzienniki, które mogą być wizualizowane w TensorBoard (więcej szczegółów w sekcji „Wizualizacja”). -
CSVLogger
: utrata lub dane strumieni danych do pliku CSV. - itp.
Zobacz dokumentację wywołań zwrotnych dla kompletnej listy.
Pisanie własnego oddzwaniania
Można tworzyć niestandardowe zwrotnego poprzez rozszerzenie klasy bazowej keras.callbacks.Callback
. Zwrotna ma dostęp do jego powiązanego modelu poprzez właściwość klasa self.model
.
Upewnij się, aby przeczytać kompletny podręcznik do pisania niestandardowych wywołań zwrotnych .
Oto prosty przykład zapisywania listy wartości strat na partię podczas treningu:
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"))
Modele kontrolne
Podczas uczenia modelu na stosunkowo dużych zestawach danych bardzo ważne jest zapisywanie punktów kontrolnych modelu w częstych odstępach czasu.
Najprostszym sposobem osiągnięcia tego celu jest z ModelCheckpoint
zwrotnego:
model = get_compiled_model()
callbacks = [
keras.callbacks.ModelCheckpoint(
# Path where to save the model
# The two parameters below mean that we will overwrite
# the current checkpoint if and only if
# the `val_loss` score has improved.
# The saved model name will include the current epoch.
filepath="mymodel_{epoch}",
save_best_only=True, # Only save a model if `val_loss` has improved.
monitor="val_loss",
verbose=1,
)
]
model.fit(
x_train, y_train, epochs=2, batch_size=64, callbacks=callbacks, validation_split=0.2
)
Epoch 1/2 613/625 [============================>.] - ETA: 0s - loss: 0.3693 - sparse_categorical_accuracy: 0.8972 Epoch 00001: val_loss improved from inf to 0.23508, saving model to mymodel_1 2021-11-12 20:11:50.182298: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them. INFO:tensorflow:Assets written to: mymodel_1/assets 625/625 [==============================] - 3s 4ms/step - loss: 0.3660 - sparse_categorical_accuracy: 0.8979 - val_loss: 0.2351 - val_sparse_categorical_accuracy: 0.9273 Epoch 2/2 620/625 [============================>.] - ETA: 0s - loss: 0.1659 - sparse_categorical_accuracy: 0.9507 Epoch 00002: val_loss improved from 0.23508 to 0.16898, saving model to mymodel_2 INFO:tensorflow:Assets written to: mymodel_2/assets 625/625 [==============================] - 2s 3ms/step - loss: 0.1657 - sparse_categorical_accuracy: 0.9507 - val_loss: 0.1690 - val_sparse_categorical_accuracy: 0.9482 <keras.callbacks.History at 0x7ff8b577cc90>
ModelCheckpoint
zwrotna może być używany do realizacji odporności na uszkodzenia: zdolność do treningu restartu od ostatniego zapisanego stanu modelu w przypadku szkolenia zostanie przypadkowo przerwany. Oto podstawowy przykład:
import os
# Prepare a directory to store all the checkpoints.
checkpoint_dir = "./ckpt"
if not os.path.exists(checkpoint_dir):
os.makedirs(checkpoint_dir)
def make_or_restore_model():
# Either restore the latest model, or create a fresh one
# if there is no checkpoint available.
checkpoints = [checkpoint_dir + "/" + name for name in os.listdir(checkpoint_dir)]
if checkpoints:
latest_checkpoint = max(checkpoints, key=os.path.getctime)
print("Restoring from", latest_checkpoint)
return keras.models.load_model(latest_checkpoint)
print("Creating a new model")
return get_compiled_model()
model = make_or_restore_model()
callbacks = [
# This callback saves a SavedModel every 100 batches.
# We include the training loss in the saved model name.
keras.callbacks.ModelCheckpoint(
filepath=checkpoint_dir + "/ckpt-loss={loss:.2f}", save_freq=100
)
]
model.fit(x_train, y_train, epochs=1, callbacks=callbacks)
Creating a new model 88/1563 [>.............................] - ETA: 3s - loss: 1.1203 - sparse_categorical_accuracy: 0.6911INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=1.04/assets 185/1563 [==>...........................] - ETA: 6s - loss: 0.7768 - sparse_categorical_accuracy: 0.7858INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.75/assets 286/1563 [====>.........................] - ETA: 6s - loss: 0.6382 - sparse_categorical_accuracy: 0.8211INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.63/assets 383/1563 [======>.......................] - ETA: 6s - loss: 0.5584 - sparse_categorical_accuracy: 0.8433INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.55/assets 484/1563 [========>.....................] - ETA: 6s - loss: 0.5032 - sparse_categorical_accuracy: 0.8578INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.50/assets 586/1563 [==========>...................] - ETA: 5s - loss: 0.4644 - sparse_categorical_accuracy: 0.8684INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.46/assets 685/1563 [============>.................] - ETA: 5s - loss: 0.4356 - sparse_categorical_accuracy: 0.8762INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.43/assets 783/1563 [==============>...............] - ETA: 5s - loss: 0.4127 - sparse_categorical_accuracy: 0.8825INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.41/assets 883/1563 [===============>..............] - ETA: 4s - loss: 0.3958 - sparse_categorical_accuracy: 0.8868INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.39/assets 985/1563 [=================>............] - ETA: 3s - loss: 0.3766 - sparse_categorical_accuracy: 0.8918INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.38/assets 1086/1563 [===================>..........] - ETA: 3s - loss: 0.3624 - sparse_categorical_accuracy: 0.8958INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.36/assets 1184/1563 [=====================>........] - ETA: 2s - loss: 0.3498 - sparse_categorical_accuracy: 0.8994INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.35/assets 1283/1563 [=======================>......] - ETA: 1s - loss: 0.3383 - sparse_categorical_accuracy: 0.9029INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.34/assets 1386/1563 [=========================>....] - ETA: 1s - loss: 0.3265 - sparse_categorical_accuracy: 0.9058INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.33/assets 1485/1563 [===========================>..] - ETA: 0s - loss: 0.3184 - sparse_categorical_accuracy: 0.9081INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.32/assets 1563/1563 [==============================] - 11s 7ms/step - loss: 0.3122 - sparse_categorical_accuracy: 0.9097 <keras.callbacks.History at 0x7ff8b53e1dd0>
Zadzwoń również napisz swój własny callback do zapisywania i przywracania modeli.
Dla kompletnego przewodnika po serializacji i oszczędności można znaleźć w instrukcji do zapisywania i szeregowania modele .
Korzystanie z harmonogramów nauki
Typowym wzorcem podczas uczenia modeli głębokiego uczenia się jest stopniowe zmniejszanie uczenia się w miarę postępu uczenia. Jest to ogólnie znane jako „zanikanie szybkości uczenia się”.
Harmonogram zaniku uczenia może być statyczny (z góry ustalony jako funkcja bieżącej epoki lub bieżącego indeksu partii) lub dynamiczny (odpowiadający na bieżące zachowanie modelu, w szczególności na utratę walidacji).
Przekazywanie harmonogramu do optymalizatora
Można łatwo korzystać z harmonogramu szybkość uczenia zaniku statyczne przekazując obiekt harmonogramu jako learning_rate
argument w swojej optymalizatora:
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)
Kilka wbudowanych harmonogramów są dostępne: ExponentialDecay
, PiecewiseConstantDecay
, PolynomialDecay
i InverseTimeDecay
.
Wykorzystanie połączeń zwrotnych do wdrożenia harmonogramu dynamicznego tempa nauki
Dynamiczny harmonogram szybkości uczenia się (na przykład zmniejszenie szybkości uczenia się, gdy utrata walidacji już się nie poprawia) nie może zostać osiągnięty za pomocą tych obiektów harmonogramu, ponieważ optymalizator nie ma dostępu do metryk walidacji.
Jednak wywołania zwrotne mają dostęp do wszystkich metryk, w tym metryk walidacji! W ten sposób można osiągnąć ten wzorzec za pomocą wywołania zwrotnego, które modyfikuje bieżącą szybkość uczenia się w optymalizatorze. W rzeczywistości, to jest nawet wbudowany jako ReduceLROnPlateau
zwrotnego.
Wizualizacja strat i metryk podczas treningu
Najlepszym sposobem, aby mieć oko na modelu podczas treningu jest wykorzystanie TensorBoard - aplikacji opartych na przeglądarce, który można uruchomić lokalnie, które oferuje:
- Żywe wykresy strat i metryki do szkolenia i oceny
- (opcjonalnie) Wizualizacje histogramów aktywacji warstw
- (opcjonalnie) 3D wizualizacje zatapiania przestrzeniach nauczyć swoich
Embedding
warstw
Jeśli zainstalowałeś TensorFlow z pipem, powinieneś być w stanie uruchomić TensorBoard z wiersza poleceń:
tensorboard --logdir=/full_path_to_your_logs
Korzystanie z funkcji zwrotnej TensorBoard
Najprostszym sposobem użycia TensorBoard z modelem Keras i fit()
metody jest TensorBoard
zwrotna.
W najprostszym przypadku po prostu określ, gdzie wywołanie zwrotne ma zapisywać logi i możesz już iść:
keras.callbacks.TensorBoard(
log_dir="/full_path_to_your_logs",
histogram_freq=0, # How often to log histogram visualizations
embeddings_freq=0, # How often to log embedding visualizations
update_freq="epoch",
) # How often to write logs (default: once per epoch)
<keras.callbacks.TensorBoard at 0x7ff88c8c04d0>
Aby uzyskać więcej informacji, zapoznaj się z dokumentacją TensorBoard
zwrotnego .