mixle.stats.combinator.hurdle module¶
Hurdle count models: a two-part model that decouples whether a count is zero from how big it is.
A hurdle model splits the count into a binary “hurdle” and a zero-truncated count part:
P(X = 0) = pi, P(X = k) = (1 - pi) * P_base(k) / (1 - P_base(0)) for k > 0.
With probability pi the observation fails to cross the hurdle and is zero; otherwise it is a
positive count drawn from base conditioned on being > 0 (the base zero is truncated away and
the remaining mass renormalized). Contrast with
ZeroInflatedDistribution, where a zero can come from either the inflation or the base, so an
observed zero is latent-ambiguous and needs EM. In a hurdle model every zero is structural and every
positive is a (truncated) base draw – there is no latent variable, so the two parts are estimated
independently and in closed form: pi is just the zero rate, and the base is fit to the
positive observations. Wrapping any count base gives the whole family: a Poisson base is the hurdle
Poisson, a NegativeBinomial base the hurdle NB, and so on.
- class HurdleDistribution(base, pi, name=None, keys=None)[source]
Bases:
SequenceEncodableProbabilityDistributionA zero hurdle (probability
pi) followed by a zero-truncated base for the positive counts.- Parameters:
- log_density(x)[source]
Return
log piatx == 0, elselog[(1-pi) p_base(x) / (1 - p_base(0))].
- seq_log_density(x)[source]
Vectorized hurdle log-density for an encoded batch.
- sampler(seed=None)[source]
Return a HurdleSampler for this distribution.
- Parameters:
seed (int | None)
- Return type:
HurdleSampler
- estimator(pseudo_count=None)[source]
Return an estimator that fits
pi(the zero rate) and the base on the positives – closed form.- Parameters:
pseudo_count (float | None)
- Return type:
HurdleEstimator
- dist_to_encoder()[source]
Return the data encoder (base encoding + a boolean is-zero mask).
- Return type:
HurdleDataEncoder
- class HurdleSampler(dist, seed=None)[source]
Bases:
DistributionSamplerDraw a zero with probability
pi, otherwise draw from the zero-truncated base.- Parameters:
dist (HurdleDistribution)
seed (int | None)
- class HurdleAccumulator(base_accumulator, keys=None)[source]
Bases:
SequenceEncodableStatisticAccumulatorAccumulate the zero count (for
pi) and the base sufficient statistics over the positives only.- Parameters:
base_accumulator (SequenceEncodableStatisticAccumulator)
keys (str | None)
- update(x, weight, estimate)[source]
- seq_update(x, weights, estimate)[source]
- initialize(x, weight, rng)[source]
- Parameters:
x (Any)
weight (float)
rng (RandomState | None)
- Return type:
None
- seq_initialize(x, weights, rng)[source]
- Parameters:
weights (ndarray)
rng (RandomState | None)
- Return type:
None
- combine(suff_stat)[source]
- scale(c)[source]
Scale linear sufficient statistics in-place by
c.The structural default is correct for ordinary weighted sums, nested tuples/lists/dicts, and numeric arrays. Families whose
value()payload includes non-linear metadata such as support bounds must override this method and leave that metadata unscaled.- Parameters:
c (float)
- Return type:
HurdleAccumulator
- key_merge(stats_dict)[source]
Pool this accumulator’s statistics into
stats_dictunder its merge key.The structural default implements the common single-key pattern: store the accumulator under
self.keysthe first time the key is seen, elsecombineinto the one already there. Accumulators with several named keys (e.g. an HMM’s init/trans/state keys) or a non-accumulator stats payload override this. AkeysofNone(the default) is a no-op.
- key_replace(stats_dict)[source]
Replace this accumulator’s statistics from the pooled
stats_dictentry (see key_merge).
- acc_to_encoder()[source]
- Return type:
HurdleDataEncoder
- class HurdleAccumulatorFactory(base_factory, keys=None)[source]
Bases:
StatisticAccumulatorFactoryFactory for
HurdleAccumulator.- Parameters:
base_factory (StatisticAccumulatorFactory)
keys (str | None)
- make()[source]
- Return type:
HurdleAccumulator
- class HurdleEstimator(base_estimator, pseudo_count=None, name=None, keys=None, trunc_max_iter=100, trunc_threshold=1.0e-10)[source]
Bases:
ParameterEstimatorClosed-form
pi(the zero rate) plus the zero-truncated MLE of the base over the positives.The two parts are independent.
piis the observed zero rate. The count part is the base fit by maximum likelihood under the zero truncation – NOT the base fit naively to the positives, which is biased (it recovers the truncated mean, so the fitted model would not match the data). The truncated MLE is obtained by a short EM that treats the removed zeros as missing data: given the current base, the positives implyN_missing = N_pos * P0/(1-P0)hypothetical base zeros; refit the base to the positives plus those pseudo-zeros and iterate. (If the base has no mass at 0 there is no truncation and the positives are fit directly.)- Parameters:
- accumulator_factory()[source]
- Return type:
HurdleAccumulatorFactory
- class HurdleDataEncoder(base_encoder)[source]
Bases:
MaskedBaseEncoderEncode observations via the base encoder, plus a boolean
x == 0mask.- Parameters:
base_encoder (DataSequenceEncoder)