Callbacks and TensorBoard
What you’ll learn
- what a callback is, and the built-in callbacks Keras ships with
EarlyStoppingEarlyStoppingandModelCheckpointModelCheckpoint, used together to stop and save automatically- writing your own callback by subclassing
keras.callbacks.Callbackkeras.callbacks.Callback - monitoring live training/validation curves with TensorBoard
From paper airplane to drone
Launching model.fit()model.fit() on a long run is, in François Chollet’s words, a bit
like launching a paper airplane: once it leaves your hand, you have no control
over where it goes. A callback turns that into a drone instead — an object
that Keras hands control to at specific points during training, with full
access to the model’s current state, so it can interrupt training, save
weights, or adjust a parameter on the fly.
flowchart TD A["on_train_begin"] --> B["on_epoch_begin"] B --> C["on_batch_begin"] C --> D["on_batch_end"] D -->|"more batches
in this epoch"| C D -->|"epoch finished"| E["on_epoch_end
(EarlyStopping / ModelCheckpoint
check here)"] E -->|"more epochs
to go"| B E -->|"training
finished"| F["on_train_end"]
EarlyStopping and ModelCheckpoint
You rarely know in advance exactly how many epochs a model needs. The standard
fix: EarlyStoppingEarlyStopping interrupts training once a monitored metric (usually
val_lossval_loss or val_accuracyval_accuracy) stops improving for patiencepatience epochs, and
ModelCheckpointModelCheckpoint continuously saves the model — with save_best_only=Truesave_best_only=True,
it only overwrites the file when the monitored metric actually improves, so you
always keep the best version seen during training, not just the last one.
import tensorflow as tf
callbacks_list = [
tf.keras.callbacks.EarlyStopping(monitor="val_accuracy", patience=2),
tf.keras.callbacks.ModelCheckpoint(
filepath="checkpoint_path.keras",
monitor="val_loss",
save_best_only=True,
),
]
model = tf.keras.models.Sequential([
tf.keras.layers.Dense(64, activation="relu", input_shape=(10,)),
tf.keras.layers.Dense(1, activation="sigmoid"),
])
model.compile(optimizer="rmsprop", loss="binary_crossentropy", metrics=["accuracy"])
print([type(cb).__name__ for cb in callbacks_list])
# model.fit(X_train, y_train, epochs=10,
# callbacks=callbacks_list,
# validation_data=(X_val, y_val))import tensorflow as tf
callbacks_list = [
tf.keras.callbacks.EarlyStopping(monitor="val_accuracy", patience=2),
tf.keras.callbacks.ModelCheckpoint(
filepath="checkpoint_path.keras",
monitor="val_loss",
save_best_only=True,
),
]
model = tf.keras.models.Sequential([
tf.keras.layers.Dense(64, activation="relu", input_shape=(10,)),
tf.keras.layers.Dense(1, activation="sigmoid"),
])
model.compile(optimizer="rmsprop", loss="binary_crossentropy", metrics=["accuracy"])
print([type(cb).__name__ for cb in callbacks_list])
# model.fit(X_train, y_train, epochs=10,
# callbacks=callbacks_list,
# validation_data=(X_val, y_val))Note that EarlyStoppingEarlyStopping is watching val_accuracyval_accuracy, so "accuracy""accuracy" must be
part of the model’s metricsmetrics — and because both callbacks need validation
numbers to watch, you must pass validation_datavalidation_data to fit()fit().
Writing your own callback
If nothing built-in covers what you need, subclass keras.callbacks.Callbackkeras.callbacks.Callback
and implement any of on_train_beginon_train_begin / on_train_endon_train_end, on_epoch_beginon_epoch_begin /
on_epoch_endon_epoch_end, or on_batch_beginon_batch_begin / on_batch_endon_batch_end. Every method receives a
logslogs dictionary with whatever metrics are available at that point.
import tensorflow as tf
class LossHistory(tf.keras.callbacks.Callback):
def on_train_begin(self, logs=None):
self.per_batch_losses = []
def on_batch_end(self, batch, logs=None):
self.per_batch_losses.append(logs.get("loss"))
def on_epoch_end(self, epoch, logs=None):
print(f"epoch {epoch}: collected {len(self.per_batch_losses)} batch losses")
self.per_batch_losses = []import tensorflow as tf
class LossHistory(tf.keras.callbacks.Callback):
def on_train_begin(self, logs=None):
self.per_batch_losses = []
def on_batch_end(self, batch, logs=None):
self.per_batch_losses.append(logs.get("loss"))
def on_epoch_end(self, epoch, logs=None):
print(f"epoch {epoch}: collected {len(self.per_batch_losses)} batch losses")
self.per_batch_losses = []Monitoring with TensorBoard
Metrics printed to a progress bar are easy to lose track of over a long
experiment. TensorBoard is a browser-based dashboard that reads the logs a
TensorBoardTensorBoard callback writes during training, and lets you watch live curves,
inspect the model graph, and explore activation/gradient histograms.
import tensorflow as tf
tensorboard_cb = tf.keras.callbacks.TensorBoard(log_dir="./logs")
# model.fit(X_train, y_train, epochs=10,
# validation_data=(X_val, y_val),
# callbacks=[tensorboard_cb])
# then, from a terminal in the same directory:
# tensorboard --logdir ./logsimport tensorflow as tf
tensorboard_cb = tf.keras.callbacks.TensorBoard(log_dir="./logs")
# model.fit(X_train, y_train, epochs=10,
# validation_data=(X_val, y_val),
# callbacks=[tensorboard_cb])
# then, from a terminal in the same directory:
# tensorboard --logdir ./logsIn a notebook (Colab or Jupyter), you can embed the dashboard directly instead of opening a separate browser tab:
# %load_ext tensorboard
# %tensorboard --logdir ./logs# %load_ext tensorboard
# %tensorboard --logdir ./logs🧪 Try It Yourself
Exercise 1 – Configure EarlyStopping’s Patience
Exercise 2 – Save Only the Best Checkpoint
Exercise 3 – Drive a Custom Callback Manually
Next
Continue to Intro to Convolutional Neural Networks (CNN) for Images in Phase 3 — you now have a full toolkit for training, evaluating, and monitoring deep nets; time to point one at real images.
If this helped you, consider buying me a coffee ☕
Buy me a coffeeWas this page helpful?
Let us know how we did
