Exact Model Enumeration & Bayesian Model Averaging
Python · R · Part 2 of the variable-selection arc — the conjugate route
Overview
Part 2 of the variable-selection arc: the conjugate route. Part 1 searched the model space with a spike-and-slab Gibbs sampler. But if the candidate set is small, we don't have to search at all — we can enumerate every model exactly. George & McCulloch (1997) showed how: put a conjugate prior on each model's coefficients so and integrate out analytically, leaving a closed-form marginal likelihood . With predictors there are models; for we score all of them and get exact posterior model probabilities — no MCMC, no Monte-Carlo error. This reproduces Congdon's (2005) Example 3.3 on the cystic-fibrosis PEmax data (respiratory muscle strength in 25 patients against 9 clinical predictors), enumerating all models rather than working through them in forward stages.
The g-prior and the closed-form marginal likelihood
For a model indexed by an inclusion vector , the conjugate choice is Zellner's -prior on the coefficients, , with a reference prior . Integrating out gives a marginal likelihood that depends on the data only through the model's (Liang et al. 2008) — the numerator penalises size, the denominator rewards fit, an automatic fully-Bayesian Occam balance. The single hyperparameter sets how wide the slab is — how large an effect the prior is prepared to entertain — and because the penalty for size grows with it, is precisely the dial controlling how hard the Occam balance bites. Here , the unit-information prior: the prior is given the weight of a single observation, the least informative choice that still lets the marginal likelihood be computed, which is what makes model comparison behave like BIC and matches R's BAS (alpha = n) exactly. The algorithm is a deterministic sweep, not a Markov chain: center and ; for each of the subsets regress by least squares, read off , and evaluate the closed-form ; normalise over all models for exact posterior model probabilities; then sum over models containing predictor for its inclusion probability, and weight the -shrunk estimates for model-averaged coefficients. Because it is exact, there is nothing to converge or diagnose — the only limit is that must be enumerable (beyond one falls back to Part 1's search). The engine is a self-contained bvsenum.py.
Results
Two predictors clear the line, and a third sits on it — weight () and FEV1 () are the only inclusion probabilities above the neutral 0.5 that a predictor starts with, with BMP third at , fractionally below it, and the remaining six trailing from 0.376 down to 0.213. Clinically that is sensible, since respiratory muscle strength tracks body size, nutrition and lung function — but it is worth reading the numbers exactly rather than rounding them into a top three. With 25 patients and nine correlated predictors, only two predictors have had their prior odds moved upward at all. But no single model dominates: the best model, weight + bmp + fev1, holds only ~5% of the posterior; dozens are plausible, and with 25 patients and 9 correlated predictors which model is genuinely uncertain — a point a stepwise "winner" hides entirely. The posterior over model size peaks at 3–4 predictors (averaging ~3.4) — the -prior's built-in Occam penalty resisting the urge to use all nine. This is why we average: inclusion probabilities and model-averaged coefficients summarise all 512 models weighted by evidence rather than betting on one fit chosen under uncertainty. Enumeration and search agree on the substance: the Part-1 spike-and-slab MCMC — a different prior reached by sampling — puts the same two predictors up front — weight (0.651) and FEV1 (0.549) — while the ordering behind them shifts: the sampled run nudges age (0.442) just above BMP (0.417), reversing third and fourth place. The leading pair is robust to both prior and algorithm; the tail ordering is not, which is the honest reading of inclusion probabilities that are genuinely prior-dependent and separated by less than the spacing between them. Seeing them coincide here, where we can enumerate, is what licenses trusting the search where we cannot. The exact marginal likelihood is the same object R's BAS computes.
Notebooks
Downloads
bvsenum.py The from-scratch g-prior model enumerator — closed-form marginal likelihoods, posterior model probabilities, inclusion probabilities, and model-averaged coefficients (new self-contained module) cystfibr_data.csv Cystic-fibrosis PEmax data (O'Neill et al. 1983; ISwR::cystfibr; Congdon Example 3.3) — respiratory muscle strength vs 9 clinical predictors, n = 25 References
- George, E. I. & McCulloch, R. E. (1997). Approaches for Bayesian variable selection. Statistica Sinica 7(2), 339–373. — the conjugate model-enumeration framework reproduced here
- Zellner, A. (1986). On assessing prior distributions and Bayesian regression analysis with g-prior distributions. In Bayesian Inference and Decision Techniques, 233–243. — the g-prior on the coefficients
- Liang, F., Paulo, R., Molina, G., Clyde, M. A. & Berger, J. O. (2008). Mixtures of g priors for Bayesian variable selection. Journal of the American Statistical Association 103(481), 410–423. — the closed-form marginal likelihood in terms of R²_γ
- Kass, R. E. & Wasserman, L. (1995). A reference Bayesian test for nested hypotheses and its relationship to the Schwarz criterion. Journal of the American Statistical Association 90(431), 928–934. — the unit-information prior (g = n) and the BIC connection
- Raftery, A. E., Madigan, D. & Hoeting, J. A. (1997). Bayesian model averaging for linear regression models. Journal of the American Statistical Association 92(437), 179–191. — Bayesian model averaging
- Hoeting, J. A., Madigan, D., Raftery, A. E. & Volinsky, C. T. (1999). Bayesian model averaging: a tutorial. Statistical Science 14(4), 382–401. — the BMA tutorial
- Clyde, M. A., Ghosh, J. & Littman, M. L. (2011). Bayesian adaptive sampling for variable selection and model averaging. Journal of Computational and Graphical Statistics 20(1), 80–101. — the R
BASpackage used in the cross-check