Logging Metrics
Basic logging
Section titled “Basic logging”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.
Explicit steps
Section titled “Explicit steps”Override the auto-incrementing step:
simpcat.log({"val/loss": 0.3}, step=100)Buffered logging
Section titled “Buffered logging”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 stepThis is useful when different metrics are computed in different parts of your training loop.
Custom x-axes
Section titled “Custom x-axes”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.
Summary aggregation
Section titled “Summary aggregation”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".
Metric aliases
Section titled “Metric aliases”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:
simpcat alias set val_loss=validation/loss --project my-projectsimpcat alias list --project my-projectsimpcat alias rm val_loss --project my-projectPer-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.
Histograms
Section titled “Histograms”Log distribution data using simpcat.Histogram:
import numpy as npimport 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 binssimpcat.log({"activations": simpcat.Histogram(activations, num_bins=128)})
# From a pre-computed numpy histogramcounts, 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.
System metrics
Section titled “System metrics”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 intervalsimpcat.init(project="my-project", system_metrics_interval=30.0)