MaybeRichard's picture
Upload folder using huggingface_hub
b8fae22 verified
Raw History Blame
1.55 kB
"""Deterministic low-data subset selection.
The SAME function is used by (a) the segmentation trainer's real-data loader and
(b) the pixel-diffusion generator's data loader, so that a low-data experiment at
fraction f trains the generator on EXACTLY the real images the segmenter sees —
no leakage, no mismatch, fully reproducible.
Selection is driven only by (fraction, fraction_seed) and the SORTED list of
items, so it is independent of the training seed: the 3 segmentation seeds all
use the identical real subset, only their weight init differs.
"""
from __future__ import annotations
import math
import random
from typing import List, Sequence, TypeVar
T = TypeVar("T")
def select_fraction(items: Sequence[T], fraction: float, seed: int = 0) -> List[T]:
"""Return a deterministic subset of `items` of size ceil(fraction*N).
items: any sequence (e.g. list of (image_path, mask_path) tuples). It is
sorted by repr() first so order of discovery never affects the subset.
fraction: in (0, 1]. >=1 returns all items (sorted copy).
seed: subset seed (NOT the training seed). Fixed across training seeds.
"""
ordered = sorted(items, key=lambda x: repr(x))
n = len(ordered)
if fraction >= 1.0 or n == 0:
return ordered
if fraction <= 0.0:
raise ValueError(f"fraction must be in (0,1], got {fraction}")
k = max(1, math.ceil(fraction * n))
rng = random.Random(seed)
idx = list(range(n))
rng.shuffle(idx)
keep = sorted(idx[:k])
return [ordered[i] for i in keep]