omniloader.sampling.weights

Class-balance helpers for categorical targets.

Two complementary tools, named for what consumes their output, both counting only valid (unmasked) target positions:

  • class_weights_for_sampler() — one weight per sample for the sampler (SubsampleConfig sample_weights), so an imbalanced dataset is resampled toward a flat class histogram.

  • class_histogram() / class_weights_for_loss() — the exact per-class counts and a (num_classes,) weight vector for a loss (e.g. CrossEntropyLoss(weight=...)). These are data-side statistics: compute once, persist (omniloader class-weights-for-loss), and reuse — the loss/model that consumes them stays in your training code.

Unlike the per-sample sampler weights, the histogram/loss weights count every valid labelled position (each valid step of a framewise (T,) target, or the scalar of a vector target), matching what a per-position loss actually sees.

Functions

class_weights_for_sampler(→ list[float])

Compute per-sample inverse-class-frequency weights for a sampler.

class_histogram(→ torch.Tensor)

Count valid instances of each class for a categorical target.

class_weights_for_loss(→ torch.Tensor)

Compute per-class weights for a loss from a categorical target.

Module Contents

omniloader.sampling.weights.class_weights_for_sampler(samples: collections.abc.Iterable[dict[str, torch.Tensor]], target_key: str) → list[float][source]

Compute per-sample inverse-class-frequency weights for a sampler.

Feed the result to a sampler (e.g. SubsampleConfig sample_weights) to resample an imbalanced dataset toward a flat class histogram. The loss-side counterpart is class_weights_for_loss().

Parameters:
  • samples – An iterable of unified sample dicts (e.g. a source dataset or an OmniLoader). Iterated once.

  • target_key – A categorical (int) target name; its <name>_mask is used to skip invalid positions.

Returns:

A list of per-sample weights (1 / class_count for the sample’s class, 0 when the sample has no valid target), aligned with samples.

omniloader.sampling.weights.class_histogram(samples: collections.abc.Iterable[dict[str, torch.Tensor]], target_key: str, num_classes: int | None = None) → torch.Tensor[source]

Count valid instances of each class for a categorical target.

Parameters:
  • samples – An iterable of unified sample dicts (a source dataset or an OmniLoader). Iterated once.

  • target_key – A categorical (int) target name; its <name>_mask skips invalid positions.

  • num_classes – Number of classes. When None, inferred as max id + 1 (so classes with zero instances are only included when given explicitly).

Returns:

A (num_classes,) int64 tensor of per-class counts.

Raises:

ValueError – If an observed class id is negative or >= num_classes.

omniloader.sampling.weights.class_weights_for_loss(samples: collections.abc.Iterable[dict[str, torch.Tensor]], target_key: str, num_classes: int | None = None, scheme: str = 'inverse', beta: float = 0.999) → torch.Tensor[source]

Compute per-class weights for a loss from a categorical target.

Intended for CrossEntropyLoss(weight=...) and similar — it reweights the loss instead of resampling the data (the sampler-side counterpart is class_weights_for_sampler()). Weights are normalised so they average 1 across classes (the loss keeps its scale). Classes with zero instances get weight 0.

Parameters:
  • samples – An iterable of unified sample dicts. Iterated once.

  • target_key – A categorical (int) target name.

  • num_classes – Number of classes (None infers max id + 1).

  • scheme – "inverse" (inverse frequency 1 / count) or "effective" (effective number of samples, Cui et al. 2019: (1 - beta) / (1 - beta ** count)).

  • beta – Re-weighting strength for scheme="effective" (closer to 1 = stronger balancing).

Returns:

A (num_classes,) float32 weight tensor.

Raises:

ValueError – If scheme is not "inverse" or "effective".