Metrics
Backprop supports displaying metrics from your experiment as live plots in the web UI. To log metrics, write JSON lines to $BP_RUN_DIR/metrics.jsonl (Backprop sets this environment variable automatically when running your experiment):
{"ts": 1709012345.123, "name": "train/loss", "value": 0.342, "step": 100}{"ts": 1709012345.123, "name": "train/lr", "value": 0.001, "step": 100}{"ts": 1709012400.456, "name": "eval/accuracy", "value": 0.89, "step": 100}Experiment Directory
Section titled “Experiment Directory”Backprop sets the BP_RUN_DIR environment variable when running your experiment. This directory is where you should write metrics and save output files. The path is bp/experiment/<experiment_id>/ relative to your project root.
my-experiment/ ← project root (contains .backpropconfig)├── .backpropconfig├── train.py└── bp/ └── experiment/ └── <experiment_id>/ ├── metrics.jsonl ← write metrics here └── outputs/ ← save output files hereWhen you download results with bp results --download, the same directory structure is created locally — so it feels as if you ran the experiment on your own machine.
Schema
Section titled “Schema”Each line in metrics.jsonl is a JSON object with the following fields:
| Field | Required | Type | Description |
|---|---|---|---|
name | yes | string | Metric name, e.g. train/loss |
value | yes | number | Numeric value |
step | no | number | Training step or iteration |
ts | no | number | Unix timestamp (seconds) |
You can include any additional fields you like (e.g. epoch, split, run). Backprop stores them as metadata and makes them available for filtering in the UI.
Naming Convention
Section titled “Naming Convention”Use / to namespace your metrics. The web UI groups metrics by the suffix (the part after the first /), so metrics that share the same suffix are automatically overlaid on the same chart. The prefix (before the /) becomes the series label.
{"ts": 1709012345.123, "name": "train/loss", "value": 0.34, "step": 100}{"ts": 1709012345.123, "name": "train/lr", "value": 0.001, "step": 100}{"ts": 1709012400.456, "name": "eval/loss", "value": 0.52, "step": 100}{"ts": 1709012400.456, "name": "eval/accuracy", "value": 0.89, "step": 100}{"ts": 1709012400.456, "name": "gpu/memory_gb", "value": 22.4, "step": 100}This would create four panels in the UI: loss (with train and eval series overlaid), lr, accuracy, and memory_gb. This makes it easy to compare the same metric across different splits or stages at a glance.
Logging Metrics from Python
Section titled “Logging Metrics from Python”Here’s a minimal implementation you can drop into your training script:
import jsonimport timeimport os
bp_dir = os.environ["BP_RUN_DIR"]
def log_metric(name, value, step=None, **kwargs): m = {"ts": time.time(), "name": name, "value": value} if step is not None: m["step"] = step m.update(kwargs) with open(os.path.join(bp_dir, "metrics.jsonl"), "a") as f: f.write(json.dumps(m) + "\n")Then call it from your training loop:
for step, batch in enumerate(dataloader): loss = train_step(batch) log_metric("train/loss", loss.item(), step=step)
if step % eval_interval == 0: acc = evaluate(model, val_set) log_metric("eval/accuracy", acc, step=step, split="val")