NormalGammaPrior#

class cultivars.bayes.priors.NormalGammaPrior(*, shape=0.1, deterministic_scale=10.0)[source]

Bases: _AdaptivePrior

Normal-Gamma shrinkage: the Bayesian lasso’s adjustable-kurtosis parent.

Griffin and Brown’s (2010) prior. Each standardized lag coefficient is normal with its own variance, and the variances are Gamma,

\[\beta_{ij} \mid \psi_{ij} \sim \mathcal{N}(0, \psi_{ij}), \qquad \psi_{ij} \sim \mathrm{Gamma}(\lambda,\, \gamma), \qquad \gamma \sim \mathrm{Gamma}(2,\, 1),\]

with \(\lambda\) the shape, \(\gamma\) the rate, and \(\beta_{ij}\) the coefficient divided by the Minnesota unit ratio \(s_i / s_j\). The marginal of \(\beta_{ij}\) has variance \(\lambda / \gamma\) and excess kurtosis \(3 / \lambda\), and that second fact is the point. At \(\lambda = 1\) the marginal is exactly the Laplace of the Bayesian lasso; pushing the shape below one puts more mass at zero and fattens the tails at the same time, which is the knob the lasso lacks: the lasso can only trade sparsity against over-shrinking large coefficients, and a small shape buys both. The rate is the global tightness, and its own Gamma hyperprior means overall shrinkage is learned rather than tuned; the default shape of a tenth is well into the sparse regime.

The variance conditionals are generalized-inverse-Gaussian and the rate’s is Gamma, all drawn exactly. The deterministic and exogenous columns are not shrunk; they sit at a fixed loose variance.

Variables:
  • shape – The Gamma shape \(\lambda\) of the local variances; 1 is the Bayesian lasso, smaller is spikier with fatter tails.

  • deterministic_scale – Looseness of the unshrunk deterministic and exogenous rows, in units of each equation’s residual scale.

Raises:

SpecificationError – If shape or deterministic_scale is not positive, at the first moment call, which is the model’s fit.

Note

The prior mean is zero everywhere, without a persistence hyperparameter: centring a sparsity prior away from zero would change what shrinking a coefficient means. Difference the data, or use the Minnesota family, for random-walk centring. Adaptive priors do not compose, and the Chib marginal likelihood is not offered under one; compare by predictive score. The scale this prior reports is \(\sqrt{\psi_{ij}}\), the prior standard deviation of the standardized coefficient; the global rate is folded into it rather than reported separately, so it reads like the horseshoe’s \(\tau \lambda_{ij}\).

Warning

Only GibbsBVAR samples the hierarchy. The static moments interface reports the variance at the initial scales, 0.04 on the standardized lag block, which is what admissibility checks need and not the Normal-Gamma; a model that reads only the static moments is fitting a fixed Gaussian prior under this class’s label.

See also

  • shrinkage_scales() – the posterior mean local scale per lag coefficient, this prior’s diagnostic.

  • HorseshoePrior – half-Cauchy scales, no shape to set, heavier tails than any finite shape gives.

  • DirichletLaplacePrior – the other GIG-conditional hierarchy, with a simplex budget across coefficients.

  • SpikeAndSlabPrior – selection rather than shrinkage.

References

Griffin, J. E., & Brown, P. J. (2010). Inference with normal-gamma prior distributions in regression problems. Bayesian Analysis, 5(1), 171-188.

Park, T., & Casella, G. (2008). The Bayesian lasso. Journal of the American Statistical Association, 103(482), 681-686.

Huber, F., & Feldkircher, M. (2019). Adaptive shrinkage in Bayesian vector autoregressive models. Journal of Business & Economic Statistics, 37(1), 27-39.

Example

Three series of which only the first has an own lag. The local scale is an order of magnitude larger on the signal than on any noise coefficient, and the noise coefficients are shrunk harder than the horseshoe shrinks them, the small shape at work:

>>> import numpy as np
>>> from cultivars.multivariate.large_dim.gibbs import GibbsBVAR
>>> rng = np.random.default_rng(0)
>>> y = np.zeros((200, 3))
>>> for t in range(1, 200):
...     y[t] = np.array([0.8, 0.0, 0.0]) * y[t - 1] + rng.standard_normal(3)
>>> res = GibbsBVAR(y, order=1, prior=NormalGammaPrior()).fit(
...     n_draws=1500, n_burn=500, seed=0
... )
>>> res.prior_label
'ng(theta=0.1)'
>>> scales = res.shrinkage_scales()[0]
>>> bool(scales[0, 0] > 0.5), bool(np.delete(scales, 0).max() < 0.2)
(True, True)
>>> np.abs(res.coefficients[0]).round(1)
array([[0.7, 0. , 0. ],
       [0. , 0. , 0.1],
       [0. , 0. , 0. ]])

Private methods#

_check()

Reject hyperparameters that do not describe a prior.

_draw_scales(standardized, context, rng, scales)

GIG conditionals for the variances, Gamma for the global rate.

_initial_scales(context, reference)

Minnesota-tightness local variances; the rate that implies them.

_label()

Short description for summary tables and comparison rows.

_scale_variance(scales, context)

ratio**2 * psi on the lag block, loose elsewhere.

_tracked(scales, context)

The local scale per lag coefficient.

_tracked_label()

What the averaged diagnostic is.