TensorBoard
Python
Machine Learning
Data Visualization
Prediction Analysis

How to show training and predicted values on Tensorboard using python

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

TensorBoard is TensorFlow's built-in visualization toolkit that displays training metrics, model graphs, and custom data in a web dashboard. To show training loss, accuracy, and predicted values, you log data using tf.summary writers during training. TensorBoard reads these log files and renders interactive charts. You can log scalars (loss, accuracy), images, histograms, and custom text. For comparing predicted vs actual values, log them as scalars or create custom matplotlib figures and log them as images.

Basic Setup

python
1import tensorflow as tf
2import numpy as np
3
4# Create a log directory
5log_dir = "logs/experiment_1"
6summary_writer = tf.summary.create_file_writer(log_dir)
7
8# Launch TensorBoard (run in terminal)
9# tensorboard --logdir=logs
10# Then open http://localhost:6006 in your browser

Logging Training Metrics

python
1import tensorflow as tf
2from tensorflow import keras
3
4model = keras.Sequential([
5    keras.layers.Dense(64, activation="relu", input_shape=(10,)),
6    keras.layers.Dense(1)
7])
8model.compile(optimizer="adam", loss="mse", metrics=["mae"])
9
10# Option 1: Use the TensorBoard callback (easiest)
11tensorboard_cb = keras.callbacks.TensorBoard(
12    log_dir="logs/run_1",
13    histogram_freq=1,       # Log weight histograms every epoch
14    write_graph=True,       # Log the model graph
15    update_freq="epoch"     # Log metrics every epoch
16)
17
18history = model.fit(
19    X_train, y_train,
20    epochs=50,
21    validation_data=(X_val, y_val),
22    callbacks=[tensorboard_cb]
23)
24# TensorBoard automatically shows loss, mae, val_loss, val_mae

The TensorBoard callback is the simplest way to log training metrics. It automatically records loss and all metrics specified in model.compile().

Logging Custom Scalars

python
1import tensorflow as tf
2
3log_dir = "logs/custom_scalars"
4writer = tf.summary.create_file_writer(log_dir)
5
6# Log custom values during training
7for epoch in range(100):
8    train_loss = train_one_epoch(model, train_data)
9    val_loss = evaluate(model, val_data)
10    learning_rate = optimizer.learning_rate.numpy()
11
12    with writer.as_default():
13        tf.summary.scalar("loss/train", train_loss, step=epoch)
14        tf.summary.scalar("loss/validation", val_loss, step=epoch)
15        tf.summary.scalar("learning_rate", learning_rate, step=epoch)
16
17    writer.flush()

Use the tag/subtag naming convention to group related metrics. TensorBoard displays loss/train and loss/validation on the same chart under the "loss" group.

Logging Predicted vs Actual Values

python
1import tensorflow as tf
2import matplotlib.pyplot as plt
3import io
4
5def log_predictions(writer, model, X_test, y_test, step):
6    predictions = model.predict(X_test).flatten()
7
8    # Log individual predictions as scalars
9    with writer.as_default():
10        for i in range(min(10, len(predictions))):
11            tf.summary.scalar(f"predictions/sample_{i}", predictions[i], step=step)
12            tf.summary.scalar(f"actuals/sample_{i}", y_test[i], step=step)
13
14    # Log a scatter plot as an image
15    fig, ax = plt.subplots(figsize=(8, 8))
16    ax.scatter(y_test, predictions, alpha=0.5)
17    ax.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], "r--")
18    ax.set_xlabel("Actual")
19    ax.set_ylabel("Predicted")
20    ax.set_title(f"Predictions vs Actual (Epoch {step})")
21
22    # Convert matplotlib figure to TensorBoard image
23    buf = io.BytesIO()
24    fig.savefig(buf, format="png", dpi=100, bbox_inches="tight")
25    buf.seek(0)
26    image = tf.image.decode_png(buf.getvalue(), channels=4)
27    image = tf.expand_dims(image, 0)  # Add batch dimension
28
29    with writer.as_default():
30        tf.summary.image("predictions_vs_actual", image, step=step)
31
32    plt.close(fig)
33
34# Use during training
35writer = tf.summary.create_file_writer("logs/predictions")
36for epoch in range(50):
37    train_one_epoch(model, train_data)
38    if epoch % 10 == 0:
39        log_predictions(writer, model, X_test, y_test, epoch)

