Skip to content
AI-grafen
EUniversityScientific method· about 60 min· evolving, reviewed regularly· verified 2026-09-20· EN

Reproducibility

Be able to pin random seeds, versions and data, document a run in a lab journal, and reproduce a result of your own.

Prerequisites

Intuition

Reproducible = somebody else runs your code on your data and gets your result. That requires everything to be pinned:

  • Seeds: Python random, NumPy, PyTorch (CPU and CUDA), and torch.use_deterministic_algorithms(True) — GPU operations are otherwise non-deterministic.
  • Versions: requirements.txt with exact versions (or a lock file), the Python version, the CUDA version.
  • Data: a hash of the data file, or a versioned snapshot (DVC, git-lfs). «Downloaded from X» is not enough — X changes.
  • Code: the git commit, a clean working tree.
  • Configuration: every hyperparameter in a file, not in your head.
  • Environment: a container image if it has to last for years.

Even with everything pinned, GPU results can differ in the last decimal. So report the spread over seeds — that is the honest number, and it makes small deviations irrelevant.

Code

import os, random, hashlib, json, subprocess, sys
import numpy as np, torch

def seed_everything(seed=0):
    random.seed(seed); np.random.seed(seed); torch.manual_seed(seed); torch.cuda.manual_seed_all(seed)
    os.environ["PYTHONHASHSEED"] = str(seed)
    torch.use_deterministic_algorithms(True, warn_only=True)
    torch.backends.cudnn.benchmark = False

def fingerprint(path):
    return hashlib.sha256(open(path, "rb").read()).hexdigest()[:16]

def provenance(config, data_path):
    return {
        "config": config, "data_sha256": fingerprint(data_path),
        "git": subprocess.run(["git", "rev-parse", "HEAD"], capture_output=True, text=True).stdout.strip(),
        "python": sys.version.split()[0], "torch": torch.__version__, "numpy": np.__version__,
        "cuda": torch.version.cuda, "gpu": torch.cuda.get_device_name(0) if torch.cuda.is_available() else None,
    }

seed_everything(0)
print(json.dumps(provenance({"lr": 1e-3, "seed": 0}, "data/train.csv"), indent=2))

Save the output alongside the result. Then run it again — do you get the same number? If not you have found a non-deterministic source; look in the data loading (shuffle without a seed, set ordering, parallel workers).

Mastery means

  • Pins the seeds, the versions and the data for a run
  • Documents it so that another person reproduces the result
  • Distinguishes reproducibility (the same code and data) from replicability (new data)

Sign in to do the exercises and build your mastery up.

Sources

All the sources and licences