convergence#

cultivars.bayes.chains.convergence(*chains, names=None, rhat_tol=_RHAT_TOL, min_ess=_MIN_ESS_PER_CHAIN, source='draws')[source]#

Full per-quantity report over one or more chains.

One row per scalar quantity: the posterior mean and standard deviation, mcse(), ess_bulk(), ess_tail(), rhat(), and the geweke() score of largest magnitude across chains. The verdict applies the thresholds of Vehtari et al. (2021): a quantity is flagged when

\[\widehat{R} > \texttt{rhat\_tol} \quad\text{or}\quad \min\!\bigl(\widehat{S}_{\text{bulk}}, \widehat{S}_{\text{tail}}\bigr) < \texttt{min\_ess} \cdot C,\]

for \(C\) chains, and the report is converged when nothing is flagged. A quantity whose draws never moved has nan in every column and is listed as degenerate rather than counted either way, because the report cannot tell a parameter fixed by construction from a sampler that is stuck; read the list. The Geweke score is reported for reading and is nan when the chains are too short for its default segments.

This is the same machinery behind the convergence() method of every sampled result in the package, for draws that did not come from the package or for a function of the package’s draws whose own convergence is the question.

Parameters:
  • *chains (ArrayLike) – One or more (S,) or (S, d) chains of the same shape from independent runs, with S at least eight and finite throughout. Passing two runs from different seeds is what lets \(\widehat{R}\) detect a chain confined to one mode; a single run is assessed by its two halves, which detects drift only.

  • names (Sequence[str] | None) – d labels, one per column; defaults to x[0], ..., x[d-1], or x for (S,) chains.

  • rhat_tol (float) – \(\widehat{R}\) above which a quantity is flagged. Must exceed one.

  • min_ess (float) – Effective draws per chain below which a quantity is flagged; the floor applied to the pooled size is min_ess times the number of chains. Must be positive.

  • source (str) – What was assessed, for the summary title.

Return type:

_ConvergenceTest

Returns:

The ConvergenceTest – read converged, flagged, and degenerate; worst() names the quantities with the largest \(\widehat{R}\), and summary() renders the table in that order.

Raises:
  • SpecificationError – If no chain is given, a chain is shorter than eight draws, rhat_tol does not exceed one, or min_ess is not positive.

  • DimensionError – If a chain is not one- or two-dimensional, the chains differ in shape, or names does not match the number of quantities.

  • NumericalError – If any draw is not finite.

See also

ConvergenceTest: The record and its summary.

References

Vehtari, A., Gelman, A., Simpson, D., Carpenter, B., & Bürkner,

P.-C. (2021). Rank-normalization, folding, and localization: An improved \(\widehat{R}\) for assessing convergence of MCMC. Bayesian Analysis, 16(2), 667-718.

Example

Three quantities drawn jointly from one run:

>>> import numpy as np
>>> rng = np.random.default_rng(6)
>>> report = convergence(rng.standard_normal((2000, 3)))
>>> report.names
('x[0]', 'x[1]', 'x[2]')
>>> report.flagged, report.converged
((), True)

Two runs that disagree in location are flagged on \(\widehat{R}\):

>>> stuck = convergence(rng.standard_normal(500), 4.0 + rng.standard_normal(500))
>>> stuck.flagged, round(float(stuck.rhat[0]), 1) > 1.5
(('x',), True)

A column that never moved is reported, not judged:

>>> fixed = np.column_stack([rng.standard_normal(2000), np.ones(2000)])
>>> report = convergence(fixed, names=("free", "fixed"))
>>> report.degenerate, report.converged
(('fixed',), True)