nstat.extras.validation.statsmodels_bridge

Cross-validate nstat.fit_poisson_glm() against statsmodels.

statsmodels.genmod.GLM is the third independent Poisson-GLM implementation triangulated by nstat.extras.validation:

Triangulating against two unrelated reference implementations is much stronger than against one — statsmodels uses IRLS like nstat but with a different stopping criterion and no ridge, while NeMoS uses an optax-driven first-order optimizer entirely. Coefficients that agree across all three to high precision are far less likely to be the result of a shared implementation bug.

Install:

pip install nstat-toolbox[test-parity] # or just: pip install statsmodels

Functions

cross_validate_poisson_glm(X, y, *[, ...])

Fit a Poisson GLM with both nstat and statsmodels; return comparison.

Classes

StatsmodelsGLMComparison(nstat_coef, ...)

Side-by-side Poisson-GLM fit comparison: nstat vs statsmodels.

class nstat.extras.validation.statsmodels_bridge.StatsmodelsGLMComparison(nstat_coef, statsmodels_coef, coef_inf_norm, coef_rel_inf_norm)[source]

Bases: object

Side-by-side Poisson-GLM fit comparison: nstat vs statsmodels.

Variables:
  • nstat_coef (numpy.ndarray) – Coefficient vector from nstat.fit_poisson_glm(). Includes the intercept as the first element if the fit included one.

  • statsmodels_coef (numpy.ndarray) – Coefficient vector from statsmodels.api.GLM(...).fit().params(). Layout matches nstat_coef (intercept-first if present).

  • coef_inf_norm (float) – \(\|\beta_{nstat} - \beta_{statsmodels}\|_\infty\).

  • coef_rel_inf_norm (float) – Same but normalized by |nstat_coef|_inf for unitless reports.

Parameters:
nstat_coef: ndarray
statsmodels_coef: ndarray
coef_inf_norm: float
coef_rel_inf_norm: float
assert_agree(atol=0.001, rtol=0.001)[source]

Assert nstat and statsmodels coefficients agree within tolerance.

Default atol=1e-3 reflects the empirical baseline: both libraries use IRLS but with different ridge / stopping conventions, and on a 1000-sample fixture the disagreement runs ~1e-4 to ~1e-3. Tighten only on a per-fixture basis.

Raises:

AssertionError – If neither the absolute (atol) nor relative (rtol) tolerance is met.

Parameters:
Return type:

None

nstat.extras.validation.statsmodels_bridge.cross_validate_poisson_glm(X, y, *, include_intercept=True)[source]

Fit a Poisson GLM with both nstat and statsmodels; return comparison.

Both fits use canonical log-link, no regularization on the statsmodels side, and nstat’s default tiny ridge (l2=1e-6).

Parameters:
  • X (ndarray) – Design matrix, shape (n_samples, n_features).

  • y (ndarray) – Spike-count vector, shape (n_samples,).

  • include_intercept (bool) – If True (default), both fits include an intercept and the returned coefficient vectors are intercept-first.

Return type:

StatsmodelsGLMComparison

Examples

>>> import numpy as np
>>> rng = np.random.default_rng(0)
>>> X = rng.standard_normal((1000, 3))
>>> beta_true = np.array([0.2, -0.4, 0.1])
>>> y = rng.poisson(np.exp(0.5 + X @ beta_true))
>>> cmp = cross_validate_poisson_glm(X, y)
>>> cmp.assert_agree(atol=1e-2)