Skip to content

Local classification experiments

JSON submits the existing classification benchmark. The contract adds identity and lifecycle records. CLI --benchmark also measures inference.

uv sync --locked
uv run --no-sync python -m references.classification.experiment CONFIG.json runs/TRIAL

Input v1

See the example. Paths resolve from CONFIG. TRIAL resolves from the working directory and must not exist, including as a symlink. runs/ is Git-ignored. Unknown fields/versions, invalid values and unsupported limits are rejected before training.

Field Meaning
schema_version Required; 1
recipe Required; CLI names/defaults; required data_path contains ImageFolder train/ and val/
initialization Required; null for random weights or a local checkpoint path; strict weights-only loading
deployment_target Required; null or description; separate from training recipe.device, never measured
test_split Optional held-out ImageFolder path; hashed only, never decoded or used for training/selection

Recipe keys: data_path, arch, device, seed, epochs, lr, batch_size, workers, grad_acc, opt, sched, weight_decay, norm_wd, label_smoothing, mixup_alpha, amp, train_crop_size, val_resize_size, val_crop_size, random_erase, wb, name. Models use the classification catalog; preprocessing uses the existing Imagenette RGB/augment/crop/normalize recipe. Epochs are the only budget. Schedulers: cosine or onecycle (div_factor=100, pct_start=0.1; ten updates rejected). W&B needs optional training dependencies. Seed covers Python, NumPy and PyTorch; identical bits across runtimes are not promised.

Output v1

File Contents
config.json Resolved inputs
provenance.json Source revision/dirty state before trial creation, packages, actual transforms, data/init hashes, optimizer defaults
data.json Matching class mapping, exact split membership and raw-byte SHA-256 hashes; content shared across splits rejected
progress.jsonl Append-only validation epoch events; no intra-epoch heartbeat
result.json Native benchmark runtime/recipe/data/models plus versioned state, timestamps, elapsed time, epoch, actual device, error/traceback and exit code
checkpoint.pth Selected weights; atomic saves preserve the prior file on failure; optimizer/scheduler/RNG state absent, not fully resumable

models[0] separates final_epoch/final_metrics from selected_epoch/ selected_metrics and records checkpoint/checkpoint_sha256. Minimum validation loss selects; ties keep the earlier epoch. metrics_split/metric_directions label loss as minimize and acc1/acc5 as maximize (fractions; acc5 needs five classes). Non-finite validation loss fails. Available metrics/checkpoints survive failure.

State Meaning / exit code
running Setup/training; not proof of liveness
completed All requested epochs and a selected checkpoint; 0
failed Setup/training/tracking exception re-raised; 1
interrupted KeyboardInterrupt 130, SIGTERM 143, or Python's SystemExit code

Split hashes use ordered sample JSON, UTF-8, sorted keys, separators (',', ':'); roots/mapping are separate. Initial weights hash sorted [name, dtype, shape] JSON and contiguous CPU tensor bytes. Re-encoded duplicates are not detected. Data/source are not snapshotted; absent Git metadata is null. Abrupt kills/storage failures may leave running or partial progress. Verify checkpoint hashes before use. No downloads, true resume, wall-time enforcement, search, export/latency or agent servers.

Offline CPU example

Use a fresh trial name:

mkdir -p runs
cp references/classification/experiment.example.json runs/tiny.json
uv run --no-sync python - <<'PY'
from pathlib import Path
from PIL import Image
for i, split in enumerate(("train", "val", "test")):
    for j, label in enumerate(("dark", "light")):
        root = Path("runs/tiny-data") / split / label
        root.mkdir(parents=True, exist_ok=True)
        for sample in range(2):
            Image.new("RGB", (40, 40), (i * 60 + j * 20 + sample, 30, 90)).save(root / f"{sample}.png")
PY
OMP_NUM_THREADS=2 uv run --no-sync python -m references.classification.experiment runs/tiny.json runs/tiny-trial
uv run --no-sync python -m json.tool runs/tiny-trial/result.json