Skip to content

Logging Metrics

Pass a dictionary of metric names to scalar values:

simpcat.log({"train/loss": 0.5, "train/acc": 0.85})

Each log() call with commit=True advances the global step counter. When commit is not specified, it defaults to True when no explicit step is provided, and False when step is given. Metrics appear as time-series charts in the web UI.

Override the auto-incrementing step:

simpcat.log({"val/loss": 0.3}, step=100)

Use commit=False to accumulate metrics across multiple calls, then flush with commit=True:

simpcat.log({"train/loss": 0.5}, commit=False)
simpcat.log({"train/acc": 0.85}, commit=True) # both metrics sent at this step

This is useful when different metrics are computed in different parts of your training loop.

By default, all metrics use the global step as the x-axis. Use define_metric() to plot a metric against a different axis:

simpcat.define_metric("val/loss", step_metric="epoch")
for epoch in range(10):
simpcat.log({"epoch": epoch, "val/loss": validate()})

Now val/loss charts use epoch as the x-axis instead of the global step.

Control how a metric is summarized in the run table:

simpcat.define_metric("val/loss", summary="min")
simpcat.define_metric("val/acc", summary="max")
simpcat.define_metric("train/loss", summary="last")

Valid summary types: "min", "max", "last", "mean", "best".

When runs logged the same conceptual metric under different names (for example val_loss in old runs and validation/loss in new ones), declare aliases so comparison charts merge them into one metric. An alias map is {alternate_name: canonical_name}; resolution is a single lookup within one map, so no canonical name in a map may itself appear as an alternate name in that same map. Across the project and per-run maps each name still resolves exactly one hop using its own effective map, so a name aliased at one scope may legitimately serve as a canonical name at the other.

Project-level aliases apply to every run in the project and are managed with the CLI:

Terminal window
simpcat alias set val_loss=validation/loss --project my-project
simpcat alias list --project my-project
simpcat alias rm val_loss --project my-project

Per-run aliases are set when starting an experiment and override project entries key-by-key:

simpcat.init(project="my-project", metric_aliases={"val_loss": "validation/loss"})

Alternate names are stored as record keys, so they must be printable ASCII, must not start with $, and cannot be __proto__; canonical names are ordinary metric names with no extra restrictions.

Logged data is never rewritten — aliases only change how metric names are grouped when listing and charting. Forked runs inherit the parent run’s aliases (with the child’s own map as overrides); inherited entries that would form a chain with the child’s map — or overflow the 200-entry cap — are dropped and surfaced as a run warning. Resuming a run with metric_aliases= replaces the stored map (an explicit {} clears it); omitting the argument keeps it.

If a single run logged several names from the same alias group (say both val_loss and validation/loss), comparison charts show only one series for that run: the canonical name if logged, otherwise the alphabetically-first alternate. The other series still exists in the data — remove the alias to see it separately.

Log distribution data using simpcat.Histogram:

import numpy as np
import simpcat
run = simpcat.init(project="my-project")
# From a sequence (auto-binned)
weights = model.layer.weight.detach().cpu().numpy().ravel()
simpcat.log({"weights": simpcat.Histogram(weights)})
# Control the number of bins
simpcat.log({"activations": simpcat.Histogram(activations, num_bins=128)})
# From a pre-computed numpy histogram
counts, bin_edges = np.histogram(data, bins=50)
simpcat.log({"custom": simpcat.Histogram(np_histogram=(counts, bin_edges))})

Histograms are displayed as bar charts in the web UI. Max 512 bins.

By default, simpcat.init() starts a background thread that logs system metrics every 15 seconds under the sys/ prefix. Metrics collected (when dependencies are available):

  • CPU/memory/disk (requires psutil): sys/cpu_percent, sys/memory_used_gb, sys/memory_total_gb, sys/memory_percent, sys/disk_used_gb, sys/disk_percent
  • GPU (requires pynvml): sys/gpu.{i}.utilization, sys/gpu.{i}.memory_utilization, sys/gpu.{i}.memory_used_gb, sys/gpu.{i}.memory_total_gb, sys/gpu.{i}.temperature, sys/gpu.{i}.power_w

If neither psutil nor pynvml is installed, system metrics collection is silently skipped.

Disable or adjust:

simpcat.init(project="my-project", system_metrics=False)
# Or change the interval
simpcat.init(project="my-project", system_metrics_interval=30.0)