Require tile quality evidence for training
GeoIntel release gates / Compile, test, contracts and builds (push) Canceled after 0s
GeoIntel release gates / Python and npm vulnerability policy (push) Canceled after 0s
GeoIntel release gates / GIS image, SBOM and container scan (push) Canceled after 0s

This commit is contained in:
Jens
2026-07-29 17:37:55 +02:00
parent 037f875575
commit 21c464c715
5 changed files with 64 additions and 5 deletions
+17 -3
View File
@@ -29,7 +29,10 @@ def write_json(path: Path, value: dict[str, Any]) -> None:
temporary.replace(path)
def dataset_audit_failures(audit: dict[str, Any]) -> list[str]:
def dataset_audit_failures(
audit: dict[str, Any],
train_quality_audit: dict[str, Any],
) -> list[str]:
"""Return automated corpus blockers while leaving final human review deferred."""
failures = [str(item) for item in audit.get("failures") or []]
status = audit.get("status")
@@ -39,7 +42,13 @@ def dataset_audit_failures(audit: dict[str, Any]) -> list[str]:
failures.append("corpus manifest is not immutable")
if audit.get("spatial_leakage_status") != "ok":
failures.append("spatial leakage audit is not ok")
if int(audit.get("low_variance_positive_tile_count") or 0) != 0:
if train_quality_audit.get("status") != "ok":
failures.append("train tile quality audit is not ok")
if int(train_quality_audit.get("label_stats", {}).get("invalid_label_count", -1)) != 0:
failures.append("train tile quality audit contains invalid labels")
if int(train_quality_audit.get("label_stats", {}).get("missing_label_file_count", -1)) != 0:
failures.append("train tile quality audit contains missing label files")
if int(train_quality_audit.get("low_variance_positive_tile_count", -1)) != 0:
failures.append("dataset contains blank/low-variance positive tiles")
return failures
@@ -188,6 +197,7 @@ def main() -> int:
parser.add_argument("--train-yaml", type=Path, required=True)
parser.add_argument("--train-summary", type=Path, required=True)
parser.add_argument("--dataset-audit", type=Path, required=True)
parser.add_argument("--train-quality-audit", type=Path, required=True)
parser.add_argument("--calibration-summary", type=Path, required=True)
parser.add_argument("--test-summary", type=Path, required=True)
parser.add_argument("--background-summary", type=Path, required=True)
@@ -230,7 +240,8 @@ def main() -> int:
if args.iterations < 1:
raise SystemExit("--iterations must be positive")
dataset_audit = json.loads(args.dataset_audit.read_text(encoding="utf-8"))
audit_failures = dataset_audit_failures(dataset_audit)
train_quality_audit = json.loads(args.train_quality_audit.read_text(encoding="utf-8"))
audit_failures = dataset_audit_failures(dataset_audit, train_quality_audit)
if audit_failures:
raise SystemExit(f"Dataset audit is not eligible for training: {audit_failures}")
@@ -242,6 +253,9 @@ def main() -> int:
"initial_model": str(args.initial_model),
"train_yaml": str(args.train_yaml),
"dataset_audit": str(args.dataset_audit),
"dataset_audit_sha256": sha256(args.dataset_audit),
"train_quality_audit": str(args.train_quality_audit),
"train_quality_audit_sha256": sha256(args.train_quality_audit),
"corpus_manifest": str(args.corpus_manifest),
"iterations": [],
}
@@ -13,6 +13,8 @@
"/app/storage/operator-data/building-be-v30-rotated-holdouts-r1/train/yolo_tile_dataset_summary.json",
"--dataset-audit",
"/app/storage/operator-data/building-be-v30-rotated-holdouts-r1/audit/belgium-building-corpus-audit.json",
"--train-quality-audit",
"/app/storage/operator-data/building-be-v30-rotated-holdouts-r1/train/audit/operator_yolo_dataset_quality_audit.json",
"--calibration-summary",
"/app/storage/operator-data/building-be-v30-rotated-holdouts-r1/calibration/yolo_tile_dataset_summary.json",
"--test-summary",