Ordered and Zero-Inflated Families¶
Ordered-categorical families, conditional and inline, and the zero-inflated, hurdle, and mixture distributions PyTorch does not ship.
ordered
¶
Cutpoint-parameterised ordered-categorical morphisms.
Ordered-categorical distributions assign probability mass to a
discrete set of ordered categories {0, 1, ..., K-1} via a latent
real-valued eta and K - 1 cutpoints
c_0 < c_1 < ... < c_{K-2}. The cumulative probability of
landing at or below category k is CDF(c_k - eta), where
CDF is either the logistic or the standard normal cumulative
distribution function:
P(Y <= k | eta, c) = CDF(c_k - eta) for 0 <= k < K - 1
P(Y = k | eta, c) = CDF(c_k - eta) - CDF(c_{k-1} - eta)
P(Y = 0 | eta, c) = CDF(c_0 - eta)
P(Y = K - 1 | eta, c) = 1 - CDF(c_{K-2} - eta)
The cutpoints argument is supplied at call time as a 1-D tensor
of length K - 1, allowing the same morphism to be reused with
different cutpoint vectors across observations or models.
Sampling is non-reparameterisable: the support is discrete.
ConditionalOrderedLogistic
¶
ConditionalOrderedLogistic(domain: AnySpace, codomain: AnySpace, num_categories: int, hidden_dim: int | Sequence[int] | None = None, param_source: ParamSource | None = None, param_source_option: str | None = None)
Bases: _ConditionalOrdered
Conditional ordered-logistic over num_categories ordered classes.
The latent eta(x) is computed by the parameter source. Given
a vector of num_categories - 1 ordered cutpoints supplied at
call time, the probability of category k is
P(Y = k) = sigmoid(c_k - eta) - sigmoid(c_{k-1} - eta)
with the conventions sigmoid(c_{-1} - eta) = 0 and
sigmoid(c_{K-1} - eta) = 1.
| PARAMETER | DESCRIPTION |
|---|---|
domain
|
Source space.
TYPE:
|
codomain
|
Target space; semantically the set of ordered categories.
TYPE:
|
num_categories
|
Number of ordered categories
TYPE:
|
hidden_dim
|
Hidden layer width for the neural parameter source.
TYPE:
|
Source code in src/quivers/continuous/ordered.py
ConditionalOrderedProbit
¶
ConditionalOrderedProbit(domain: AnySpace, codomain: AnySpace, num_categories: int, hidden_dim: int | Sequence[int] | None = None, param_source: ParamSource | None = None, param_source_option: str | None = None)
Bases: _ConditionalOrdered
Conditional ordered-probit over num_categories ordered classes.
Identical to :class:ConditionalOrderedLogistic but uses the
standard normal cumulative distribution function in place of the
logistic CDF.
| PARAMETER | DESCRIPTION |
|---|---|
domain
|
Source space.
TYPE:
|
codomain
|
Target space; semantically the set of ordered categories.
TYPE:
|
num_categories
|
Number of ordered categories
TYPE:
|
hidden_dim
|
Hidden layer width for the neural parameter source.
TYPE:
|
Source code in src/quivers/continuous/ordered.py
_ordered
¶
Ordered-categorical distribution families that PyTorch does not
ship natively (OrderedLogistic, OrderedProbit).
The DSL surfaces these as inline call sites:
observe y : Resp <- OrderedLogistic(eta, cutpoints)
with eta a real predictor (one row per observation) and
cutpoints either a globally shared sorted vector of length
K - 1 or a per-row sorted matrix of shape (batch, K - 1).
Per-row cutpoints land in the ordinal-mixed-model setting where
every participant has distinct thresholds; the distribution's
broadcast rules handle both shapes uniformly.
OrderedLogistic
¶
Bases: Distribution
Ordered-logit distribution over K = cutpoints.shape[-1] + 1
ordered categories indexed 0 .. K - 1.
With a real predictor eta and a sorted cutpoint vector
c = (c_0 < c_1 < ... < c_{K-2}):
P(Y = 0) = sigmoid(c_0 - eta)P(Y = k) = sigmoid(c_k - eta) - sigmoid(c_{k-1} - eta)for0 < k < K - 1P(Y = K - 1) = 1 - sigmoid(c_{K-2} - eta)
Cutpoint broadcasting:
- Shared cutpoints
cof shape(K - 1,)apply uniformly to every row. - Per-row cutpoints of shape
(batch, K - 1)apply distinct thresholds per observation (the ordinal-mixed-model case). - Arbitrary leading batch shape is supported; the last axis is always the cutpoint axis.
Log probabilities are computed without forming the difference of
sigmoids: with a < b the two cutpoint offsets bounding a
category, sigmoid(b) - sigmoid(a) equals
sigmoid(b) * sigmoid(-a) * (1 - exp(a - b)), so its log is a sum
of two log-sigmoids and a log(1 - exp(.)) term, each accurate in
both tails. A category far from the predictor thus keeps its exact
log probability rather than one floored at the smallest normal
float.
Reference: McCullagh 1980.
Source code in src/quivers/continuous/_ordered.py
_zip_hurdle
¶
Sugar wrappers for zero-inflated, hurdle, and mixture families.
Each class here desugars at construction time to a composition in the measure algebra:
ZeroInflatedPoisson(pi, rate) := Mixture([pi, 1-pi], [PointMass(0), Poisson(rate)])HurdlePoisson(pi, rate) := Mixture([pi, 1-pi], [PointMass(0), Restrict(Poisson(rate), low=1)])MixtureNormal(w, loc, scale) := Mixture(w, [Normal(loc_k, scale_k) for k])
Internally each is a Mixture
of PointMass and
Restrict / base components,
which the rewrite pass recognises and lifts to the canonical
Bernoulli-branch + conditional-density form Stan / PyMC / NumPyro
expect. A single Mixture-with-PointMass emitter covers every family
in place of per-family per-base Cartesian-product renderer logic.
ZeroInflatedPoisson
¶
Bases: Distribution
Mixture([pi, 1-pi], [PointMass(0), Poisson(rate)]).
Total zero mass pi + (1-pi) * exp(-rate) per Lambert 1992;
the count component is the unrestricted Poisson, so excess zeros
come from both the structural-zero spike and the natural Poisson
zeros. Contrast with
HurdlePoisson
in which the count component is zero-truncated.
Reference: Lambert 1992.
Source code in src/quivers/continuous/_zip_hurdle.py
HurdlePoisson
¶
Bases: Distribution
Mixture([pi, 1-pi], [PointMass(0), Restrict(Poisson(rate), low=1)]).
Two-stage hurdle model: a Bernoulli(1 - pi) decides whether the
response is zero or positive; conditional on positivity, the
response is a zero-truncated Poisson. Because the two components
have measure-disjoint supports, the joint log-density factors
into a Bernoulli plus a zero-truncated Poisson term, and the
rewrite pass emits that factored form to every backend.
Reference: Mullahy 1986.
Source code in src/quivers/continuous/_zip_hurdle.py
MixtureNormal
¶
Bases: Distribution
Mixture(weights, [Normal(loc_k, scale_k) for k]).
Same-family Gaussian mixture with K = weights.shape[-1]
components. Mixing weights live in the K-simplex along the last
axis; component means and scales also vary along the last axis
and broadcast over the leading batch.
For mixing arbitrary families together, construct the
Mixture directly with a
list of heterogeneous components.
Reference: McLachlan & Peel 2000.
Source code in src/quivers/continuous/_zip_hurdle.py
ZeroOneInflatedBeta
¶
ZeroOneInflatedBeta(mu: Tensor, phi: Tensor, zoi: Tensor, coi: Tensor, validate_args: bool | None = None)
Bases: Distribution
Zero-one inflated beta (Ospina & Ferrari 2010 / brms ZOIB).
Mixture of point masses at 0 and 1 with a continuous Beta on (0, 1):
P(y = 0) = zoi * (1 - coi)P(y = 1) = zoi * coiP(y ∈ (0, 1)) = (1 - zoi) · Beta(μ·φ, (1-μ)·φ)
Parameters follow the mean-precision Beta reparameterisation and the
brms zoi / coi inflation probabilities (all on the unit
interval). Formula frontend emits
ZeroOneInflatedBeta(mu, phi, zoi, coi).