Classification Predictions with Confusion Matrix

python
1import tensorflow as tf
2import matplotlib.pyplot as plt
3import numpy as np
4from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
5import io
6
7def log_confusion_matrix(writer, model, X_test, y_test, class_names, step):
8    predictions = model.predict(X_test)
9    pred_classes = np.argmax(predictions, axis=1)
10
11    cm = confusion_matrix(y_test, pred_classes)
12
13    fig, ax = plt.subplots(figsize=(8, 8))
14    disp = ConfusionMatrixDisplay(cm, display_labels=class_names)
15    disp.plot(ax=ax, cmap="Blues")
16    ax.set_title(f"Confusion Matrix (Epoch {step})")
17
18    buf = io.BytesIO()
19    fig.savefig(buf, format="png", dpi=100, bbox_inches="tight")
20    buf.seek(0)
21    image = tf.image.decode_png(buf.getvalue(), channels=4)
22    image = tf.expand_dims(image, 0)
23
24    with writer.as_default():
25        tf.summary.image("confusion_matrix", image, step=step)
26
27    plt.close(fig)

Logging Weight Histograms

python
1writer = tf.summary.create_file_writer("logs/histograms")
2
3for epoch in range(50):
4    train_one_epoch(model, train_data)
5
6    with writer.as_default():
7        for layer in model.layers:
8            for weight in layer.weights:
9                tf.summary.histogram(weight.name, weight, step=epoch)

Histograms show how weight distributions change over training — useful for detecting vanishing/exploding gradients.

Comparing Multiple Runs

python
1# Run 1: learning rate 0.001
2model_1 = build_model()
3model_1.compile(optimizer=keras.optimizers.Adam(0.001), loss="mse")
4model_1.fit(X_train, y_train, epochs=50,
5            callbacks=[keras.callbacks.TensorBoard("logs/lr_0.001")])
6
7# Run 2: learning rate 0.01
8model_2 = build_model()
9model_2.compile(optimizer=keras.optimizers.Adam(0.01), loss="mse")
10model_2.fit(X_train, y_train, epochs=50,
11            callbacks=[keras.callbacks.TensorBoard("logs/lr_0.01")])
12
13# TensorBoard shows both runs overlaid on the same charts
14# tensorboard --logdir=logs

Using separate subdirectories under the same parent logs/ directory enables side-by-side comparison of runs.

Launching TensorBoard

bash
1# Terminal command
2tensorboard --logdir=logs --port=6006
3
4# In Jupyter Notebook
5%load_ext tensorboard
6%tensorboard --logdir=logs
7
8# Programmatically
9from tensorboard import program
10tb = program.TensorBoard()
11tb.configure(argv=[None, "--logdir", "logs"])
12url = tb.launch()
13print(f"TensorBoard at: {url}")

Common Pitfalls

  • Not calling writer.flush() or writer.close(): TensorBoard writers buffer data before writing to disk. If you do not flush, recent data may not appear in TensorBoard until the writer is closed or the buffer fills. Call writer.flush() after each epoch for real-time updates.
  • Overwriting log directories between runs: Writing to the same log directory across different training runs mixes old and new data, creating confusing charts with discontinuities. Use unique subdirectories per run (e.g., timestamped names).
  • Logging too frequently: Logging every training step generates massive log files and slows TensorBoard. Log scalars every N steps and images every N epochs. Use update_freq="epoch" or update_freq=100 in the callback.
  • Forgetting to close matplotlib figures: Each plt.subplots() call creates a new figure object. Without plt.close(fig), figures accumulate in memory, causing memory leaks during long training runs.
  • Not adding the batch dimension to images: tf.summary.image() expects a 4D tensor [batch, height, width, channels]. Forgetting tf.expand_dims(image, 0) raises a shape error.

Summary

  • Use keras.callbacks.TensorBoard(log_dir=...) for automatic logging of loss and metrics
  • Use tf.summary.scalar() for custom metric logging and tf.summary.image() for plots
  • Log predicted vs actual values as scatter plots converted to TensorBoard images
  • Use separate log subdirectories per run to enable side-by-side comparison
  • Call writer.flush() to ensure data appears in real-time
  • Launch with tensorboard --logdir=logs and open http://localhost:6006

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.