mixle.models.mixture_density module¶
NeuralConditionalDensity – the adapter that turns ANY torch conditional density into a mixle leaf.
This is the conditional sibling of NeuralDensity. Where that one wraps a
module exposing log_density(x) -> (n,) (an unconditional p(x)), this wraps a module exposing
log_density(x, y) -> (n,) (and sample_given(x) -> (n, d)) and gives you a full five-piece mixle
Distribution over the pair (x, y) – so a flexible conditional density drops into a mixture of experts,
a composite field, or an HMM emission and is fit jointly with classical families by the same
responsibility-weighted-NLL EM M-step (warm-started across iterations, i.e. generalized EM).
Why it matters: NeuralGaussian fixes the conditional law to a single Gaussian,
p(y | x) = N(y; f(x), sigma^2 I) – one mean per x, unimodal and homoscedastic. Many real conditionals
are neither: an inverse problem has several valid y for one x; measurement noise grows with x.
build_mdn() is the ready instance – a mixture density network, p(y | x) = sum_k pi_k(x) N(y; mu_k(x),
sigma_k(x)^2) – whose entire mixture (weights, means, variances) is a function of x, so it is multimodal
and heteroscedastic. Any other conditional density (a conditional flow, an autoregressive head) plugs in the same
way: give it log_density(x, y) and sample_given(x).
- class NeuralConditionalDensity(module, *, m_steps=60, lr=5e-3, device='cpu', name=None)[source]
Bases:
SequenceEncodableProbabilityDistributionWrap a torch conditional-density
module(module.log_density(x, y) -> (n,)) as a mixle leaf.Observations are pairs
(x, y). The module must also exposesample_given(x) -> (n, d)to drawy.- log_density(xy)[source]
Return the log-density or log-mass at a single observation.
- seq_log_density(enc)[source]
Return vectorized log-density values for sequence-encoded observations.
- sampler(seed=None)[source]
Return a sampler for drawing observations from this distribution.
- Parameters:
seed (int | None)
- Return type:
NeuralConditionalDensitySampler
- estimator(pseudo_count=None)[source]
Return an estimator for fitting this distribution from data.
- Parameters:
pseudo_count (float | None)
- Return type:
NeuralConditionalDensityEstimator
- dist_to_encoder()[source]
Return the data encoder used by this distribution for vectorized methods.
- Return type:
NeuralConditionalDensityEncoder
- to_dict()[source]
Return a safe JSON-compatible representation of this distribution.
- class NeuralConditionalDensitySampler(dist, seed=None)[source]
Bases:
DistributionSampler- Parameters:
dist (NeuralConditionalDensity)
seed (int | None)
- sample(size=None, *, batched=True)[source]
Draw observations.
Combinator samplers (mixture/sequence/…) accept
batched. Withbatched=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 independentRandomState, batching consumes each stream in the same order as the loop, so the draws are identical to the legacy path.batched=Falseforces that legacy per-draw loop as a guaranteed- stable reference. Leaf samplers are already vectorized and ignore the flag.
- class NeuralConditionalDensityEncoder[source]
Bases:
DataSequenceEncoder
- class NeuralConditionalDensityAccumulator[source]
Bases:
SequenceEncodableStatisticAccumulatorBuffers responsibility-weighted
(x, y)pairs for the M-step (the weights are the E-step soft counts).- update(xy, weight, estimate)[source]
- seq_update(enc, weights, estimate)[source]
- seq_initialize(enc, weights, rng)[source]
- from_value(value)[source]
- Parameters:
value (tuple)
- Return type:
NeuralConditionalDensityAccumulator
- acc_to_encoder()[source]
- Return type:
NeuralConditionalDensityEncoder
- class NeuralConditionalDensityAccumulatorFactory[source]
Bases:
StatisticAccumulatorFactory- make()[source]
- Return type:
NeuralConditionalDensityAccumulator
- class NeuralConditionalDensityEstimator(module, *, m_steps=60, lr=5e-3, device='cpu', name=None)[source]
Bases:
ParameterEstimatorM-step: responsibility-weighted MLE
max sum_i w_i log p(y_i | x_i)by gradient ascent (warm-started).- accumulator_factory()[source]
- Return type:
NeuralConditionalDensityAccumulatorFactory
- build_mdn(x_dim, y_dim, *, k=5, hidden=32, layers=2)[source]
A mixture density network:
p(y | x) = sum_k pi_k(x) N(y; mu_k(x), diag sigma_k(x)^2)– ready to wrap.A shared MLP body maps
xto three heads – mixing logits, component means, and (log) component scales – so the entire conditional law is a function ofx: multimodal (severalmu_k) and heteroscedastic (input-dependentsigma_k). Exposeslog_density(x, y)(a log-sum-exp over components) andsample_given(x)(pick a component bypi, then a Gaussian), the contract aNeuralConditionalDensityadapts.
- build_conditional_flow(x_dim, y_dim, *, hidden=32, layers=4)[source]
A conditional coupling flow: an exact
p(y | x)whose transform ofyis conditioned onx.The exact-density counterpart to
build_mdn(). Each affine-coupling layer’s shift/scale networks take both the passed-throughycoordinates andx, so the whole invertibley-transform bends with the input – capturing within-``y`` dependence (e.g.y2a nonlinear function ofy1) that a single-GaussianNeuralGaussian(isotropic mean-only) cannot, while keeping an exact log-density (so it composes honestly, unlike a bound). Needsy_dim >= 2for the coupling to be non-trivial. Exposeslog_density(x, y)andsample_given(x)– the contract aNeuralConditionalDensityadapts.
- build_conditional_autoregressive_categorical(x_dim, y_dim, n_categories, *, hidden=64)[source]
An autoregressive categorical conditioned on
x: exactp(y | x)over discretey in {0..C-1}^y_dim.The conditional sibling of
build_autoregressive_categorical()and the discrete counterpart tobuild_conditional_flow(). It factorizesp(y | x) = prod_i p(y_i | y_{<i}, x)with a MADE-masked net overyinto whichxis injected unmasked (degree 0, so every coordinate may depend onx). Each per-coordinate softmax is exactly a conditional, so the density is exactly normalized and composes honestly. Exposeslog_density(x, y)andsample_given(x)– the contract aNeuralConditionalDensityadapts.