machine learning
tensorflow
model saving
validation accuracy
neural networks

tensorflowCan save best model only with val_acc available, skipping

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

The warning about saving best model only when val_acc is available means your checkpoint monitor name does not match the metrics emitted during training. In modern TensorFlow, metric names changed over time, so many older examples still reference outdated keys. The fix is to align ModelCheckpoint.monitor with the actual history keys and ensure validation metrics are being computed.

Why the Warning Appears

ModelCheckpoint saves based on the metric named in monitor. If the metric never appears in logs, callback logic cannot decide what is "best" and skips saving.

Common reasons:

  • using val_acc while model reports val_accuracy
  • no validation data passed to fit
  • custom training step not logging the monitored name
  • typo in monitor string

You can always inspect available metric names after a short run.

python
1import tensorflow as tf
2import numpy as np
3
4x = np.random.rand(200, 20).astype("float32")
5y = np.random.randint(0, 2, size=(200, 1))
6
7model = tf.keras.Sequential([
8    tf.keras.layers.Dense(32, activation="relu", input_shape=(20,)),
9    tf.keras.layers.Dense(1, activation="sigmoid"),
10])
11
12model.compile(optimizer="adam", loss="binary_crossentropy", metrics=["accuracy"])
13
14history = model.fit(x, y, epochs=1, batch_size=16, validation_split=0.2, verbose=0)
15print(history.history.keys())

This printout tells you exactly which monitor names are valid in your environment.

Correct ModelCheckpoint Configuration

In current TensorFlow, use val_accuracy for binary and categorical classification unless you explicitly rename metrics.

python
1checkpoint = tf.keras.callbacks.ModelCheckpoint(
2    filepath="best_model.keras",
3    monitor="val_accuracy",
4    mode="max",
5    save_best_only=True,
6    verbose=1,
7)
8
9history = model.fit(
10    x,
11    y,
12    epochs=10,
13    batch_size=16,
14    validation_split=0.2,
15    callbacks=[checkpoint],
16)

If you monitor loss instead, use mode="min" and monitor="val_loss".

python
1checkpoint_loss = tf.keras.callbacks.ModelCheckpoint(
2    filepath="best_by_loss.keras",
3    monitor="val_loss",
4    mode="min",
5    save_best_only=True,
6)

Pick one objective and keep it consistent with model goals.

Ensure Validation Metrics Exist

No validation metrics means no val_ keys, even with correct monitor spelling. You need either validation_split or explicit validation_data.

python
1x_val = np.random.rand(40, 20).astype("float32")
2y_val = np.random.randint(0, 2, size=(40, 1))
3
4model.fit(
5    x,
6    y,
7    epochs=5,
8    validation_data=(x_val, y_val),
9    callbacks=[checkpoint],
10)

For sequence and custom dataset pipelines, verify validation dataset is non-empty and batched correctly.

Debugging With Callback Logs

If checkpointing still skips, add a small callback to print epoch log keys.

python
1class LogKeys(tf.keras.callbacks.Callback):
2    def on_epoch_end(self, epoch, logs=None):
3        print(f"epoch {epoch} keys:", sorted((logs or {}).keys()))
4
5model.fit(
6    x,
7    y,
8    epochs=3,
9    validation_split=0.2,
10    callbacks=[checkpoint, LogKeys()],
11)

This removes guesswork and immediately shows whether your monitor key exists.

Notes on save_weights_only and File Formats

Choose whether you want full model serialization or only weights. Full model saves optimizer state and architecture, which is usually easier for deployment reproducibility.

python
1checkpoint_weights = tf.keras.callbacks.ModelCheckpoint(
2    filepath="weights_only.weights.h5",
3    monitor="val_accuracy",
4    mode="max",
5    save_best_only=True,
6    save_weights_only=True,
7)

When using save_weights_only=True, remember to rebuild model architecture before loading weights.

Verify Saved Artifacts During Training

Do not assume checkpoints are being written just because training logs continue. Confirm files appear and update as epochs progress.

python
1from pathlib import Path
2
3path = Path(\"best_model.keras\")
4print(\"exists:\", path.exists())
5if path.exists():
6    print(\"size bytes:\", path.stat().st_size)

For team workflows, store checkpoint path, monitored metric, and best value in run metadata. This makes experiment audits much easier when comparing runs across branches and environments.

Common Pitfalls

  • Monitoring val_acc in environments that emit val_accuracy.
  • Forgetting to pass validation data and expecting val_ metrics.
  • Using mode="max" while monitoring a metric that should decrease.
  • Typo in monitor string such as val_acuracy.
  • Mixing full model and weights-only workflows without clear restore logic.

Summary

  • The warning means the monitored metric was not found in epoch logs.
  • Use history keys to choose the exact monitor name.
  • Prefer val_accuracy on modern TensorFlow unless custom names are defined.
  • Always provide validation data if monitoring val_ metrics.
  • Add callback log inspection to debug checkpoint behavior quickly.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.