Reject blank positive imagery in training loop
This commit is contained in:
@@ -117,6 +117,27 @@ class OrthophotoAcquisitionService:
|
||||
valid_from=datetime(2024, 4, 6, tzinfo=UTC),
|
||||
valid_to=datetime(2024, 9, 21, 23, 59, 59, tzinfo=UTC),
|
||||
),
|
||||
OrthophotoProduct(
|
||||
key="wallonia_2023",
|
||||
display_name="Zomerorthofoto Wallonië 2023",
|
||||
observation_label="27 mei tot 25 juni 2023",
|
||||
temporal_granularity="period",
|
||||
native_resolution_m=0.25,
|
||||
wms_url="https://geoservices.wallonie.be/arcgis/services/IMAGERIE/ORTHO_2023_ETE/MapServer/WMSServer",
|
||||
layer="0",
|
||||
catalog_url="https://geoportail.wallonie.be/catalogue/ad55c2ce-62ad-4c3c-b3cf-8fbc270a6b6e.html",
|
||||
limitation_message="Officiële gebiedsdekkende SPW-zomercampagne 2023; exacte vliegdata zijn beschikbaar in het afzonderlijke maillage- en tuilageproduct.",
|
||||
provider="spw_orthophoto",
|
||||
source_label="SPW ORTHO_2023_ETE WMS",
|
||||
attribution="Bron: Service public de Wallonie (SPW), Orthophotos 2023 Été",
|
||||
license_note="CC BY 4.0; citeer SPW en vermeld wijzigingen.",
|
||||
series_namespace="spw",
|
||||
coverage_zone="wallonia",
|
||||
supports_detection=True,
|
||||
observed_at=datetime(2023, 5, 27, tzinfo=UTC),
|
||||
valid_from=datetime(2023, 5, 27, tzinfo=UTC),
|
||||
valid_to=datetime(2023, 6, 25, 23, 59, 59, tzinfo=UTC),
|
||||
),
|
||||
OrthophotoProduct(
|
||||
key="brussels_latest",
|
||||
display_name="Meest recente orthofoto Brussel",
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib.util
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
SCRIPT = Path(__file__).parents[2] / "scripts" / "run_belgium_building_training_loop.py"
|
||||
SPEC = importlib.util.spec_from_file_location("training_loop", SCRIPT)
|
||||
assert SPEC and SPEC.loader
|
||||
MODULE = importlib.util.module_from_spec(SPEC)
|
||||
SPEC.loader.exec_module(MODULE)
|
||||
|
||||
|
||||
def test_training_command_is_cuda_deterministic_and_bound_to_frozen_inputs(tmp_path: Path) -> None:
|
||||
command = MODULE.training_command(
|
||||
"yolo",
|
||||
model=tmp_path / "base.pt",
|
||||
data=tmp_path / "dataset.yaml",
|
||||
project=tmp_path / "runs",
|
||||
name="iteration-001",
|
||||
epochs=160,
|
||||
seed=42,
|
||||
batch=2,
|
||||
workers=4,
|
||||
)
|
||||
assert command[:2] == ["yolo", "train"]
|
||||
assert "device=0" in command
|
||||
assert "deterministic=True" in command
|
||||
assert "seed=42" in command
|
||||
assert "epochs=160" in command
|
||||
assert f"data={tmp_path / 'dataset.yaml'}" in command
|
||||
@@ -65,6 +65,7 @@ def test_operator_yolo_dataset_quality_audit_reports_dataset_risks(tmp_path: Pat
|
||||
"label_count": 2,
|
||||
"is_negative": False,
|
||||
"is_repeated_background_negative": False,
|
||||
"low_visual_variance": True,
|
||||
},
|
||||
{
|
||||
"sample_slug": "postel_bos",
|
||||
@@ -144,6 +145,7 @@ def test_operator_yolo_dataset_quality_audit_reports_dataset_risks(tmp_path: Pat
|
||||
assert report["positive_sample_count"] == 2
|
||||
assert report["background_sample_count"] == 1
|
||||
assert report["train_negative_tile_count"] == 2
|
||||
assert report["low_variance_positive_tile_count"] == 1
|
||||
assert report["repeated_background_negative_tile_count"] == 1
|
||||
assert report["label_stats"]["parsed_label_count"] == 3
|
||||
assert report["label_stats"]["invalid_label_count"] == 0
|
||||
@@ -169,6 +171,7 @@ def test_operator_yolo_dataset_quality_audit_reports_dataset_risks(tmp_path: Pat
|
||||
assert "repeated_background_negative_share_above_gate" in warning_codes
|
||||
assert "median_box_area_below_gate" in warning_codes
|
||||
assert "small_box_share_above_gate" in warning_codes
|
||||
assert "positive_tiles_have_low_visual_variance" in warning_codes
|
||||
|
||||
markdown = (output_dir / "operator_yolo_dataset_quality_audit.md").read_text(encoding="utf-8")
|
||||
assert "Operator YOLO Dataset Quality Audit" in markdown
|
||||
|
||||
@@ -169,7 +169,7 @@ def test_orthophoto_product_registry_exposes_only_governed_official_layers() ->
|
||||
assert {"2025", "2012", "2008_2011", "2000_2003", "1979_1990", "1971"}.issubset(keys)
|
||||
assert next(item for item in products if item["key"] == "most_recent")["supports_detection"] is True
|
||||
detection_keys = {item["key"] for item in products if item["supports_detection"]}
|
||||
assert {"most_recent", "wallonia_latest", "wallonia_2024", "brussels_latest", "brussels_2025", "2025"} <= detection_keys
|
||||
assert {"most_recent", "wallonia_latest", "wallonia_2024", "wallonia_2023", "brussels_latest", "brussels_2025", "2025"} <= detection_keys
|
||||
by_key = {item["key"]: item for item in products}
|
||||
assert by_key["wallonia_latest"]["provider"] == "spw_orthophoto"
|
||||
assert by_key["wallonia_latest"]["coverage_zone"] == "wallonia"
|
||||
|
||||
Reference in New Issue
Block a user