modified_harmonic_mean#
- cultivars.bayes.evidence.modified_harmonic_mean(draws, log_kernel, *, tau=_MHM_TAU, source='draws')[source]#
Geweke’s (1999) modified harmonic mean on posterior draws.
The harmonic-mean identity \(m(y)^{-1} = \mathbb{E}_{\theta \mid y}\bigl[g(\theta) / (f(y \mid \theta)\, \pi(\theta))\bigr]\) holds for any density \(g\) on the parameter space, and the plain harmonic mean, \(g = \pi\), has infinite variance because the prior’s tails are heavier than the posterior’s. Geweke’s modification takes \(g\) to be a Gaussian fitted to the draws and truncated to its central \(\tau\) ellipsoid, so that \(g\) has lighter tails than the posterior by construction:
\[\log \widehat{m}(y) = -\log \frac{1}{S} \sum_{s=1}^{S} \frac{g_\tau(\theta^{(s)})}{f(y \mid \theta^{(s)})\, \pi(\theta^{(s)})}, \qquad g_\tau(\theta) = \frac{\phi(\theta;\, \hat\mu, \hat\Sigma)}{\tau} \, \mathbb{1}\{(\theta - \hat\mu)^\top \hat\Sigma^{-1} (\theta - \hat\mu) \le \chi^2_{d}(\tau)\}.\]The sum is formed on the log scale, and the Monte Carlo standard error of the log estimate is the standard deviation of the ratios divided by the square root of their Geyer effective sample size, so autocorrelated draws are charged for their autocorrelation. The share of draws that fall inside the ellipsoid is compared with \(\tau\): a share far from it says the posterior is not the Gaussian the envelope assumes, and the record notes it.
- Parameters:
draws (
ArrayLike) –(S,)or(S, d)posterior draws, finite throughout, withSgreater than2d + 2so a Gaussian can be fitted. Transform bounded parameters to the real line first (a log for a variance, a logit for a probability) and include the Jacobian inlog_kernel; a Gaussian envelope that leaves the support biases the estimate.log_kernel (
ArrayLike) –(S,)unnormalized log posterior, log likelihood plus log prior, evaluated at each draw in the same parameterization asdraws.tau (
float) – Probability mass of the Gaussian envelope retained, in(0, 1). Draws outside thetauellipsoid receive zero weight; a smaller value is more robust to non-Gaussian tails and uses fewer draws.source (
str) – Label for the record’ssourcefield, which is the row label incompare().
- Return type:
_MarginalLikelihoodSelection- Returns:
The
MarginalLikelihoodSelectionwithmethodset to"modified harmonic mean", the log estimate, its Monte Carlo standard error (nanwhen fewer than eight draws fall inside the ellipsoid),n_drawsthe number of draws supplied,nobszero since the function cannot know the sample, and a note on the envelope, plus a second note when the inside share differs fromtauby more than a tenth.- Raises:
SpecificationError – If
tauis not inside(0, 1), if there are too few draws to fit the envelope, or if no draw falls inside the truncation ellipsoid.DimensionError – If
drawsis not one- or two-dimensional, orlog_kerneldoes not have one value per draw.NumericalError – If any draw or kernel value is not finite.
Note
The estimator is biased upward when the posterior’s tails are heavier than the envelope’s inside the ellipsoid, and the coverage check catches only gross failures; on a skewed posterior the share can sit near
tauwhile the estimate is off by a tenth of a nat. For a roughly elliptical posteriorbridge_sampling()has lower variance and no such bias, at the price of a callable kernel. Records from this function carrynobs = 0, socompare()cannot check that they score the same sample as the records they are ranked against; that is the caller’s responsibility.See also
bridge_sampling()– the lower-variance estimator when the kernel can be evaluated at new points.marginal_likelihood()– the same estimator applied by the particle-chain DSGE result to its own draws.compare()– ranks the records.
References
Geweke, J. (1999). Using simulation methods for Bayesian econometric models: Inference, development, and communication. Econometric Reviews, 18(1), 1-73.
Newton, M. A., & Raftery, A. E. (1994). Approximate Bayesian inference with the weighted likelihood bootstrap. Journal of the Royal Statistical Society B, 56(1), 3-48.
Example
Draws from a standard normal in three dimensions with the unnormalized kernel \(-\tfrac{1}{2}\|z\|^2\); the evidence is the missing constant \((2\pi)^{3/2}\):
>>> import numpy as np >>> rng = np.random.default_rng(1) >>> z = rng.standard_normal((3000, 3)) >>> record = modified_harmonic_mean(z, -0.5 * (z**2).sum(axis=1)) >>> bool(abs(record.log_value - 1.5 * np.log(2 * np.pi)) < 0.05) True >>> record.method, record.n_draws ('modified harmonic mean', 3000)
A bounded parameter left on its own scale biases the estimate; the log transform with its Jacobian removes the bias. Here the draws are exponential, the kernel is \(-x\), and the true log evidence is zero:
>>> rng = np.random.default_rng(3) >>> x = rng.exponential(size=4000) >>> raw = modified_harmonic_mean(x, -x) >>> u = np.log(x) >>> transformed = modified_harmonic_mean(u, -np.exp(u) + u) >>> round(raw.log_value, 2), round(transformed.log_value, 2) (0.12, 0.01)