File size: 1,553 Bytes
b8fae22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
"""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]