Random Sampler

A constraint-based random sampler for generating valid samples.

Overview

  • Supports continuous, integer, and categorical features

  • Allows custom constraints

  • Parallel sampling supported

API Reference

class mlsampler.engine.random.RandomSampler(config: SamplerConfig)

Bases: BaseSampler

Random constraint-based sampler.

This sampler generates samples based on feature metadata inferred from training data. Users can register constraints that are applied during sample generation.

Parameters:

config (SamplerConfig) – Configuration object containing feature metadata and sampling settings.

Notes

Two types of constraints are supported:

  • Validation constraints:

    Return a boolean. If False, the sample is rejected.

  • Constructive constraints:

    Return a modified numpy array.

Internally, constraints are unified to return either: - np.ndarray (valid sample) - None (invalid sample)

Sampling is performed with retry logic up to max_retries.

property constraints
reset_constraints()
sample(n_samples: int) → Any

Generate samples satisfying all registered constraints.

Parameters:

n_samples (int) – Total number of samples to generate.

Returns:

Shape (n_samples, n_features). The same type setup was given: an object array for an array, or a pandas/polars DataFrame carrying the input’s column names and per-column dtypes.

Return type:

np.ndarray or DataFrame

Raises:
  • ConstraintValidationError – A constraint refers to a column the data does not have.

  • ConstraintViolationError – A constraint cannot apply to a column’s dtype, or no row satisfied every constraint within max_retries.

Warns:
  • DuplicateColumnWarning – A column is used by more than one constraint.

  • ParallelRngWarning – A constraint was given an explicit rng while n_jobs != 1.

Notes

The generator is reseeded from random_state at the start of every call, so a seeded sampler returns the same rows each time. Pass a different seed, or random_state=None, for fresh draws.

set_constraints(constraint_fn: Literal['sum'], reset: bool = False, *, cols: Sequence[int | str], sum_value: int | float | integer | floating = ..., method: str = ..., alpha: ndarray | None = ..., min_used: int = ..., max_used: int | None = ..., rng: Generator | None = ...) → None
set_constraints(constraint_fn: Literal['sumint'], reset: bool = False, *, cols: Sequence[int | str], sum_value: int = ..., min_used: int = ..., max_used: int | None = ..., rng: Generator | None = ...) → None
set_constraints(constraint_fn: Literal['multihot'], reset: bool = False, *, cols: Sequence[int | str], n_hot: int = ..., rng: Generator | None = ...) → None
set_constraints(constraint_fn: Literal['random'], reset: bool = False, *, cols: Sequence[int | str], min_used: int = ..., max_used: int | None = ..., rng: Generator | None = ...) → None
set_constraints(constraint_fn: Literal['range'], reset: bool = False, *, cols: Sequence[int | str], low: float = ..., high: float = ..., rng: Generator | None = ...) → None
set_constraints(constraint_fn: Literal['categories'], reset: bool = False, *, cols: Sequence[int | str], values: Sequence[Any], strength: str = ..., rng: Generator | None = ...) → None
set_constraints(constraint_fn: Literal['step'], reset: bool = False, *, col: int | str, step: float, low: float, high: float, rng: Generator | None = ...) → None
set_constraints(constraint_fn: Literal['stepsum'], reset: bool = False, *, cols: Sequence[int | str], sum_value: float, lows: ndarray | list | tuple | None = ..., highs: ndarray | list | tuple | None = ..., step: float = ..., rng: Generator | None = ...) → None
set_constraints(constraint_fn: Callable[[ndarray], bool | bool | ndarray], reset: bool = False, *, cols: Sequence[int | str]) → None

Register a constraint on the sampler.

Every constraint takes cols (a list of column indices) except "step", which takes col (a single index). All of them also accept rng, which is honoured only when n_jobs=1.

Supported constraints, with the arguments each one accepts:

  • "sum" : spreads sum_value over cols; also method, alpha, min_used, max_used.

  • "sumint" : as "sum", but splits an integer total; also min_used, max_used.

  • "multihot" : sets exactly n_hot of cols to 1 and the rest to 0.

  • "random" : keeps a random subset of cols, zeroes the rest; also min_used, max_used.

  • "range" : draws cols uniformly from [low, high].

  • "categories" : restricts cols to the combinations in values; strength is "soft" or "hard".

  • "step" : snaps col onto low + k * step inside [low, high].

  • "stepsum" : spreads sum_value over cols in step units, bounded by lows and highs.

  • a callable : takes a row, returns a bool to accept or reject it, or an array to write into cols.

Parameters:
  • constraint_fn (str or callable) – The constraint to register, chosen from the list above.

  • reset (bool, default=False) – If True, clears existing constraints before adding the new one.

  • **kwargs (Any) – Arguments for the chosen constraint, as listed above.

Raises:
  • ConstraintTypeError – The name is not a registered constraint.

  • ConstraintValidationError – The arguments do not match the chosen constraint.

Examples

>>> from mlsampler import RandomSampler
>>> sampler = RandomSampler.setup(X_train)
>>> sampler.set_constraints(
...     lambda row: (0 < row[0] < 1) and (0 < row[1] < 1), cols=[0, 1]
... )
>>> sampler.set_constraints("sum", sum_value=1, cols=[2, 3, 4], max_used=2)
>>> # Step constraint takes col, not cols
>>> sampler.set_constraints("step", col=2, step=0.5, low=0.0, high=5.0)