ZeroInflatedNegativeBinomial

Zero-inflated negative binomial (ZINB) family for GAMLSS.

Usage

Source

ZeroInflatedNegativeBinomial(theta=1.0)

ZeroInflatedNegativeBinomial combines the two departures from plain Poisson counts that are most common in practice: overdispersion (variance exceeding the mean, as in NegativeBinomial) and structural excess zeros (as in ZeroInflatedPoisson). It is appropriate for count data where, even after allowing for a mixture of structural and sampling zeros, the remaining positive counts are still more variable than a Poisson model would predict — for example, healthcare utilization counts, insurance claim frequencies, or ecological abundance data with many true absences plus overdispersed non-zero counts. mu (the NB mean) and pi (the zero-inflation probability) are modeled as smooth functions of covariates through GAMLSS, while the overdispersion parameter theta is fixed at construction rather than estimated per observation.

Parameters

theta: float = 1.0
Negative binomial size (overdispersion) parameter, must be positive. Larger values mean less overdispersion (theta -> infinity recovers ZeroInflatedPoisson); smaller values mean more overdispersion among the non-structural-zero counts. Unlike mu and pi, theta is a single fixed value shared across all observations rather than modeled by a smooth predictor.

Notes

Two distributional parameters are modeled, each with its own link:

g_{\mu}(\mu) = \log(\mu), \qquad g_{\pi}(\pi) = \log\!\left(\frac{\pi}{1-\pi}\right).

The probability mass function is a mixture of a point mass at zero and a Negative Binomial distribution using the mean-size parameterization (Var(NB) = mu + mu^2/theta):

P(Y = 0) = \pi + (1-\pi)\, \mathrm{NB}(0 \mid \mu, \theta), \qquad P(Y = k) = (1-\pi)\, \mathrm{NB}(k \mid \mu, \theta) \quad \text{for } k > 0,

where

\mathrm{NB}(k \mid \mu, \theta) = \binom{k+\theta-1}{k} \left(\frac{\theta}{\theta+\mu}\right)^{\theta} \left(\frac{\mu}{\theta+\mu}\right)^{k}.

Examples

Fit a GAMLSS for overdispersed count data with excess zeros:

import numpy as np
import whittaker as wk
from scipy.special import expit

rng = np.random.default_rng(0)
n = 300
x = np.linspace(0, 2 * np.pi, n)
mu = np.exp(0.5 + 0.4 * np.sin(x))
pi = expit(-1.0 + 0.8 * np.cos(x))
theta = 2.0

is_structural_zero = rng.uniform(size=n) < pi
counts = rng.negative_binomial(theta, theta / (theta + mu))
y = np.where(is_structural_zero, 0, counts).astype(float)

data = {"x": x, "y": y}

model = wk.GAMLSS(
    formulas={"mu": "y ~ s(x)", "pi": "y ~ s(x)"},
    family=wk.ZeroInflatedNegativeBinomial(theta=theta),
)
model.fit(data)
print(model.summary())
GAMLSS fit summary
========================================
Family: ZeroInflatedNegativeBinomial(theta=2, mu=log, pi=logit)
N obs: 300
Global deviance: 911.2129
AIC: 921.0281
BIC: 939.2047
Log-likelihood: -455.6064
Converged: True (3 iterations)

--- mu ---
  EDF total: 2.00
  Smooth 1: edf = 1.00

--- pi ---
  EDF total: 2.91
  Smooth 1: edf = 1.91

Attributes

Name Description
parameter_names Names of the distributional parameters modeled by this family.
theta Fixed negative binomial size (overdispersion) parameter.

parameter_names

Names of the distributional parameters modeled by this family.

parameter_names: tuple[str, …]


theta

Fixed negative binomial size (overdispersion) parameter.

theta: float

Methods

