tensorflow
training progress bar
machine learning
python
deep learning

How to display training progress bar in tensorflow?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

TensorFlow can show training progress in several different ways, and the best choice depends on whether you are using model.fit() or a custom training loop. Many projects overcomplicate this by reaching for third-party progress bars before checking what Keras already provides. In practice, the simplest reliable solution is usually the built-in progress display, with callbacks or manual bars only when you need extra control.

Use Keras Built-In Progress First

If training happens through model.fit(), start with Keras verbosity settings:

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

verbose=1 gives the standard progress bar. verbose=2 prints one line per epoch and is often better for CI logs or remote terminals.

For many teams, this is enough. Replace it only when you need custom metrics or tighter control over display behavior.

Use a Callback for Extra Information

If you want more than the default progress bar, callbacks are the clean extension point.

python
1import tensorflow as tf
2
3class BatchLogger(tf.keras.callbacks.Callback):
4    def on_train_batch_end(self, batch, logs=None):
5        logs = logs or {}
6        loss = logs.get("loss")
7        acc = logs.get("accuracy")
8        print(f"batch={batch} loss={loss:.4f} accuracy={acc:.4f}")
9
10model.fit(
11    x,
12    y,
13    epochs=1,
14    batch_size=32,
15    callbacks=[BatchLogger()],
16    verbose=0,
17)

This is useful when you need to show learning rate, ETA, custom counters, or push metrics into another system without rewriting training.

Use Progbar in a Custom Loop

Once you move to a manual GradientTape loop, the Keras progress bar is gone. At that point, tf.keras.utils.Progbar is a good built-in replacement.

python
1import tensorflow as tf
2
3dataset = tf.data.Dataset.from_tensor_slices((x, y)).batch(32)
4loss_fn = tf.keras.losses.BinaryCrossentropy()
5optimizer = tf.keras.optimizers.Adam()
6
7progbar = tf.keras.utils.Progbar(target=len(list(dataset)))
8
9for step, (batch_x, batch_y) in enumerate(dataset, start=1):
10    with tf.GradientTape() as tape:
11        preds = model(batch_x, training=True)
12        loss = loss_fn(batch_y, preds)
13
14    grads = tape.gradient(loss, model.trainable_variables)
15    optimizer.apply_gradients(zip(grads, model.trainable_variables))
16
17    progbar.update(step, values=[("loss", float(loss))])

Progbar keeps you inside the TensorFlow ecosystem and avoids another dependency. It works well when you want one clear terminal progress line per epoch.

Use tqdm When You Want Richer Control

If you need nested bars, notebook-friendly rendering, or a more customizable loop display, tqdm is a good choice.

python
1from tqdm.auto import tqdm
2
3dataset = tf.data.Dataset.from_tensor_slices((x, y)).batch(32)
4
5for epoch in range(3):
6    bar = tqdm(dataset, desc=f"epoch {epoch + 1}")
7    for batch_x, batch_y in bar:
8        with tf.GradientTape() as tape:
9            preds = model(batch_x, training=True)
10            loss = loss_fn(batch_y, preds)
11
12        grads = tape.gradient(loss, model.trainable_variables)
13        optimizer.apply_gradients(zip(grads, model.trainable_variables))
14
15        bar.set_postfix(loss=float(loss))

The main advantage of tqdm is presentation flexibility. The main drawback is that it is easier to produce messy output if the loop structure is not clean.

Which Option Should You Choose?

Use this rule of thumb:

  • 'model.fit(..., verbose=1) for ordinary Keras training'
  • callbacks when you want extra information during fit
  • 'Progbar for a simple custom TensorFlow loop'
  • 'tqdm when you want richer terminal or notebook UX'

The right answer depends more on the training API than on TensorFlow itself.

Common Pitfalls

  • Updating a Python progress bar inside @tf.function. Fix: keep progress updates outside graph-compiled functions.
  • Printing every batch for long training jobs. Fix: prefer aggregated progress unless you are actively debugging.
  • Materializing the whole dataset just to count steps. Fix: compute step count from dataset metadata or source size when possible.
  • Using terminal-only progress bars in notebooks. Fix: use tqdm.auto or a notebook-aware display mode.
  • Replacing model.fit() progress too early. Fix: start with Keras built-ins before building custom UI logic.

Summary

  • For model.fit(), the built-in Keras progress bar is usually enough.
  • Use callbacks when you want custom status information without rewriting training.
  • Use tf.keras.utils.Progbar for simple custom loops.
  • Use tqdm when presentation control matters more than keeping dependencies minimal.
  • Keep progress updates outside @tf.function and avoid overly chatty per-batch printing in large jobs.

Course illustration
Course illustration

All Rights Reserved.