Riebler 2016 - Penalised Complexity Priors for BYM2
Summary
PC priors place an exponential prior on the Kullback-Leibler “distance” from a flexible model to a base model. For BYM2: (type-2 Gumbel), i.e. an exponential prior on , calibrated by giving ; and a tabulated prior on (via ) calibrated by , shrinking to .
Overview
Four principles (Simpson et al.): (1) Occam’s razor, (2) KLD measures complexity, (3) constant-rate penalisation, (4) user-defined scaling. BYM2 is a flexible extension of two nested base models: level 1 = constant risk (infinite precision); level 2 (given variance) = unstructured noise only ().
Main Content
PC prior distance
; prior: , then transform by change of variables.
PC prior for the precision (Sec. 4.1, App. C.1)
Base: large fixed precision . The -dimensional stochastic part gives , so . With held fixed as :
Interpretation: . Example: is about “99% probability that residual relative risk is below 2”. The paper’s Fig. 2 uses (so ).
PC prior for the mixing parameter (Sec. 4.2, App. C.2)
With , :
for eigenvalues of and for the zero eigenvalue. Put and transform to the logit scale; no closed form. Calibrate by ; INLA:
INLA:::inla.pc.bym.phi(Q, rankdef=1, u=0.5, alpha=2/3). Reasonable default: (conservative: unstructured part dominates).
(The printed formula in the paper reads with an extraction ambiguity; the expression above is the algebraic expansion of the trace form and is what the code below uses.)
Why not gamma priors: gamma has no density at the base model, so the base model can never be reached (overfitting); uniform priors on ignore the shrinkage principle. Figure 2: PC(; ) vs Gamma(1, rate .01/.02); PC(; ) vs Uniform(0,1).
Examples
Distances and PC density on a 16-node grid
Using the scaled grid from Riebler 2016 - Scaling and the BYM2 Construction: 0.029, 0.280, 1.244, 2.298, 2.876 at (verified numerically); at with equals 0.0230, 0.0170, 0.00145 (units: per unit precision).
import numpy as np
def pc_tau_pdf(tau, U=1., alpha=.01):
th = -np.log(alpha)/U; return th/2*tau**-1.5*np.exp(-th*tau**-.5)
def d_phi(phi, Qs):
n = Qs.shape[0]; ev = np.linalg.eigvalsh(Qs); g = np.where(ev > 1e-9, 1/np.maximum(ev, 1e-9), 0.)
return np.sqrt(2*0.5*(phi*(g.sum()-n) - np.sum(np.log(1-phi+phi*g))))PyMC: sigma = pm.Exponential("sigma", rate=-np.log(alpha)/U) implements the PC prior on in standard-deviation form; the prior needs a tabulated log-density via pm.CustomDist or a Beta approximation.
Connections
Riebler 2016 - Simulation Study and Sardinia IDDM Application tests these priors; compare to default priors in Prior Predictive Checking.