Name Description
d2l_dtheta2() Compute the (negative) second derivative of the log-likelihood.
dl_dtheta() Compute the first derivative of the log-likelihood with respect to a parameter.
initialize() Generate starting values for mu and pi before the first IRLS iteration.
link() Map a distributional parameter from its natural scale to the link scale.
link_derivative() Compute the derivative of the link function with respect to the natural parameter.
link_inverse() Map a distributional parameter from the link scale back to its natural scale.
log_likelihood() Compute the total log-likelihood under the zero-inflated negative binomial model.
simulate() Draw a random sample of counts from the fitted zero-inflated NB model.

d2l_dtheta2()

Compute the (negative) second derivative of the log-likelihood.

Usage

Source

d2l_dtheta2(
    param,
    y,
    params,
)

Implements the family-specific working weight used by GAMLSS’s Fisher-scoring updates for the zero-inflated negative binomial model, computed separately for zero and positive observations and floored at _EPS to keep weights strictly positive.

Parameters

param: str

Name of the parameter, either "mu" or "pi".

y: NDArray

Observed response values.

params: dict of str to NDArray
Current fitted values of "mu" and "pi".

Returns

NDArray
Elementwise working weight for param.

dl_dtheta()

Compute the first derivative of the log-likelihood with respect to a parameter.

Usage

Source

dl_dtheta(
    param,
    y,
    params,
)

Implements the family-specific score function for the zero-inflated negative binomial model, combining the derivative of the NB(0 | mu, theta) probability weighted by the mixture for zero observations with the ordinary negative binomial score \partial \ell / \partial \mu = (y - \mu) / (\mu (1 + \mu/\theta)) for positive observations. For pi the score reflects the same zero/positive split as in ZeroInflatedPoisson.dl_dtheta.

Parameters

param: str

Name of the parameter to differentiate with respect to, either "mu" or "pi".

y: NDArray

Observed response values.

params: dict of str to NDArray
Current fitted values of "mu" and "pi".

Returns

NDArray
Elementwise first derivative of the log-likelihood with respect to param.

initialize()

Generate starting values for mu and pi before the first IRLS iteration.

Usage

Source

initialize(y)

Sets mu to the mean of the strictly positive observations (or 1.0 if none are positive) for every observation, and sets pi to half the observed fraction of zeros, clipped to [0.01, 0.5]. The fixed overdispersion parameter theta is not part of the returned dictionary since it is not estimated per observation.

Parameters

y: NDArray
Observed response values.

Returns

dict of str to NDArray
Initial values for "mu" and "pi", each broadcast to the shape of y.




log_likelihood()

Compute the total log-likelihood under the zero-inflated negative binomial model.

Usage

Source

log_likelihood(
    y,
    params,
)

Evaluates

\ell = \sum_{i: y_i = 0} \log\!\big(\pi_i + (1-\pi_i)\, \mathrm{NB}(0 \mid \mu_i, \theta)\big) + \sum_{i: y_i > 0} \Big[\log(1-\pi_i) + \log \mathrm{NB}(y_i \mid \mu_i, \theta)\Big],

where \mathrm{NB}(\cdot \mid \mu, \theta) is the negative binomial probability mass function in the mean-size parameterization with the fixed theta.

Parameters

y: NDArray

Observed response values.

params: dict of str to NDArray
Fitted values of "mu" and "pi" for each observation.

Returns

float
Total log-likelihood summed over all observations.

simulate()

Draw a random sample of counts from the fitted zero-inflated NB model.

Usage

Source

simulate(
    params,
    rng,
)

For each observation, flips a pi-weighted coin to decide whether it is a structural zero; observations that are not structural zeros are drawn from a negative binomial distribution with the fixed theta and success probability theta / (mu + theta), so a sampled value can still be zero even when it was not selected as a structural zero.

Parameters

params: dict of str to NDArray

Fitted values of "mu" and "pi" for each observation to simulate.

rng: object
Random number generator exposing uniform and negative_binomial methods, such as a numpy.random.Generator.

Returns

NDArray
Simulated response values, one per row of params.