Download scripts/audit_dataset.py from Dev2506/flash-crash-watchdog: direct link, hf CLI and curl.
- Browser
- Download file 3.29 kB
-
https://huggingface.co/Dev2506/flash-crash-watchdog/resolve/main/scripts/audit_dataset.py
- Command line
-
hf download hf://Dev2506/flash-crash-watchdog/scripts/audit_dataset.py
-
curl -L -o audit_dataset.py https://huggingface.co/Dev2506/flash-crash-watchdog/resolve/main/scripts/audit_dataset.py
3.29 kB
| #!/usr/bin/env python3 | |
| """RSR-16: checkpoint/dataset provenance audit. | |
| Verifies that a trained checkpoint's recorded provenance is honest and that its | |
| training inputs do not leak the held-out validation days. | |
| New-style checkpoints (trained by train_tcn_windows.py after RSR-09) carry a | |
| ``provenance`` dict: {trainer, seed, torch_version, input_files, label_mode, | |
| normalize}. This script: | |
| 1. reads the provenance (if present), | |
| 2. checks ``label_mode`` is wall-clock (RSR-02) and ``normalize`` is | |
| rolling-z (BUG-03), | |
| 3. cross-checks the training window files against configs/operating.yml's | |
| held-out validation days — any overlap is a train/test leak. | |
| Legacy checkpoints (e.g. the current stage3_tcn_prod.pt, trained before | |
| stamping) have no provenance: they are reported as unstamped (exit 0 with a | |
| warning — the day-level split is still enforced by scripts/audit_dataset_split.py). | |
| Usage: | |
| PYTHONPATH=ml python scripts/audit_dataset.py \ | |
| --model models/stage3_tcn_prod.pt --config configs/operating.yml | |
| """ | |
| import argparse | |
| import sys | |
| from pathlib import Path | |
| from typing import Any | |
| import torch | |
| import yaml | |
| from flash_crash_watchdog.models.stage3_tcn import TCNConfig | |
| def main() -> int: | |
| ap = argparse.ArgumentParser(description="RSR-16 checkpoint provenance audit") | |
| ap.add_argument("--model", required=True, help="checkpoint .pt") | |
| ap.add_argument("--config", default="configs/operating.yml") | |
| args = ap.parse_args() | |
| torch.serialization.add_safe_globals([TCNConfig]) # MLOPS-06 | |
| state = torch.load(args.model, map_location="cpu", weights_only=True) | |
| prov = state.get("provenance") if isinstance(state, dict) else None | |
| with open(args.config, encoding="utf-8") as f: | |
| op = yaml.safe_load(f) | |
| held = {(d["symbol"], d["date"]) for d in op["validation"]["days"]} | |
| problems = [] | |
| model = Path(args.model).name | |
| if not isinstance(prov, dict): | |
| print(f"[audit] {model}: NO provenance stamp (legacy checkpoint). " | |
| f"Recorded sources cannot be verified; " | |
| f"day-level split enforced by audit_dataset_split.py instead.") | |
| return 0 | |
| print(f"[audit] {model}: provenance present") | |
| for k in ("trainer", "seed", "torch_version", "label_mode", "normalize"): | |
| if k in prov: | |
| print(f" {k}: {prov[k]}") | |
| files = prov.get("input_files", []) | |
| print(f" input_files: {files}") | |
| if prov.get("label_mode") != "wall-clock": | |
| problems.append("label_mode is not wall-clock (RSR-02 violated)") | |
| if prov.get("normalize") != "rolling-z-500": | |
| problems.append("normalize is not rolling-z-500 (BUG-03 violated)") | |
| # Infer which (symbol, date) each training window covers from the filename. | |
| for f in files: | |
| f = Path(f).name | |
| for sym, date in held: | |
| # npz names like LUNAUSDT_2022-05-10_slice_norm500.npz | |
| if sym in f and date in f: | |
| problems.append(f"LEAK: training input '{f}' matches held-out ({sym}, {date})") | |
| if problems: | |
| for p in problems: | |
| print(f" ERROR: {p}", file=sys.stderr) | |
| return 1 | |
| print("[audit] OK: provenance consistent; no training/held-out overlap.") | |
| return 0 | |
| if __name__ == "__main__": | |
| raise SystemExit(main()) |