Reading and controlling the κ fallback¶
import numpy as np
import pandas as pd
import statsmodels.api as sm
import statsmodels.formula.api as smf
from pymargins import Margins
rng = np.random.default_rng(42)
n = 2000
df = pd.DataFrame({
"age": rng.integers(20, 75, n),
"female": rng.binomial(1, 0.52, n),
"treated": rng.binomial(1, 0.40, n),
})
lp = -1.5 + 0.04 * df["age"] - 0.3 * df["female"] + 0.8 * df["treated"]
df["y"] = rng.binomial(1, 1 / (1 + np.exp(-lp)))
fit = smf.glm("y ~ age + female + treated", data=df,
family=sm.families.Binomial()).fit()
m = Margins.log_scale(fit, at="overall")
Every result records the inference path actually used. When the session’s κ threshold is exceeded, delta auto-falls-back to simulation, and the summary annotates the fallback reason.
m = Margins.log_scale(fit, kappa_threshold=0.3, method="delta", n_sim=4000)
res = m.predict(atexog={"age": [25, 45, 65]})
print(res.summary()) # notes 'fallback: simulation (κ=0.42 > 0.30)'
============================================================
Margins Result (delta, level=0.95)
============================================================
estimate std err z P>|z| [95% Conf. Int.]
------------------------------------------------------------
age=25 0.4120 0.0453 -19.5680 0.000 0.3770, 0.4503
age=45 0.6124 0.0184 -26.7196 0.000 0.5908, 0.6349
age=65 0.7819 0.0173 -14.1802 0.000 0.7558, 0.8089
============================================================
n = 2000
Note: std err is on the inference scale; estimate and CI are on the reporting scale.
κ: max=0.062
Delta-vs-sim disagreement: 0.498%
Pre-flight diagnostic¶
print(m.diagnose().summary())
Session diagnostic (50 design points)
Session: Margins session
Model: GLMResultsWrapper
Adapter: StatsmodelsGLMAdapter
Inference scale: log
Variance: default
Confidence level: 0.95
At: overall
Method: delta (κ-threshold=0.3)
n_sim: 4000
n_boot: 1000
Gradient backend: autodiff
Diagnostics: enabled
Strict: False
κ min: 0.031
κ median: 0.064
κ max: 0.132
Verdict: delta_borderline
Delta method is borderline. Consider running specific estimands with method='simulation' or enabling automatic fallback via the session's kappa_threshold.
diagnose() samples the estimand surface and reports the κ
distribution; if it is uniformly large, change the inference scale
(see Inference scales and the κ diagnostic) before paying for
simulation on every call.
What to do when κ is high¶
A high κ means the delta-method linearization is a poor approximation for your estimand. Three strategies, in order of preference:
Change the inference scale. Often the estimand is nearly linear on a different scale (log instead of identity, logit instead of probability). See Inference scales and the κ diagnostic.
Accept the simulation fallback. If the scale is already the most natural one, Krinsky–Robb simulation is a robust alternative. Just make sure
n_simis large enough (≥ 4000) for stable tail quantiles.Switch to bootstrap. Bootstrap does not rely on local linearity at all; it is the safest choice when both curvature and model misspecification are concerns. See Bootstrap inference.
Disabling the fallback¶
Set kappa_threshold=float("inf") to force the chosen method= to
run regardless of curvature.
m = Margins.log_scale(fit, kappa_threshold=float("inf"))
Disabling diagnostics altogether¶
In tight loops, set diagnostics=False to skip the κ computation:
m = Margins.log_scale(fit, diagnostics=False)