TensorFlow checkpoints keep training state as named object variables rather than as an inference export. They fit jobs that need to pause, resume, or inspect model weights, optimizer slots, and a training counter without packaging the model for serving.
A checkpoint follows the object graph passed to tf.train.Checkpoint. Restoring works when fresh objects use the same trackable names and compatible variable shapes, so a recreated model and optimizer can receive the saved values after their variables have been created.
Checkpoint files belong to the training workflow, while SavedModel exports belong to inference handoff. Keep the checkpoint directory private to the training job, verify the latest checkpoint path before restore, and use assert_consumed() when an exact object match matters.
The demo was verified with TensorFlow 2.21.0. Use the same environment that owns the model code, because checkpoints do not store the Python class or model architecture.
checkpoint-save-restore-demo.py
.
import os import pathlib import shutil os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2" import tensorflow as tf tf.get_logger().setLevel("ERROR") tf.keras.utils.set_random_seed(7) checkpoint_dir = pathlib.Path("training_checkpoints") if checkpoint_dir.exists(): shutil.rmtree(checkpoint_dir) features = tf.constant( [ [0.2, 0.8, 0.4, 0.6], [0.9, 0.1, 0.7, 0.8], [0.1, 0.7, 0.3, 0.4], [0.8, 0.2, 0.6, 0.7], [0.3, 0.9, 0.2, 0.3], [0.7, 0.3, 0.8, 0.9], ], dtype=tf.float32, ) labels = tf.constant([[0.0], [1.0], [0.0], [1.0], [0.0], [1.0]], dtype=tf.float32) probe = tf.constant([[0.15, 0.75, 0.35, 0.45], [0.85, 0.25, 0.65, 0.75]], dtype=tf.float32) def build_model(): return tf.keras.Sequential( [ tf.keras.layers.Input(shape=(4,)), tf.keras.layers.Dense(8, activation="relu"), tf.keras.layers.Dense(1, activation="sigmoid"), ], name="support_score", ) model = build_model() optimizer = tf.keras.optimizers.Adam(learning_rate=0.05) model.compile(optimizer=optimizer, loss="binary_crossentropy") model.fit(features, labels, epochs=8, verbose=0) training_step = tf.Variable(int(optimizer.iterations), dtype=tf.int64) checkpoint = tf.train.Checkpoint(model=model, optimizer=optimizer, training_step=training_step) manager = tf.train.CheckpointManager(checkpoint, checkpoint_dir, max_to_keep=3) save_path = manager.save() before = model(probe, training=False) restored_model = build_model() restored_optimizer = tf.keras.optimizers.Adam(learning_rate=0.05) restored_optimizer.build(restored_model.trainable_variables) restored_step = tf.Variable(0, dtype=tf.int64) restored_checkpoint = tf.train.Checkpoint( model=restored_model, optimizer=restored_optimizer, training_step=restored_step, ) latest_path = tf.train.latest_checkpoint(checkpoint_dir) status = restored_checkpoint.restore(latest_path) status.assert_consumed() after = restored_model(probe, training=False) tf.debugging.assert_near(before, after) print(f"Saved checkpoint: {save_path}") print(f"Latest checkpoint: {latest_path}") print(f"Checkpoint files: {', '.join(sorted(path.name for path in checkpoint_dir.iterdir()))}") print(f"Restored training step: {int(restored_step.numpy())}") print(f"Predictions before save: {[round(float(value), 4) for value in before[:, 0]]}") print(f"Predictions after restore: {[round(float(value), 4) for value in after[:, 0]]}") print("Restore assertion: consumed") print("Prediction match: True") shutil.rmtree(checkpoint_dir) print(f"Cleaned up: {not checkpoint_dir.exists()}")
Build or call the fresh model and optimizer before an exact restore assertion. Optimizers such as Adam create slot variables from the model variables, and those slot variables must exist before assert_consumed() can prove a full restore.
$ python3 checkpoint-save-restore-demo.py Saved checkpoint: training_checkpoints/ckpt-1 Latest checkpoint: training_checkpoints/ckpt-1 Checkpoint files: checkpoint, ckpt-1.data-00000-of-00001, ckpt-1.index Restored training step: 8 Predictions before save: [0.3968, 0.646] Predictions after restore: [0.3968, 0.646] Restore assertion: consumed Prediction match: True Cleaned up: True
Restore assertion: consumed confirms that every saved checkpoint value matched a tracked object in the restored model, optimizer, and training step. Prediction match: True confirms that the restored model variables produce the same outputs for the probe batch.