Keras
TensorFlow
TensorBoard
Deep Learning
Machine Learning

Tensorboard without fit using keras and tf

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 does not depend on model.fit(). It only needs event files, and you can write those yourself from a custom training loop with tf.summary.

Create a Log Directory and Writer

The first step is to create a per-run log directory and a summary writer. Treat each run as a separate folder so TensorBoard can compare experiments cleanly.

python
1from pathlib import Path
2from datetime import datetime
3import tensorflow as tf
4
5run_id = datetime.now().strftime("run_%Y%m%d_%H%M%S")
6log_dir = Path("logs") / run_id
7writer = tf.summary.create_file_writer(str(log_dir))
8
9print(f"Writing logs to: {log_dir}")

That writer is the only piece model.fit() normally hides from you. Once it exists, you can log anything you want at any step.

Log Metrics from a Custom Training Loop

A manual loop is useful when training does not fit the standard epoch and batch pattern. Reinforcement learning, alternating losses, and gradient accumulation are common examples.

Here is a minimal loop that trains a binary classifier and logs loss every ten steps:

python
1import tensorflow as tf
2
3x = tf.random.normal((256, 4))
4y = tf.cast(tf.reduce_sum(x, axis=1, keepdims=True) > 0, tf.float32)
5
6model = tf.keras.Sequential([
7    tf.keras.layers.Input(shape=(4,)),
8    tf.keras.layers.Dense(16, activation="relu"),
9    tf.keras.layers.Dense(1, activation="sigmoid"),
10])
11
12optimizer = tf.keras.optimizers.Adam(learning_rate=0.01)
13loss_fn = tf.keras.losses.BinaryCrossentropy()
14
15for step in range(1, 101):
16    with tf.GradientTape() as tape:
17        predictions = model(x, training=True)
18        loss = loss_fn(y, predictions)
19
20    gradients = tape.gradient(loss, model.trainable_variables)
21    optimizer.apply_gradients(zip(gradients, model.trainable_variables))
22
23    if step % 10 == 0:
24        with writer.as_default():
25            tf.summary.scalar("train/loss", loss, step=step)
26
27writer.flush()

The key rule is that every summary needs a name and a step. TensorBoard builds its charts from those two pieces of information.

Record Validation Metrics and Debug Signals

Once you own the loop, you are not limited to the metrics Keras callbacks happen to expose. You can log validation accuracy, learning rate, gradient norms, or any internal signal that helps explain model behavior.

python
1train_acc = tf.keras.metrics.BinaryAccuracy()
2val_acc = tf.keras.metrics.BinaryAccuracy()
3
4for step in range(1, 51):
5    preds = model(x, training=False)
6    train_acc.update_state(y, preds)
7
8    if step % 10 == 0:
9        val_preds = model(x, training=False)
10        val_acc.update_state(y, val_preds)
11
12        with writer.as_default():
13            tf.summary.scalar("metrics/train_accuracy", train_acc.result(), step=step)
14            tf.summary.scalar("metrics/val_accuracy", val_acc.result(), step=step)
15            tf.summary.histogram("dense/kernel", model.layers[0].kernel, step=step)
16
17        train_acc.reset_state()
18        val_acc.reset_state()

This is one of the biggest advantages of manual logging. You decide when validation runs and what data belongs in TensorBoard, instead of forcing your workflow through fit().

Export a Graph When You Need It

If you want the Graphs tab, trace the function explicitly. That is especially useful when checking whether tf.function compiled your step function the way you expect.

python
1@tf.function
2def forward(inputs):
3    return model(inputs, training=False)
4
5sample = tf.random.normal((1, 4))
6
7tf.summary.trace_on(graph=True, profiler=False)
8_ = forward(sample)
9
10with writer.as_default():
11    tf.summary.trace_export(
12        name="inference_graph",
13        step=0,
14        profiler_outdir=str(log_dir),
15    )

Graph tracing is optional. Scalars are enough for most projects, but graphs are valuable when you are debugging custom layers or tracing behavior.

Start TensorBoard

After writing summaries, launch TensorBoard against the parent directory:

bash
tensorboard --logdir logs --port 6006

If you keep one run per subdirectory, TensorBoard can overlay curves from multiple experiments. That becomes much more useful than the default fit() output once you start comparing hyperparameters or custom schedules.

When This Approach Is Better Than fit()

Custom summary writing is usually the right choice when:

  • one training step contains multiple optimizers or losses,
  • evaluation happens at irregular intervals,
  • you want to log custom tensors or intermediate activations,
  • training state comes from an environment or simulator instead of a dataset iterator.

In those situations, TensorBoard is still the same tool. The only difference is that you take responsibility for writing the summaries yourself.

Common Pitfalls

  • Reusing the same log directory across unrelated runs, which mixes curves and makes comparisons meaningless.
  • Forgetting writer.as_default(), so summaries are not written where you expect.
  • Logging metrics with inconsistent tag names such as loss, train_loss, and train/loss for the same concept.
  • Using step values that reset or jump around, which produces confusing charts.
  • Never calling writer.flush() in short-lived scripts, causing recent summaries to appear missing.

Summary

  • TensorBoard works without model.fit() because it reads event files, not Keras callbacks.
  • Use tf.summary.create_file_writer to create a writer and log directory for each run.
  • Write scalars, histograms, and traces manually from your custom loop.
  • Stable tag names and monotonic step values make TensorBoard runs easy to compare.
  • Manual logging is the better approach whenever your training process does not match the standard fit() workflow.

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.