Reject blank positive imagery in training loop
This commit is contained in:
@@ -4,7 +4,7 @@ from __future__ import annotations
|
||||
import argparse
|
||||
import json
|
||||
import statistics
|
||||
from collections import Counter, defaultdict
|
||||
from collections import Counter
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
@@ -246,6 +246,7 @@ def build_audit(summary: dict[str, Any], summary_path: Path, args: argparse.Name
|
||||
]
|
||||
positive_tiles = [tile for tile in tiles if tile not in negative_tiles]
|
||||
train_negative_tiles = [tile for tile in negative_tiles if tile.get("split") == "train"]
|
||||
low_variance_positive_tiles = [tile for tile in positive_tiles if tile.get("low_visual_variance")]
|
||||
val_positive_samples = {
|
||||
str(tile.get("sample_slug"))
|
||||
for tile in positive_tiles
|
||||
@@ -288,6 +289,15 @@ def build_audit(summary: dict[str, Any], summary_path: Path, args: argparse.Name
|
||||
f"gate is {args.max_repeated_negative_share:.3f}."
|
||||
),
|
||||
)
|
||||
if low_variance_positive_tiles:
|
||||
add_warning(
|
||||
warnings,
|
||||
"positive_tiles_have_low_visual_variance",
|
||||
(
|
||||
f"{len(low_variance_positive_tiles)} positive tiles are visually blank/low-variance; "
|
||||
"the imagery source does not support their labels."
|
||||
),
|
||||
)
|
||||
if label_stats["missing_label_file_count"]:
|
||||
add_warning(
|
||||
warnings,
|
||||
@@ -337,6 +347,7 @@ def build_audit(summary: dict[str, Any], summary_path: Path, args: argparse.Name
|
||||
"train_tile_count": split_counts.get("train", 0),
|
||||
"val_tile_count": split_counts.get("val", 0),
|
||||
"train_negative_tile_count": len(train_negative_tiles),
|
||||
"low_variance_positive_tile_count": len(low_variance_positive_tiles),
|
||||
"repeated_background_negative_tile_count": repeated_negative_count,
|
||||
"repeated_background_negative_share_of_negatives": repeated_negative_share,
|
||||
"positive_tile_share": len(positive_tiles) / len(tiles) if tiles else 0.0,
|
||||
@@ -371,6 +382,10 @@ def build_recommendations(warnings: list[dict[str, str]]) -> list[str]:
|
||||
)
|
||||
if "label_files_missing" in codes or "invalid_label_rows" in codes:
|
||||
recommendations.append("Regenerate the YOLO tile dataset and review exporter path/label integrity.")
|
||||
if "positive_tiles_have_low_visual_variance" in codes:
|
||||
recommendations.append(
|
||||
"Reject the raster product for affected AOIs or replace it with an officially complete imagery edition before training."
|
||||
)
|
||||
if not recommendations:
|
||||
recommendations.append("Dataset audit passed the configured gates; continue with benchmarked training.")
|
||||
return recommendations
|
||||
@@ -389,6 +404,7 @@ def write_markdown(report: dict[str, Any], path: Path) -> None:
|
||||
f"- Samples: {report['sample_count']} ({report['positive_sample_count']} positive, {report['background_sample_count']} background)",
|
||||
f"- Repeated background negative share: {report['repeated_background_negative_share_of_negatives']:.3f}",
|
||||
f"- Minimum visible label ratio: {format_optional_float(report.get('min_label_visible_ratio'))}",
|
||||
f"- Blank/low-variance positive tiles: {report['low_variance_positive_tile_count']}",
|
||||
"",
|
||||
"## Label Quality",
|
||||
"",
|
||||
|
||||
Reference in New Issue
Block a user