geweke#

cultivars.bayes.chains.geweke(*chains, first=0.1, last=0.5)[source]#

Geweke’s early-versus-late z-score, one per chain and quantity.

For a chain of \(N\) draws, the first \(N_A = \lfloor \text{first} \cdot N \rfloor\) and the last \(N_B = \lfloor \text{last} \cdot N \rfloor\) draws are compared as two samples from what should be the same distribution:

\[z = \frac{\bar x_A - \bar x_B} {\sqrt{\widehat{\operatorname{lrv}}_A / N_A + \widehat{\operatorname{lrv}}_B / N_B}},\]

where each long-run variance is the segment’s sample variance times the ratio of its length to its effective sample size, \(\widehat{\operatorname{lrv}} = s^2 \, N / \widehat{S}_{\text{eff}}\). Geweke (1992) estimated the long-run variances with a spectral window; using the Geyer size instead means no window is tuned separately from the rest of this module. A large score says the chain was still moving when the early segment was drawn, that is, the burn-in was too short. Unlike the other statistics here, nothing is pooled: each chain is scored on its own.

Parameters:
  • *chains (ArrayLike) – One or more (S,) or (S, d) chains of the same shape, finite throughout.

  • first (float) – Fraction of each chain forming the early segment.

  • last (float) – Fraction of each chain forming the late segment. The segments must not overlap, so first + last <= 1.

Return type:

NDArray[double]

Returns:

(C,) for (S,) chains, else (C, d), for C chains. Under the null the scores are standard normal, so magnitudes above about 2 indicate the early and late segments disagree in mean; nan where a segment never moved.

Raises:
  • SpecificationError – If no chain is given; if the fractions are not positive or sum to more than one; or if either segment has fewer than eight draws, which at the defaults means a chain shorter than 80.

  • DimensionError – If a chain is not one- or two-dimensional, or the chains differ in shape.

  • NumericalError – If any draw is not finite.

Note

The score is a diagnostic of burn-in, not of mixing: a chain that is stationary but slowly mixing passes it while failing ess_bulk(), and a chain confined to one mode passes it while failing rhat() against a second run. convergence() reports it for reading and leaves it out of the verdict.

References

Geweke, J. (1992). Evaluating the accuracy of sampling-based

approaches to the calculation of posterior moments. In J. M. Bernardo, J. O. Berger, A. P. Dawid, & A. F. M. Smith (Eds.), Bayesian Statistics 4 (pp. 169-193). Oxford University Press.

Example

One score per chain:

>>> import numpy as np
>>> rng = np.random.default_rng(5)
>>> geweke(rng.standard_normal(1000), rng.standard_normal(1000)).shape
(2,)

A chain whose level is still moving is flagged:

>>> drifting = np.linspace(0.0, 3.0, 1000) + rng.standard_normal(1000)
>>> bool(abs(geweke(drifting)[0]) > 2.0)
True