mrkeyoor.com_
Wed 05 Aug 19:53 UTC
PyPIAI / MLupdated 05 Aug 2026

tensorboard

TensorBoard is the browser dashboard for machine learning runs: point it at a directory of event files and it renders loss curves, histograms, images, audio, text, embedding projections and hyperparameter tables. It installs as a standalone pip package with a CLI (tensorboard --logdir), reads data written by tf.summary, the Keras callback or PyTorch's built-in torch.utils.tensorboard.SummaryWriter, runs entirely offline with no account or server, and treats each subdirectory of your log dir as a separate run for side-by-side comparison.

Verdict

Still the fastest way to see whether your loss is going down, and the only mainstream tracker that is fully local with zero setup. Beyond one person on one machine, a real experiment tracker earns its keep quickly.

API stability5/5The event file format and the --logdir contract have been stable for roughly a decade; the 2.x line tracks TensorFlow's versioning and the writer APIs in both TF and PyTorch rarely change.
Docs4/5tensorflow.org tutorials with Colab walkthroughs cover every dashboard and the README explains the logdir and runs model clearly; the PyTorch writer is documented separately in torch docs, which splits the story across two sites.
Maintenance3/5Releases stay synced to TensorFlow and the repo was pushed within a week of this review, but several hundred open issues and PRs and little new feature work put it in keep-the-lights-on territory.
Ecosystem4/5Writers exist in TensorFlow, PyTorch core, Lightning and Keras, and most trackers can ingest or export its event files, making the format a de facto standard for local training logs; W&B even offers a sync mode for it.

Use it if

  • You want free, local, offline training visualization with zero accounts, agents or infrastructure: pip install, write logs, open localhost:6006
  • You train in PyTorch or Keras and want loss curves and histograms from a few lines, since the writer half already ships inside torch and the Keras callback is one argument
  • You compare experiments on one machine: the subdirectory-per-run convention gives overlay charts and run toggling with no extra code
  • You need the embedding projector or TensorFlow profiler views, which the hosted trackers either lack or gate behind paid tiers
Skip it if

Setup reality

pip install tensorboard is standalone and does not drag in TensorFlow; PyTorch users already have SummaryWriter in the core package. The routine annoyances: nothing appears until the writer flushes (call flush() or close()), every add_* call needs a global_step or your chart collapses into a single point, each run must live in its own subdirectory or curves overwrite each other, port 6006 collides with forgotten instances, and stale runs pile up until you rm the directories. Version skew between tensorboard's protobuf pins and other ML packages occasionally starts dependency resolver fights.

Patterns

Launch TensorBoard on a log directorylaunch-dashboard

tensorboard --logdir runs/
# then open http://localhost:6006

# pick another port when 6006 is taken
tensorboard --logdir runs/ --port 6007

# bind for access from another machine
tensorboard --logdir runs/ --host 0.0.0.0

TensorBoard walks the logdir recursively and treats each subdirectory containing tfevents files as a run; there is no auth, so think before binding 0.0.0.0.

Log training scalars from PyTorchpytorch-log-scalars

from torch.utils.tensorboard import SummaryWriter

writer = SummaryWriter('runs/exp1')

for step, batch in enumerate(loader):
    loss = train_step(batch)
    writer.add_scalar('train/loss', loss.item(), global_step=step)

writer.close()

The writer buffers; without close() or flush() the tail of your run never reaches disk. Slashes in tags group charts into sections.

Log a Keras training runkeras-callback

import tensorflow as tf

tb = tf.keras.callbacks.TensorBoard(
    log_dir='logs/fit/run1',
    histogram_freq=1,
)
model.fit(x_train, y_train, epochs=10,
          validation_data=(x_val, y_val), callbacks=[tb])

histogram_freq=1 adds weight histograms per epoch at a real training-time cost; give each fit its own log_dir or runs merge into one noisy curve.

Write summaries manually in TensorFlow 2tf2-summary-writer

import tensorflow as tf

writer = tf.summary.create_file_writer('logs/run1')

with writer.as_default():
    for step in range(1000):
        loss = train_step()
        tf.summary.scalar('loss', loss, step=step)
writer.flush()

step is mandatory in TF2 summaries; the old tf.summary.FileWriter API from TF1 shown in ancient tutorials no longer applies.

Organize the log directory to compare runscompare-runs-layout

runs/
  baseline/events.out.tfevents...
  lr_0.01/events.out.tfevents...
  lr_0.001/events.out.tfevents...

# tensorboard --logdir runs/  overlays all three

The directory name becomes the run name in the UI, so encode hyperparameters into it; restarted jobs can append new event files to the same run directory and TensorBoard stitches them.

Track weight and gradient distributionslog-histograms

for name, param in model.named_parameters():
    writer.add_histogram(f'weights/{name}', param, global_step=epoch)
    if param.grad is not None:
        writer.add_histogram(f'grads/{name}', param.grad, global_step=epoch)

Histograms are the quickest way to spot dead layers and exploding gradients, but they bloat event files; log per epoch, not per step.

Log image batcheslog-images

import torchvision

grid = torchvision.utils.make_grid(images[:16])
writer.add_image('inputs', grid, global_step=step)

# single HWC numpy image
writer.add_image('sample', img_hwc, global_step=step, dataformats='HWC')

Default dataformats is CHW with values in [0, 1] floats or uint8; wrong layout renders as stripes rather than erroring.

Record hyperparameters with final metricslog-hparams

writer.add_hparams(
    {'lr': 0.01, 'batch_size': 64, 'optimizer': 'adam'},
    {'hparam/val_accuracy': 0.91, 'hparam/val_loss': 0.31},
)

add_hparams writes a nested sub-run per call, which surprises people browsing the logdir; the HParams dashboard then gives a sortable table across runs.

Visualize embeddings in the projectorembedding-projector

writer.add_embedding(
    features,            # (N, D) tensor
    metadata=labels,     # N strings shown as point labels
    label_img=images,    # optional (N, C, H, W) thumbnails
    global_step=step,
)

The projector runs PCA/t-SNE/UMAP in the browser, so keep N in the low thousands; very large embeddings freeze the tab.

Run TensorBoard inside a notebooknotebook-magic

%load_ext tensorboard
%tensorboard --logdir runs/

Works in Jupyter and Colab; rerunning the cell reuses the existing instance, and %reload_ext tensorboard is the fix when the panel goes blank.

Alternatives

PackageRegistryPick it when
wandbPyPIHosted experiment tracking with team access, artifacts and sweeps once local dashboards stop scaling
mlflowPyPISelf-hosted tracking server plus model registry when runs must be stored centrally
aimPyPIAn open source local-first tracker with a faster UI when you have many runs but no appetite for a hosted service