mixle.models.neural_leaf module

A neural network as a mixle conditional-density leaf – the bridge that makes nets generative components.

NeuralGaussian(module) wraps a Torch module as a mixle distribution p(y | x) = N(y; module(x), noise^2 I) over observations (x, y). It implements the full SequenceEncodableProbabilityDistribution contract, so it drops into MixtureDistribution / CompositeDistribution / HMM emissions like any leaf – but its EM M-step is weighted-NLL gradient descent on the module (warm-started across EM iterations => generalized EM).

A MixtureDistribution of NeuralGaussian components is therefore a mixture of neural experts: the E-step computes responsibilities, the M-step trains each expert by responsibility-weighted regression. Combined with the em move in mixle.experimental.program, the same model fits with EM where conjugate and gradient where neural:

from mixle.stats import MixtureEstimator
experts = MixtureEstimator([NeuralGaussian(mlp_a).estimator(), NeuralGaussian(mlp_b).estimator()])
# ... run EM (estimate loop) -> each expert specializes, gated by the responsibilities.

Requires torch (the module). The leaf is conditional: sampler().sample_given(x) draws y; sample() raises (there is no p(x)).

class NeuralGaussian(module, noise=1.0, m_steps=40, lr=0.01, name=None, device=None)[source]

Bases: SequenceEncodableProbabilityDistribution

p(y | x) = N(y; module(x), noise^2 I) as a mixle leaf. Observation is the pair (x, y).

Parameters:
  • module (Any)

  • noise (float)

  • m_steps (int)

  • lr (float)

  • name (str | None)

  • device (Any)

log_density(xy)[source]

Return the log-density or log-mass at a single observation.

Parameters:

xy (Any)

Return type:

float

seq_log_density(enc)[source]

Return vectorized log-density values for sequence-encoded observations.

Parameters:

enc (Any)

Return type:

ndarray

classmethod compute_capabilities()[source]
backend_seq_log_density(enc, engine)[source]

Engine-neutral vectorized log-density for encoded (x, y) pairs.

Parameters:
Return type:

Any

sampler(seed=None)[source]

Return a sampler for drawing observations from this distribution.

Parameters:

seed (int | None)

Return type:

NeuralGaussianSampler

estimator(pseudo_count=None)[source]

Return an estimator for fitting this distribution from data.

Parameters:

pseudo_count (float | None)

Return type:

NeuralGaussianEstimator

dist_to_encoder()[source]

Return the data encoder used by this distribution for vectorized methods.

Return type:

NeuralGaussianEncoder

to_dict()[source]

Return a safe JSON-compatible representation of this distribution.

Return type:

dict[str, Any]

classmethod from_dict(payload)[source]

Reconstruct a distribution from to_dict output.

Parameters:

payload (dict[str, Any])

Return type:

NeuralGaussian

class NeuralGaussianSampler(dist, seed=None)[source]

Bases: DistributionSampler

Parameters:
  • dist (NeuralGaussian)

  • seed (int | None)

sample(size=None, *, batched=True)[source]

Draw observations.

Combinator samplers (mixture/sequence/…) accept batched. With batched=True (the default) each child stream is drawn in one vectorized call instead of a per-draw Python loop – far faster. Because every child sampler owns an independent RandomState, batching consumes each stream in the same order as the loop, so the draws are identical to the legacy path. batched=False forces that legacy per-draw loop as a guaranteed- stable reference. Leaf samplers are already vectorized and ignore the flag.

Parameters:
Return type:

Any

sample_given(x)[source]
Parameters:

x (Any)

Return type:

ndarray

class NeuralGaussianEncoder[source]

Bases: DataSequenceEncoder

seq_encode(data)[source]

Encode the iid observation sequence x for vectorized evaluation.

Parameters:

data (list)

Return type:

tuple[ndarray, ndarray]

class NeuralGaussianAccumulator[source]

Bases: SequenceEncodableStatisticAccumulator

update(xy, weight, estimate)[source]
Parameters:
Return type:

None

seq_update(enc, weights, estimate)[source]
Parameters:
Return type:

None

initialize(xy, weight, rng)[source]
Parameters:
Return type:

None

seq_initialize(enc, weights, rng)[source]
Parameters:
Return type:

None

combine(other)[source]
Parameters:

other (Any)

Return type:

NeuralGaussianAccumulator

value()[source]
Return type:

tuple

from_value(value)[source]
Parameters:

value (tuple)

Return type:

NeuralGaussianAccumulator

acc_to_encoder()[source]
Return type:

NeuralGaussianEncoder

class NeuralGaussianAccumulatorFactory[source]

Bases: StatisticAccumulatorFactory

make()[source]
Return type:

NeuralGaussianAccumulator

class NeuralGaussianEstimator(module, noise=1.0, m_steps=40, lr=0.01, name=None, device=None)[source]

Bases: ParameterEstimator

EM estimator for a NeuralGaussian: the M-step is m_steps of weighted-NLL gradient on the module.

The module is held (and warm-started) across EM iterations, so each M-step is a partial maximization (generalized EM). The accumulator buffers responsibility-weighted (x, y) observations.

Parameters:
  • module (Any)

  • noise (float)

  • m_steps (int)

  • lr (float)

  • name (str | None)

  • device (Any)

accumulator_factory()[source]
Return type:

NeuralGaussianAccumulatorFactory

estimate(nobs, suff_stat)[source]
Parameters:
Return type:

NeuralGaussian

NeuralLeaf

alias of NeuralGaussian

NeuralLeafEstimator

alias of NeuralGaussianEstimator