data generators
ssms.dataset_generators.estimator_builders
Estimator builder implementations.
This module contains builder classes that construct likelihood estimators from configuration dictionaries. Builders follow the EstimatorBuilderProtocol and handle the responsibility of extracting relevant parameters from configs.
Available builders: - KDEEstimatorBuilder: Builds KDE-based likelihood estimators - Works with all models - Requires simulation data
- PyDDMEstimatorBuilder: Builds PyDDM analytical PDF estimators
- Only for compatible models (single-particle, two-choice, Gaussian noise)
- Does not require simulation data (purely analytical)
- Requires optional 'pyddm' package: pip install pyddm
Factory: - create_estimator_builder: Factory function for creating builders based on config - Automatically selects appropriate builder based on 'estimator_type' - Handles compatibility checking and error messages
KDEEstimatorBuilder
Builder for KDE-based likelihood estimators.
This builder is responsible for: 1. Extracting relevant parameters from the generator_config 2. Instantiating KDELikelihoodEstimator with explicit parameters 3. Fitting the estimator with provided simulations
Attributes:
-
generator_config(dict) –Configuration dictionary containing KDE settings
-
displace_t(bool) –Extracted parameter: whether to displace time by the t parameter
Examples:
>>> builder = KDEEstimatorBuilder(generator_config)
>>> estimator = builder.build(theta, simulations)
>>> log_liks = estimator.evaluate(rts, choices)
Notes
Implements EstimatorBuilderProtocol from protocols.py Extracted from lan_mlp.py as part of Phase 1 refactoring
Arguments
generator_config : dict Configuration dictionary in nested structure containing: - estimator.displace_t (optional): Whether to displace time by t parameter. Defaults to False if not specified.
build
Build and fit a KDE likelihood estimator.
This method: 1. Creates a KDELikelihoodEstimator with extracted parameters 2. Fits it with the provided simulations
Arguments
theta : dict Parameter dictionary (not directly used by KDE, but part of protocol) simulations : dict | None Simulation data containing 'rts', 'choices', and 'metadata' keys. Required for KDE estimators (cannot be None).
Returns:
-
KDELikelihoodEstimator–A fitted likelihood estimator ready for evaluate() or sample() calls
Raises:
-
ValueError–If simulations is None (KDE requires simulation data)
Examples:
>>> builder = KDEEstimatorBuilder({"kde_displace_t": False})
>>> estimator = builder.build(theta, simulations)
>>> assert estimator._kde is not None # Verifies it's fitted
Notes
The theta parameter is included in the signature to conform to EstimatorBuilderProtocol. Future estimator types (e.g., PyDDM) will use theta to configure model-specific parameters.
PyDDMEstimatorBuilder
Builder for PyDDM analytical PDF estimators.
This builder: 1. Validates model compatibility with PyDDM at construction 2. Builds PyDDM models using SSMSToPyDDMMapper for each theta 3. Solves the Fokker-Planck equation analytically 4. Wraps the solution in a PyDDMLikelihoodEstimator
Key advantages: - No simulation required (purely analytical) - Deterministic results - Fast for compatible models
Compatible models: - Single-particle, two-choice models - Gaussian noise only - Examples: ddm, ornstein, angle, weibull, gamma_drift, conflict_*
Incompatible models: - Multi-particle: race_, lca_, lba* - Non-Gaussian noise: levy - Inter-trial variability: full_ddm, ddm_sdv, ddm_st
Validates model compatibility at construction time (fail-fast approach).
Args: generator_config: Generator settings including: - delta_t: Time step for solving - max_t: Maximum time - pdf_interpolation: 'linear' or 'cubic' (optional, defaults to 'cubic') model_config: Model specification from ssms.config
Raises: ValueError: If model is not compatible with PyDDM ImportError: If pyddm package is not installed
build
Build PyDDM likelihood estimator for given parameters.
Unlike KDE builder, this does NOT require simulation data. The estimator is built by solving the Fokker-Planck equation analytically.
Args: theta: Model parameters (v, a, z, t, etc.) simulations: Ignored (PyDDM doesn't need simulations)
Returns: PyDDMLikelihoodEstimator instance fitted to theta
Raises: ValueError: If PyDDM model cannot be built (e.g., invalid parameters)
Note: The simulations parameter is accepted for protocol compliance but is not used by PyDDM estimators.
builder_factory
Builder factory for creating likelihood estimators based on configuration.
This module provides a factory function that selects the appropriate estimator builder based on the generator_config settings. This enables seamless switching between different likelihood estimation methods (KDE, PyDDM, etc.) via configuration alone.
create_estimator_builder
Create appropriate estimator builder based on configuration.
This factory function examines the generator_config and returns the appropriate builder for likelihood estimation.
Arguments
generator_config : dict Configuration dictionary containing: - 'estimator.type' (str): Estimator type ('kde' or 'pyddm') model_config : dict Model configuration dictionary (used for PyDDM builder)
Returns:
-
EstimatorBuilderProtocol–An estimator builder instance
Raises:
-
ImportError–If 'pyddm' estimator is requested but pyddm package is not installed
-
ValueError–If an unknown estimator_type is specified or if model is incompatible with PyDDM
Examples:
>>> # Default to KDE
>>> builder = create_estimator_builder({}, {})
>>> isinstance(builder, KDEEstimatorBuilder)
True
>>> # Explicit KDE
>>> config = {"estimator": {"type": "kde"}}
>>> builder = create_estimator_builder(config, {})
>>> isinstance(builder, KDEEstimatorBuilder)
True
>>> # PyDDM estimator (requires pyddm package)
>>> config = {"estimator": {"type": "pyddm"}}
>>> builder = create_estimator_builder(config, model_config["ddm"])
>>> isinstance(builder, PyDDMEstimatorBuilder)
True
Notes
PyDDM estimator requires the optional 'pyddm' package. Install with: pip install pyddm or pip install ssms[pyddm]
PyDDM is only compatible with single-particle, two-choice, Gaussian noise models. Incompatible models will raise ValueError at builder construction.
See Also
KDEEstimatorBuilder : Builder for KDE-based likelihood estimators
create_estimator_builder
Create appropriate estimator builder based on configuration.
This factory function examines the generator_config and returns the appropriate builder for likelihood estimation.
Arguments
generator_config : dict Configuration dictionary containing: - 'estimator.type' (str): Estimator type ('kde' or 'pyddm') model_config : dict Model configuration dictionary (used for PyDDM builder)
Returns:
-
EstimatorBuilderProtocol–An estimator builder instance
Raises:
-
ImportError–If 'pyddm' estimator is requested but pyddm package is not installed
-
ValueError–If an unknown estimator_type is specified or if model is incompatible with PyDDM
Examples:
>>> # Default to KDE
>>> builder = create_estimator_builder({}, {})
>>> isinstance(builder, KDEEstimatorBuilder)
True
>>> # Explicit KDE
>>> config = {"estimator": {"type": "kde"}}
>>> builder = create_estimator_builder(config, {})
>>> isinstance(builder, KDEEstimatorBuilder)
True
>>> # PyDDM estimator (requires pyddm package)
>>> config = {"estimator": {"type": "pyddm"}}
>>> builder = create_estimator_builder(config, model_config["ddm"])
>>> isinstance(builder, PyDDMEstimatorBuilder)
True
Notes
PyDDM estimator requires the optional 'pyddm' package. Install with: pip install pyddm or pip install ssms[pyddm]
PyDDM is only compatible with single-particle, two-choice, Gaussian noise models. Incompatible models will raise ValueError at builder construction.
See Also
KDEEstimatorBuilder : Builder for KDE-based likelihood estimators
kde_builder
KDE Estimator Builder.
This module implements the builder pattern for KDE-based likelihood estimators. The builder extracts relevant parameters from the generator_config and instantiates a KDELikelihoodEstimator with explicit parameters.
This separation of concerns ensures that: 1. KDELikelihoodEstimator remains focused on likelihood estimation 2. Configuration parsing logic is centralized in the builder 3. New estimator parameters can be added with minimal changes
KDEEstimatorBuilder
Builder for KDE-based likelihood estimators.
This builder is responsible for: 1. Extracting relevant parameters from the generator_config 2. Instantiating KDELikelihoodEstimator with explicit parameters 3. Fitting the estimator with provided simulations
Attributes:
-
generator_config(dict) –Configuration dictionary containing KDE settings
-
displace_t(bool) –Extracted parameter: whether to displace time by the t parameter
Examples:
>>> builder = KDEEstimatorBuilder(generator_config)
>>> estimator = builder.build(theta, simulations)
>>> log_liks = estimator.evaluate(rts, choices)
Notes
Implements EstimatorBuilderProtocol from protocols.py Extracted from lan_mlp.py as part of Phase 1 refactoring
Arguments
generator_config : dict Configuration dictionary in nested structure containing: - estimator.displace_t (optional): Whether to displace time by t parameter. Defaults to False if not specified.
build
Build and fit a KDE likelihood estimator.
This method: 1. Creates a KDELikelihoodEstimator with extracted parameters 2. Fits it with the provided simulations
Arguments
theta : dict Parameter dictionary (not directly used by KDE, but part of protocol) simulations : dict | None Simulation data containing 'rts', 'choices', and 'metadata' keys. Required for KDE estimators (cannot be None).
Returns:
-
KDELikelihoodEstimator–A fitted likelihood estimator ready for evaluate() or sample() calls
Raises:
-
ValueError–If simulations is None (KDE requires simulation data)
Examples:
>>> builder = KDEEstimatorBuilder({"kde_displace_t": False})
>>> estimator = builder.build(theta, simulations)
>>> assert estimator._kde is not None # Verifies it's fitted
Notes
The theta parameter is included in the signature to conform to EstimatorBuilderProtocol. Future estimator types (e.g., PyDDM) will use theta to configure model-specific parameters.
pyddm_builder
Builder for PyDDM-based likelihood estimators.
PyDDMEstimatorBuilder
Builder for PyDDM analytical PDF estimators.
This builder: 1. Validates model compatibility with PyDDM at construction 2. Builds PyDDM models using SSMSToPyDDMMapper for each theta 3. Solves the Fokker-Planck equation analytically 4. Wraps the solution in a PyDDMLikelihoodEstimator
Key advantages: - No simulation required (purely analytical) - Deterministic results - Fast for compatible models
Compatible models: - Single-particle, two-choice models - Gaussian noise only - Examples: ddm, ornstein, angle, weibull, gamma_drift, conflict_*
Incompatible models: - Multi-particle: race_, lca_, lba* - Non-Gaussian noise: levy - Inter-trial variability: full_ddm, ddm_sdv, ddm_st
Validates model compatibility at construction time (fail-fast approach).
Args: generator_config: Generator settings including: - delta_t: Time step for solving - max_t: Maximum time - pdf_interpolation: 'linear' or 'cubic' (optional, defaults to 'cubic') model_config: Model specification from ssms.config
Raises: ValueError: If model is not compatible with PyDDM ImportError: If pyddm package is not installed
build
Build PyDDM likelihood estimator for given parameters.
Unlike KDE builder, this does NOT require simulation data. The estimator is built by solving the Fokker-Planck equation analytically.
Args: theta: Model parameters (v, a, z, t, etc.) simulations: Ignored (PyDDM doesn't need simulations)
Returns: PyDDMLikelihoodEstimator instance fitted to theta
Raises: ValueError: If PyDDM model cannot be built (e.g., invalid parameters)
Note: The simulations parameter is accepted for protocol compliance but is not used by PyDDM estimators.
ssms.dataset_generators.lan_mlp
This module defines a data generator class for use with LANs. The class defined below can be used to generate training data compatible with the expectations of LANs.
Note: Multiprocessing start method is configured in ssms/init.py to use 'spawn' by default for OpenMP safety. Override with SSMS_MP_START_METHOD environment variable if needed.
TrainingDataGenerator
The TrainingDataGenerator() class is used to generate training data for various likelihood approximators.
Attributes:
-
generator_config(dict) –Configuration dictionary for the data generator. (For an example load ssms.get_default_generator_config())model_config: dict Configuration dictionary for the model to be simulated. (For an example load ssms.config.model_config['ddm']) _generation_pipeline: DataGenerationPipelineProtocol Strategy for orchestrating the complete data generation workflow.
Methods:
-
generate_data_training_uniform–Generates training data for LANs. _get_ncpus() Helper function for determining the number of cpus to use for parallelization.
Returns:
-
TrainingDataGenerator object–
Notes
The class supports dependency injection of generation_pipeline, enabling complete customization of the data generation workflow. By default, it auto-creates the appropriate strategy based on generator_config settings (KDE-based simulation or PyDDM analytical methods).
Arguments
config: dict or DataGenerationPipelineProtocol Either: - A dictionary with generator configuration (e.g., from ssms.config.get_default_generator_config()). The TrainingDataGenerator will auto-create the appropriate strategy. - A DataGenerationPipelineProtocol instance for complete custom control over the data generation workflow. model_config: dict, optional Configuration dictionary for the model to be simulated. (For an example load ssms.config.model_config['ddm']) This serves as the single source of truth for model specifications, parameter bounds, transforms, and custom drift/boundary functions.
**Optional** when config is a dict containing a 'model' field - will
auto-derive using ModelConfigBuilder.from_model(config['model']).
**Optional** when config is a pipeline (extracted from pipeline if not provided).
Raises:
-
ValueError–If config is None, or if model_config is None and cannot be derived (i.e., config is a dict without 'model' field), or if model_config cannot be extracted from a pipeline.
Returns:
-
TrainingDataGenerator object–
Notes
Simple Usage (recommended): Pass a generator_config dict with 'model' field set. The TrainingDataGenerator will auto-derive model_config and create the appropriate strategy.
Explicit model_config: Pass both generator_config and model_config for complete control over model configuration (e.g., custom param_bounds).
Advanced Usage: Pass a custom DataGenerationPipelineProtocol instance to completely control the workflow (parameter sampling, simulation, estimation, etc.). In this case, model_config can be omitted (will use pipeline's config).
The pipeline internally manages: - Parameter sampling (uniform, Sobol, custom) - Simulation or analytical PDF computation - Likelihood estimation (KDE, PyDDM analytical) - Training data structuring (ResampleMixture, etc.)
For custom drift/boundary functions, use ModelConfigBuilder to create a custom model_config before passing it to TrainingDataGenerator.
Examples:
Simple (auto-derive model_config from generator_config['model']): >>> from ssms import get_default_generator_config >>> config = get_default_generator_config(model="ddm_deadline") >>> gen = TrainingDataGenerator(config) # model_config auto-derived! >>> data = gen.generate_data_training()
Explicit model_config (for custom bounds): >>> from ssms.config import ModelConfigBuilder >>> model_config = ModelConfigBuilder.from_model("ddm", param_bounds=[...]) >>> gen = TrainingDataGenerator(generator_config, model_config) >>> data = gen.generate_data_training()
Advanced (custom pipeline, model_config from pipeline): >>> from ssms.dataset_generators.pipelines import SimulationPipeline >>> custom_pipeline = SimulationPipeline( ... generator_config, model_config, ... estimator_builder=MyCustomBuilder(...), ... training_strategy=MyCustomStrategy(...), ... ) >>> gen = TrainingDataGenerator(custom_pipeline) # model_config optional! >>> data = gen.generate_data_training()
generate_data_training
Generates training data for LANs.
Arguments
save: bool
If True, the generated data is saved to disk.
verbose: bool
If True, progress is printed to the console.
Returns:
-
data: dict–Dictionary containing the generated data.
Notes
Phase 4 refactoring: This method now delegates to the
generation_pipeline, which handles the complete workflow from
parameter sampling to training data generation. This eliminates
wasteful simulations for analytical methods (PyDDM) and provides
a clean, modular architecture.
ssms.dataset_generators.likelihood_estimators
Likelihood estimators for training data generation.
This module provides implementations of LikelihoodEstimatorProtocol: - KDELikelihoodEstimator: KDE-based estimator from simulated samples - Works with all models - Requires simulation data for fitting
- PyDDMLikelihoodEstimator: Analytical PDF-based estimator using PyDDM
- Only for compatible models (single-particle, two-choice, Gaussian noise)
- Does not require simulation data (uses Fokker-Planck solution)
- Deterministic results
- Requires optional 'pyddm' package: pip install pyddm
KDELikelihoodEstimator
KDE-based likelihood estimator.
This estimator builds a kernel density estimate from simulated (RT, choice) samples and uses it to estimate the likelihood P(RT, choice | theta).
Attributes:
-
displace_t(bool) –Whether to displace time by the t parameter (non-decision time)
-
_kde(LogKDE | None) –The fitted KDE object (None before fit() is called)
-
_metadata(dict | None) –Metadata from simulations (None before fit() is called)
Examples:
>>> estimator = KDELikelihoodEstimator(displace_t=False)
>>> estimator.fit(simulations)
>>> log_liks = estimator.evaluate(rts, choices)
>>> samples = estimator.sample(n_samples=1000)
Arguments
displace_t : bool, optional Whether to displace time by the t parameter (non-decision time). Only works if all simulations have the same t value. Default is False.
evaluate
Evaluate log-likelihood at given (RT, choice) pairs.
Arguments
rts : np.ndarray Reaction times to evaluate, shape (n_samples,) choices : np.ndarray Choices to evaluate, shape (n_samples,)
Returns:
-
log_likelihoods(ndarray) –Log-likelihood for each (RT, choice) pair, shape (n_samples,)
Raises:
-
ValueError–If fit() has not been called yet
Notes
Extracted from lan_mlp.py lines 312, 342-344
fit
Build KDE from simulation data.
This method constructs a kernel density estimate from the provided simulations. Must be called before evaluate() or sample().
Arguments
simulations : dict Dictionary containing simulation data with keys: - 'rts': np.ndarray of reaction times - 'choices': np.ndarray of choices - 'metadata': dict with model information
Notes
Extracted from lan_mlp.py lines 305-308
get_metadata
Return metadata from the simulations.
Returns:
-
metadata(dict) –Dictionary containing simulation metadata including: - 'max_t': Maximum time value - 'possible_choices': List of possible choice values - Other model-specific metadata
Raises:
-
ValueError–If fit() has not been called yet
sample
Sample (RT, choice) pairs from the KDE.
Arguments
n_samples : int Number of samples to generate random_state : int | None, optional Random seed for reproducibility. If None, uses non-reproducible random behavior.
Returns:
-
samples(dict) –Dictionary with keys: - 'rts': np.ndarray of sampled reaction times, shape (n_samples,) - 'choices': np.ndarray of sampled choices, shape (n_samples,)
Raises:
-
ValueError–If fit() has not been called yet
Notes
Extracted from lan_mlp.py line 311
PyDDMLikelihoodEstimator
Likelihood estimator using PyDDM's analytical Fokker-Planck solutions.
Unlike KDE estimators which resample from simulations, this estimator uses PyDDM's Fokker-Planck solver to compute analytical PDFs and interpolates them for fast likelihood evaluation.
Key advantages: - No simulation required (purely analytical) - Deterministic (no sampling variability) - Fast evaluation via interpolation - Exact solutions for compatible models
Limitations: - Only works for PyDDM-compatible models (single-particle, two-choice, Gaussian noise)
The estimator extracts PDFs from the solution internally and creates interpolators for fast likelihood evaluation.
Args: pyddm_solution: PyDDM Solution object from model.solve() t_domain: Time domain array from model.t_domain() interpolation: Interpolation method ('linear' or 'cubic')
evaluate
Evaluate log-likelihood at (RT, choice) pairs.
Uses interpolation for fast evaluation. RTs outside the time domain are assigned zero probability (log-likelihood = -inf, clipped to -66).
Args: rts: Reaction times, shape (n,) choices: Choices in {-1, 1}, shape (n,)
Returns: Log-likelihoods, shape (n,)
fit
Fit is a no-op for analytical estimator (already fitted).
This method exists for protocol compliance with LikelihoodEstimatorProtocol. PyDDM solutions are already "fitted" when the Fokker-Planck equation is solved.
Args: simulations: Ignored (not used by analytical estimator)
get_metadata
Return metadata about the estimator.
Returns: Dictionary containing: - max_t: Maximum time in domain - dt: Time step - possible_choices: List of possible choice values - n_choices: Number of choices
sample
Sample (RT, choice) pairs from the analytical distribution.
Uses PyDDM's built-in sampling method for efficient sampling.
Args: n_samples: Number of samples to generate random_state: Random seed for reproducibility. If None, uses non-reproducible random behavior.
Returns: Dictionary with keys: - 'rts': Reaction times, shape (n_samples,) - 'choices': Choices in {-1, 1}, shape (n_samples,)
Raises: RuntimeError: If unable to collect enough decided trials after max_attempts (indicates P(undecided) is too high)
Note: - PyDDM may produce "undecided" trials (process didn't reach boundary within T_dur), which appear as NaN. These are filtered out. - PyDDM's Sample object segregates trials by boundary (all upper, then all lower). We always shuffle to provide randomized samples consistent with the rest of ssm-simulators. - If P(undecided) is high, multiple sampling rounds may be needed to collect enough decided trials.
kde_estimator
KDE-based likelihood estimator.
This module implements likelihood estimation via Kernel Density Estimation (KDE). The estimator builds a KDE from simulated samples and uses it to evaluate likelihoods and generate new samples.
KDELikelihoodEstimator
KDE-based likelihood estimator.
This estimator builds a kernel density estimate from simulated (RT, choice) samples and uses it to estimate the likelihood P(RT, choice | theta).
Attributes:
-
displace_t(bool) –Whether to displace time by the t parameter (non-decision time)
-
_kde(LogKDE | None) –The fitted KDE object (None before fit() is called)
-
_metadata(dict | None) –Metadata from simulations (None before fit() is called)
Examples:
>>> estimator = KDELikelihoodEstimator(displace_t=False)
>>> estimator.fit(simulations)
>>> log_liks = estimator.evaluate(rts, choices)
>>> samples = estimator.sample(n_samples=1000)
Arguments
displace_t : bool, optional Whether to displace time by the t parameter (non-decision time). Only works if all simulations have the same t value. Default is False.
evaluate
Evaluate log-likelihood at given (RT, choice) pairs.
Arguments
rts : np.ndarray Reaction times to evaluate, shape (n_samples,) choices : np.ndarray Choices to evaluate, shape (n_samples,)
Returns:
-
log_likelihoods(ndarray) –Log-likelihood for each (RT, choice) pair, shape (n_samples,)
Raises:
-
ValueError–If fit() has not been called yet
Notes
Extracted from lan_mlp.py lines 312, 342-344
fit
Build KDE from simulation data.
This method constructs a kernel density estimate from the provided simulations. Must be called before evaluate() or sample().
Arguments
simulations : dict Dictionary containing simulation data with keys: - 'rts': np.ndarray of reaction times - 'choices': np.ndarray of choices - 'metadata': dict with model information
Notes
Extracted from lan_mlp.py lines 305-308
get_metadata
Return metadata from the simulations.
Returns:
-
metadata(dict) –Dictionary containing simulation metadata including: - 'max_t': Maximum time value - 'possible_choices': List of possible choice values - Other model-specific metadata
Raises:
-
ValueError–If fit() has not been called yet
sample
Sample (RT, choice) pairs from the KDE.
Arguments
n_samples : int Number of samples to generate random_state : int | None, optional Random seed for reproducibility. If None, uses non-reproducible random behavior.
Returns:
-
samples(dict) –Dictionary with keys: - 'rts': np.ndarray of sampled reaction times, shape (n_samples,) - 'choices': np.ndarray of sampled choices, shape (n_samples,)
Raises:
-
ValueError–If fit() has not been called yet
Notes
Extracted from lan_mlp.py line 311
pyddm_estimator
PyDDM-based likelihood estimator using Fokker-Planck solutions.
PyDDMLikelihoodEstimator
Likelihood estimator using PyDDM's analytical Fokker-Planck solutions.
Unlike KDE estimators which resample from simulations, this estimator uses PyDDM's Fokker-Planck solver to compute analytical PDFs and interpolates them for fast likelihood evaluation.
Key advantages: - No simulation required (purely analytical) - Deterministic (no sampling variability) - Fast evaluation via interpolation - Exact solutions for compatible models
Limitations: - Only works for PyDDM-compatible models (single-particle, two-choice, Gaussian noise)
The estimator extracts PDFs from the solution internally and creates interpolators for fast likelihood evaluation.
Args: pyddm_solution: PyDDM Solution object from model.solve() t_domain: Time domain array from model.t_domain() interpolation: Interpolation method ('linear' or 'cubic')
evaluate
Evaluate log-likelihood at (RT, choice) pairs.
Uses interpolation for fast evaluation. RTs outside the time domain are assigned zero probability (log-likelihood = -inf, clipped to -66).
Args: rts: Reaction times, shape (n,) choices: Choices in {-1, 1}, shape (n,)
Returns: Log-likelihoods, shape (n,)
fit
Fit is a no-op for analytical estimator (already fitted).
This method exists for protocol compliance with LikelihoodEstimatorProtocol. PyDDM solutions are already "fitted" when the Fokker-Planck equation is solved.
Args: simulations: Ignored (not used by analytical estimator)
get_metadata
Return metadata about the estimator.
Returns: Dictionary containing: - max_t: Maximum time in domain - dt: Time step - possible_choices: List of possible choice values - n_choices: Number of choices
sample
Sample (RT, choice) pairs from the analytical distribution.
Uses PyDDM's built-in sampling method for efficient sampling.
Args: n_samples: Number of samples to generate random_state: Random seed for reproducibility. If None, uses non-reproducible random behavior.
Returns: Dictionary with keys: - 'rts': Reaction times, shape (n_samples,) - 'choices': Choices in {-1, 1}, shape (n_samples,)
Raises: RuntimeError: If unable to collect enough decided trials after max_attempts (indicates P(undecided) is too high)
Note: - PyDDM may produce "undecided" trials (process didn't reach boundary within T_dur), which appear as NaN. These are filtered out. - PyDDM's Sample object segregates trials by boundary (all upper, then all lower). We always shuffle to provide randomized samples consistent with the rest of ssm-simulators. - If P(undecided) is high, multiple sampling rounds may be needed to collect enough decided trials.
ssms.dataset_generators.parameter_samplers
Parameter sampling infrastructure for training data generation.
ParameterSamplerProtocol
Bases: Protocol
Protocol for parameter sampling strategies.
This protocol defines the interface that all parameter samplers must implement. Samplers are responsible for generating parameter sets from a parameter space, potentially with dependencies between parameters and transformations applied.
get_param_space
Get the parameter space bounds.
Returns: Dictionary mapping parameter names to (lower, upper) bound tuples
ParameterSamplingConstraintProtocol
Bases: Protocol
Protocol for parameter sampling constraints.
Constraints are applied after sampling to enforce relationships or modify parameter values (e.g., ensuring a > z, normalizing drift rates to sum to 1). Constraints can trigger resampling if validation fails.
UniformParameterSampler
Bases: AbstractParameterSampler
Uniform random sampling of parameters.
This sampler generates parameter values uniformly distributed between lower and upper bounds. It matches the current behavior of the sample_parameters_from_constraints() function.
Example: >>> param_space = {"v": (-1.0, 1.0), "a": (0.5, 2.0)} >>> sampler = UniformParameterSampler(param_space) >>> samples = sampler.sample(n_samples=100) >>> samples["v"].shape (100,)
base_sampler
Base class for parameter samplers with dependency resolution.
AbstractParameterSampler
Bases: ABC
Base class for parameter samplers with dependency resolution.
This class handles: - Building dependency graphs from parameter bounds - Topological sorting to determine sampling order - Applying transforms after sampling - Validating parameter spaces
Subclasses must implement _sample_parameter() to define the specific sampling strategy (uniform, Sobol, Latin Hypercube, etc.).
Args: param_space: Dictionary mapping parameter names to (lower, upper) bounds. Bounds can be numeric or strings (for dependencies). constraints: List of constraint objects (must have apply() method). Applied after sampling in the order provided.
get_param_space
Get the parameter space bounds.
Returns: Dictionary mapping parameter names to (lower, upper) bound tuples
sample
Sample parameters respecting dependencies and applying transforms.
Args: n_samples: Number of parameter sets to sample rng: Random number generator. If None, uses np.random.default_rng()
Returns: Dictionary mapping parameter names to sampled arrays
Raises: ValueError: If parameter dependencies cannot be resolved
constraints
Parameter sampling constraint classes.
NOTE: This module re-exports from ssms.transforms for backwards compatibility. Import directly from ssms.transforms instead:
from ssms.transforms import SwapIfLessConstraint, NormalizeToSumConstraint
NormalizeToSumConstraint
Bases: ParameterTransform
Normalize a set of parameters to sum to 1.
This constraint is commonly used for drift rates in multi-accumulator models (e.g., RLWM models) where the drift rates must sum to 1.
The normalization includes a small epsilon (1e-20) to avoid division by zero and ensure numerical stability.
Parameters:
-
param_names(list[str]) –List of parameter names to normalize together
Examples:
>>> constraint = NormalizeToSumConstraint(["v1", "v2", "v3"])
>>> theta = {"v1": 0.2, "v2": 0.3, "v3": 0.5}
>>> result = constraint.apply(theta)
>>> sum([result["v1"], result["v2"], result["v3"]])
1.0
Use in model config:
>>> model_config = {
... "name": "dev_rlwm_lba_race_v1",
... "parameter_transforms": {
... "sampling": [
... NormalizeToSumConstraint(["vRL0", "vRL1", "vRL2"]),
... NormalizeToSumConstraint(["vWM0", "vWM1", "vWM2"]),
... ],
... }
... }
Parameters:
-
param_names(list[str]) –List of parameter names to normalize together
apply
Normalize specified parameters to sum to 1.
Parameters:
-
theta(dict[str, Any]) –Dictionary of parameter values (can be scalars or arrays)
-
model_config(dict[str, Any] or None, default:None) –Not used by this transform (included for interface compatibility)
-
n_trials(int or None, default:None) –Not used by this transform (included for interface compatibility)
-
epsilon(float, default:1e-20) –Small value to add to the total to avoid division by zero. Default is 1e-20.
Returns:
-
dict[str, Any]–Modified theta dictionary with normalized values
SwapIfLessConstraint
Bases: ParameterTransform
Swap two parameters if first is less than or equal to second.
This constraint ensures ordering relationships like a > z by swapping the values when the constraint is violated. Works with both scalar and array inputs.
Parameters:
-
param_a(str) –First parameter name (should be > param_b after constraint)
-
param_b(str) –Second parameter name (should be < param_a after constraint)
Examples:
>>> constraint = SwapIfLessConstraint("a", "z")
>>> theta = {"a": np.array([0.5, 1.5]), "z": np.array([1.0, 0.5])}
>>> result = constraint.apply(theta)
>>> # First element: a=0.5 <= z=1.0 → swap → a=1.0, z=0.5
>>> # Second element: a=1.5 > z=0.5 → no swap → a=1.5, z=0.5
Use in model config:
>>> model_config = {
... "name": "lba_angle_3",
... "parameter_transforms": {
... "sampling": [SwapIfLessConstraint("a", "z")],
... }
... }
Parameters:
-
param_a(str) –First parameter name (should be > param_b after constraint)
-
param_b(str) –Second parameter name (should be < param_a after constraint)
apply
Swap param_a and param_b where param_a <= param_b.
Parameters:
-
theta(dict[str, Any]) –Dictionary of parameter values (can be scalars or arrays)
-
model_config(dict[str, Any] or None, default:None) –Not used by this transform (included for interface compatibility)
-
n_trials(int or None, default:None) –Not used by this transform (included for interface compatibility)
Returns:
-
dict[str, Any]–Modified theta dictionary with swapped values where needed
protocols
Protocols for parameter sampling and constraints.
ParameterSamplerProtocol
Bases: Protocol
Protocol for parameter sampling strategies.
This protocol defines the interface that all parameter samplers must implement. Samplers are responsible for generating parameter sets from a parameter space, potentially with dependencies between parameters and transformations applied.
get_param_space
Get the parameter space bounds.
Returns: Dictionary mapping parameter names to (lower, upper) bound tuples
ParameterSamplingConstraintProtocol
Bases: Protocol
Protocol for parameter sampling constraints.
Constraints are applied after sampling to enforce relationships or modify parameter values (e.g., ensuring a > z, normalizing drift rates to sum to 1). Constraints can trigger resampling if validation fails.
uniform_sampler
Uniform random parameter sampler (default behavior).
UniformParameterSampler
Bases: AbstractParameterSampler
Uniform random sampling of parameters.
This sampler generates parameter values uniformly distributed between lower and upper bounds. It matches the current behavior of the sample_parameters_from_constraints() function.
Example: >>> param_space = {"v": (-1.0, 1.0), "a": (0.5, 2.0)} >>> sampler = UniformParameterSampler(param_space) >>> samples = sampler.sample(n_samples=100) >>> samples["v"].shape (100,)
ssms.dataset_generators.pipelines
Data generation pipelines for orchestrating end-to-end workflows.
PyDDMPipeline
Generate training data via PyDDM analytical PDF workflow.
This strategy implements an analytical workflow: 1. Sample parameters from parameter space 2. SKIP simulation (use analytical Fokker-Planck solution) 3. Build PyDDM estimator (solves PDE) 4. Compute auxiliary labels analytically 5. Generate training data from analytical PDF
Used for: PyDDM-based likelihood estimation
Benefits: - Much faster (no simulation overhead) - No filtering needed (analytical solution always valid) - Deterministic for given parameters - Memory efficient (no large simulation arrays) - Computes choice probabilities, omission_p, and nogo_p analytically
Limitations: - Only works for compatible models (single-particle, two-choice, Gaussian noise) - Cannot generate binned RT histograms (these require trajectory simulations)
Args: generator_config: Configuration for data generation model_config: Model specification (must contain 'param_bounds_dict') estimator_builder: Builder for PyDDM estimator (class or instance) - If a class is passed, it will be instantiated with generator_config - If an instance is passed, it will be used as-is training_strategy: Strategy for generating training samples (class or instance) - If a class is passed, it will be instantiated with generator_config and model_config - If an instance is passed, it will be used as-is
generate_for_parameter_set
Generate training data for one parameter set (analytical workflow).
Workflow: 1. Sample theta from parameter space 2. Build analytical estimator (no simulations needed) 3. Compute auxiliary labels analytically 4. Generate training data
Args: parameter_sampling_seed: Index for parameter sampling (used as seed) random_seed: Random seed (accepted for API compatibility, may not be used as analytical solutions are deterministic)
Returns: Dictionary with keys: - 'data': Training data dictionary (or None if generation failed) - 'theta': Parameter values used - 'success': Whether generation succeeded - 'error': Error message if success=False (optional)
Note: PyDDM can compute choice probabilities, omission_p, and nogo_p analytically without simulations. Only binned RT histograms require trajectory data and are set to None.
SimulationPipeline
Generate training data via simulation + KDE workflow.
This pipeline implements the traditional workflow: 1. Sample parameters from parameter space 2. Run Cython simulator to generate samples 3. Filter simulations for quality (RT variance, choice proportions, etc.) 4. Build KDE estimator from simulations 5. Generate training data from KDE
Used for: KDE-based likelihood estimation
This pipeline is necessary when analytical solutions are not available or when you want to validate analytical methods against simulations.
Args: generator_config: Configuration for data generation model_config: Model specification (must contain 'param_bounds_dict') estimator_builder: Builder for KDE estimator (class or instance) - If a class is passed, it will be instantiated with generator_config - If an instance is passed, it will be used as-is training_strategy: Strategy for generating training samples (class or instance) - If a class is passed, it will be instantiated with generator_config and model_config - If an instance is passed, it will be used as-is
generate_for_parameter_set
Generate training data for one parameter set (simulation workflow).
Workflow: 1. Sample theta from parameter space 2. Run simulations 3. Filter simulations 4. Build estimator 5. Generate training data
Args: parameter_sampling_seed: Seed for parameter sampling (ensures different workers sample different θ) simulator_seed: Random seed for simulations (controls RT/choice variability)
Returns: Dictionary with keys: - 'data': Training data dictionary (or None if generation failed) - 'theta': Parameter values used - 'success': Whether generation succeeded
create_data_generation_pipeline
Create appropriate data generation pipeline based on configuration.
This factory selects the right pipeline based on estimator_type in generator_config: - 'kde': SimulationPipeline (runs simulations + KDE) - 'pyddm': PyDDMPipeline (analytical Fokker-Planck solution)
The factory internally creates all required components (estimator builder, training strategy, parameter sampler) from the provided configurations. The model_config serves as the single source of truth for model specifications, parameter bounds, and transformations.
Args: generator_config: Configuration dict with 'estimator.type' key model_config: Model specification (must contain 'param_bounds_dict')
Returns: Data generation pipeline instance
Raises: ValueError: If estimator_type is unknown
Note: The same model_config can be used for both simulation-based (KDE) and analytical (PyDDM) pipelines. Custom boundaries and drift functions should be configured through the model_config or using ModelConfigBuilder.
Example: >>> pipeline = create_data_generation_pipeline( ... generator_config=config, ... model_config=model_config, ... ) >>> # Pipeline is ready to use with all components created internally
pipeline_factory
Factory for creating data generation pipelines.
create_data_generation_pipeline
Create appropriate data generation pipeline based on configuration.
This factory selects the right pipeline based on estimator_type in generator_config: - 'kde': SimulationPipeline (runs simulations + KDE) - 'pyddm': PyDDMPipeline (analytical Fokker-Planck solution)
The factory internally creates all required components (estimator builder, training strategy, parameter sampler) from the provided configurations. The model_config serves as the single source of truth for model specifications, parameter bounds, and transformations.
Args: generator_config: Configuration dict with 'estimator.type' key model_config: Model specification (must contain 'param_bounds_dict')
Returns: Data generation pipeline instance
Raises: ValueError: If estimator_type is unknown
Note: The same model_config can be used for both simulation-based (KDE) and analytical (PyDDM) pipelines. Custom boundaries and drift functions should be configured through the model_config or using ModelConfigBuilder.
Example: >>> pipeline = create_data_generation_pipeline( ... generator_config=config, ... model_config=model_config, ... ) >>> # Pipeline is ready to use with all components created internally
pyddm_pipeline
PyDDM-based data generation pipeline using analytical solutions.
PyDDMPipeline
Generate training data via PyDDM analytical PDF workflow.
This strategy implements an analytical workflow: 1. Sample parameters from parameter space 2. SKIP simulation (use analytical Fokker-Planck solution) 3. Build PyDDM estimator (solves PDE) 4. Compute auxiliary labels analytically 5. Generate training data from analytical PDF
Used for: PyDDM-based likelihood estimation
Benefits: - Much faster (no simulation overhead) - No filtering needed (analytical solution always valid) - Deterministic for given parameters - Memory efficient (no large simulation arrays) - Computes choice probabilities, omission_p, and nogo_p analytically
Limitations: - Only works for compatible models (single-particle, two-choice, Gaussian noise) - Cannot generate binned RT histograms (these require trajectory simulations)
Args: generator_config: Configuration for data generation model_config: Model specification (must contain 'param_bounds_dict') estimator_builder: Builder for PyDDM estimator (class or instance) - If a class is passed, it will be instantiated with generator_config - If an instance is passed, it will be used as-is training_strategy: Strategy for generating training samples (class or instance) - If a class is passed, it will be instantiated with generator_config and model_config - If an instance is passed, it will be used as-is
generate_for_parameter_set
Generate training data for one parameter set (analytical workflow).
Workflow: 1. Sample theta from parameter space 2. Build analytical estimator (no simulations needed) 3. Compute auxiliary labels analytically 4. Generate training data
Args: parameter_sampling_seed: Index for parameter sampling (used as seed) random_seed: Random seed (accepted for API compatibility, may not be used as analytical solutions are deterministic)
Returns: Dictionary with keys: - 'data': Training data dictionary (or None if generation failed) - 'theta': Parameter values used - 'success': Whether generation succeeded - 'error': Error message if success=False (optional)
Note: PyDDM can compute choice probabilities, omission_p, and nogo_p analytically without simulations. Only binned RT histograms require trajectory data and are set to None.
simulation_pipeline
Simulation-based data generation pipeline for KDE estimators.
SimulationPipeline
Generate training data via simulation + KDE workflow.
This pipeline implements the traditional workflow: 1. Sample parameters from parameter space 2. Run Cython simulator to generate samples 3. Filter simulations for quality (RT variance, choice proportions, etc.) 4. Build KDE estimator from simulations 5. Generate training data from KDE
Used for: KDE-based likelihood estimation
This pipeline is necessary when analytical solutions are not available or when you want to validate analytical methods against simulations.
Args: generator_config: Configuration for data generation model_config: Model specification (must contain 'param_bounds_dict') estimator_builder: Builder for KDE estimator (class or instance) - If a class is passed, it will be instantiated with generator_config - If an instance is passed, it will be used as-is training_strategy: Strategy for generating training samples (class or instance) - If a class is passed, it will be instantiated with generator_config and model_config - If an instance is passed, it will be used as-is
generate_for_parameter_set
Generate training data for one parameter set (simulation workflow).
Workflow: 1. Sample theta from parameter space 2. Run simulations 3. Filter simulations 4. Build estimator 5. Generate training data
Args: parameter_sampling_seed: Seed for parameter sampling (ensures different workers sample different θ) simulator_seed: Random seed for simulations (controls RT/choice variability)
Returns: Dictionary with keys: - 'data': Training data dictionary (or None if generation failed) - 'theta': Parameter values used - 'success': Whether generation succeeded
ssms.dataset_generators.protocols
Protocols for data generation components.
This module defines the interfaces (protocols) for: - Likelihood estimators: Objects that estimate P(RT, choice | theta) - Estimator builders: Objects that create and configure likelihood estimators - Training data strategies: Objects that generate training samples from estimators - Data generation strategies: Objects that orchestrate the end-to-end workflow - Parameter samplers: Objects that sample parameters from parameter spaces
Using protocols allows for dependency injection and clean separation of concerns.
DataGenerationPipelineProtocol
Bases: Protocol
Protocol for end-to-end data generation workflows.
Data generation pipelines orchestrate the complete process from parameter sampling to training data generation. Different pipelines handle different workflows: - Simulation-based: Run simulations, filter, build KDE, generate data - Analytical (PyDDM): Skip simulations, solve Fokker-Planck, generate data - Hybrid: Mix simulation and analytical approaches - Other: Custom workflows
This protocol enables clean separation between simulation-dependent logic (SimulationPipeline) and analytical approaches (PyDDMPipeline), eliminating wasteful computation.
Attributes:
-
generator_config(dict) –Configuration for data generation (samples, bins, etc.)
-
model_config(dict) –Model specification (parameters, bounds, transforms, etc.)
generate_for_parameter_set
Generate training data for one parameter set.
Arguments
parameter_sampling_seed : int Index of parameter set to generate (used to sample from param space) random_seed : int | None Random seed for reproducibility (may be unused for deterministic methods)
Returns:
-
result(dict) –Dictionary with keys: - 'data': np.ndarray of training data (or None if generation failed) - 'theta': dict of parameter values used - 'success': bool indicating whether generation succeeded - 'error': str (optional) error message if success=False
EstimatorBuilderProtocol
Bases: Protocol
Protocol for building likelihood estimators.
Builders encapsulate all the logic for creating and configuring likelihood estimators. This keeps the TrainingDataGenerator class generic and free of type-specific logic.
build
Build and return a fitted likelihood estimator for given theta.
Arguments
theta : dict Model parameters (e.g., {'v': 1.0, 'a': 2.0, 'z': 0.5, 't': 0.3}) simulations : dict | None Simulation data (required for KDE, may be None for analytical estimators)
Returns:
-
estimator(LikelihoodEstimatorProtocol) –A fitted likelihood estimator ready for use
Raises:
-
ValueError–If required data (e.g., simulations for KDE) is missing
LikelihoodEstimatorProtocol
Bases: Protocol
Protocol for likelihood estimation.
Likelihood estimators compute P(RT, choice | theta) and can sample from this distribution. They may use different methods: - KDE: Build kernel density estimate from simulated samples - Analytical: Use closed-form PDF (e.g., from PyDDM solver) - Other: Custom methods
evaluate
Evaluate log-likelihood at given (RT, choice) pairs.
Arguments
rts : np.ndarray Reaction times to evaluate, shape (n_samples,) choices : np.ndarray Choices to evaluate, shape (n_samples,)
Returns:
-
log_likelihoods(ndarray) –Log-likelihood for each (RT, choice) pair, shape (n_samples,)
fit
Fit estimator to simulation data.
For KDE: Builds the kernel density estimate. For analytical: May be a no-op (PDF already available).
Arguments
simulations : dict Dictionary containing simulation data with keys: - 'rts': np.ndarray of reaction times - 'choices': np.ndarray of choices - 'metadata': dict with model info
get_metadata
Return metadata about the estimator.
Returns:
-
metadata(dict) –Dictionary containing: - 'max_t': Maximum time value - 'possible_choices': List of possible choice values - Other model-specific metadata
sample
Sample (RT, choice) pairs from the estimated likelihood.
Arguments
n_samples : int Number of samples to generate random_state : int | None, optional Random seed for reproducibility. If None, uses non-reproducible random behavior.
Returns:
-
samples(dict) –Dictionary with keys: - 'rts': np.ndarray of sampled reaction times - 'choices': np.ndarray of sampled choices
ParameterSamplerProtocol
Bases: Protocol
Protocol for parameter sampling strategies.
Parameter samplers generate parameter sets from a parameter space, handling dependencies between parameters and applying transforms.
get_param_space
Get the parameter space bounds.
Returns: Dictionary mapping parameter names to (lower, upper) bound tuples
TrainingDataStrategyProtocol
Bases: Protocol
Protocol for training data generation strategies.
Strategies define how to generate training samples from a likelihood estimator. Different strategies might: - Resample from estimator + add uniform samples (current approach) - Evaluate on a uniform grid - Use importance sampling - Other methods
generate
Generate training data array.
Arguments
theta : dict Model parameters likelihood_estimator : LikelihoodEstimatorProtocol Fitted likelihood estimator random_state : int | None, optional Random seed for reproducibility. If None, uses non-reproducible random behavior. Controls all random operations including sampling and row shuffling.
Returns:
-
training_data(ndarray) –Array of shape (n_samples, n_params + 3) containing: - Columns 0:n_params: Parameter values (tiled for all samples) - Column -3: Reaction times - Column -2: Choices - Column -1: Log-likelihoods
Note: Rows are shuffled to avoid ordering bias in training batches.
ssms.dataset_generators.strategies
Training data generation strategies.
This module contains strategy classes for training data generation:
-
ResampleMixtureStrategy: Generates training data by mixing samples from a likelihood estimator (KDE or PyDDM) with uniform samples in positive and negative RT space. This helps networks learn both the likelihood surface and its boundaries.
-
MixtureTrainingStrategy: Alias for ResampleMixtureStrategy (for backward compatibility).
Note: For end-to-end data generation workflows, see the pipelines module which
contains SimulationPipeline and PyDDMPipeline.
ResampleMixtureStrategy
Training data strategy using mixture of resamples and uniform draws.
This strategy generates training data by: 1. Resampling (RT, choice) pairs from the fitted likelihood estimator 2. Generating uniform samples in positive RT space [0, max_t] 3. Generating uniform samples in negative RT space [-1, 0]
For each sample, the strategy evaluates the log-likelihood and combines: - Parameters (theta) - RT and choice - Log-likelihood at (RT, choice)
Attributes:
-
generator_config(dict) –Configuration for data generation (sample counts, mixture probabilities, etc.)
-
model_config(dict) –Model configuration (params, nchoices, etc.)
Examples:
>>> strategy = ResampleMixtureStrategy(generator_config, model_config)
>>> training_data = strategy.generate(theta, likelihood_estimator)
>>> assert training_data.shape == (n_training_samples, n_features)
Arguments
generator_config : dict Configuration dictionary containing: - ['training']['n_samples_per_param']: Total samples to generate - ['training']['mixture_probabilities']: [p_estimator, p_unif_up, p_unif_down] - ['training']['separate_response_channels']: Whether to one-hot encode choices - ['training']['negative_rt_log_likelihood']: Log-likelihood value for negative RTs model_config : dict Model configuration containing: - 'params': List of parameter names - 'nchoices': Number of possible choices
generate
Generate training data using mixture strategy.
Arguments
theta : dict Parameter dictionary (e.g., {'v': 1.0, 'a': 2.0, ...}) likelihood_estimator : LikelihoodEstimatorProtocol Fitted likelihood estimator (must support sample() and evaluate()) random_state : int | None, optional Random seed for reproducibility. If None, uses non-reproducible random behavior. Controls all random operations including sampling from estimator and shuffling output.
Returns:
-
ndarray–Training data array of shape (n_samples, n_features) where: - First columns: theta parameters - Middle columns: RT and choice (possibly one-hot encoded) - Last column: log-likelihood
Note: Rows are shuffled to avoid ordering bias in training batches.
Raises:
-
ValueError–If mixture probabilities don't lead to valid sample counts
Notes
Extracted from lan_mlp.py lines 268-360
resample_mixture_strategy
Mixture training data generation strategy.
This strategy generates training data by mixing three types of samples: 1. Samples drawn from the likelihood estimator (KDE or analytical PDF) 2. Uniform samples in positive RT space (to encourage exploration) 3. Uniform samples in negative RT space (to learn the hard boundary at t=0)
This approach helps the network learn both the likelihood surface and its boundaries.
Note: MixtureTrainingStrategy is provided as an alias for backward compatibility.
ResampleMixtureStrategy
Training data strategy using mixture of resamples and uniform draws.
This strategy generates training data by: 1. Resampling (RT, choice) pairs from the fitted likelihood estimator 2. Generating uniform samples in positive RT space [0, max_t] 3. Generating uniform samples in negative RT space [-1, 0]
For each sample, the strategy evaluates the log-likelihood and combines: - Parameters (theta) - RT and choice - Log-likelihood at (RT, choice)
Attributes:
-
generator_config(dict) –Configuration for data generation (sample counts, mixture probabilities, etc.)
-
model_config(dict) –Model configuration (params, nchoices, etc.)
Examples:
>>> strategy = ResampleMixtureStrategy(generator_config, model_config)
>>> training_data = strategy.generate(theta, likelihood_estimator)
>>> assert training_data.shape == (n_training_samples, n_features)
Arguments
generator_config : dict Configuration dictionary containing: - ['training']['n_samples_per_param']: Total samples to generate - ['training']['mixture_probabilities']: [p_estimator, p_unif_up, p_unif_down] - ['training']['separate_response_channels']: Whether to one-hot encode choices - ['training']['negative_rt_log_likelihood']: Log-likelihood value for negative RTs model_config : dict Model configuration containing: - 'params': List of parameter names - 'nchoices': Number of possible choices
generate
Generate training data using mixture strategy.
Arguments
theta : dict Parameter dictionary (e.g., {'v': 1.0, 'a': 2.0, ...}) likelihood_estimator : LikelihoodEstimatorProtocol Fitted likelihood estimator (must support sample() and evaluate()) random_state : int | None, optional Random seed for reproducibility. If None, uses non-reproducible random behavior. Controls all random operations including sampling from estimator and shuffling output.
Returns:
-
ndarray–Training data array of shape (n_samples, n_features) where: - First columns: theta parameters - Middle columns: RT and choice (possibly one-hot encoded) - Last column: log-likelihood
Note: Rows are shuffled to avoid ordering bias in training batches.
Raises:
-
ValueError–If mixture probabilities don't lead to valid sample counts
Notes
Extracted from lan_mlp.py lines 268-360