neighbayes.diagnostics.spatial_kfold

neighbayes.diagnostics.spatial_kfold(model, *, splitter=None, fold_ids=None, n_blocks=10, geometry=None, draws=400, tune=400, chains=2, random_seed=0, progressbar=True, verbose=False, **fit_kwargs)[source]

Spatial block cross-validation for a fitted Bayesian spatial model.

Refits the model on each training fold and evaluates the conditional Gaussian predictive density of the held-out fold under the full-data joint implied by the model.

Parameters:
model : SpatialModel

A model from neighbayes.models. The model must have been constructed (its _X, _y and _W_sparse will be used for prediction); it does not need to be fit, since fold-specific refits are performed internally.

splitter : sklearn-compatible splitter, optional

Any object exposing split(X) that yields (train_idx, test_idx) pairs (sklearn BaseCrossValidator protocol). This is the recommended entry point for using geovalidate splitters such as HilbertKFold, CellStratifiedKFold, LeaveClusterOut, or BallKFold. geometry (when provided) is forwarded as the X argument to split; this suffices for geometry-aware geovalidate splitters. Mutually exclusive with fold_ids.

fold_ids : np.ndarray, optional

Integer fold assignment per observation, shape (n,). When supplied, n_blocks and geometry are ignored.

n_blocks : int, default 10

Number of spatial blocks for the KMeans fallback when neither splitter nor fold_ids is provided.

geometry : geopandas.GeoSeries, optional

Geometry used by the KMeans fallback to cluster centroids, and forwarded to splitter.split when splitter is supplied. Required for the KMeans fallback.

draws=400

Forwarded to SpatialModel.fit() for each per-fold refit. Defaults are deliberately modest to keep CV affordable.

tune=400

Forwarded to SpatialModel.fit() for each per-fold refit. Defaults are deliberately modest to keep CV affordable.

chains=2

Forwarded to SpatialModel.fit() for each per-fold refit. Defaults are deliberately modest to keep CV affordable.

random_seed=0

Forwarded to SpatialModel.fit() for each per-fold refit. Defaults are deliberately modest to keep CV affordable.

progressbar : bool, default True

If True, display a fold-level progress bar (via tqdm) showing CV progress. Independent of any per-chain progress bar inside SpatialModel.fit(), which is always disabled.

verbose : bool, default False

If True, allow per-fold fit calls to print their usual sampler / compile messages to stdout/stderr. When False (the default) those messages — along with PyMC’s INFO logger output and warnings — are suppressed so only the fold-level progress bar is visible.

**fit_kwargs

Extra keyword arguments forwarded to SpatialModel.fit().

Return type:

SpatialCVResult

Notes

When splitter produces folds whose test sets do not form a disjoint partition of the data (e.g. LeaveBallOut with an exclusion buffer, or any splitter where some observations are tested multiple times or not at all), the per-observation accounting used to estimate se is undefined. In that case se is set to nan; elpd_per_fold and elpd remain valid.

Notes

Computation is \(O(K \cdot G \cdot \text{nnz}(W))\) per fold plus the cost of refitting; spatial folds are typically a handful (e.g. n_blocks=5–10). For OLS/SLX the predictive collapses to the standard independent Gaussian and the per-fold cost is \(O(G \cdot n_{\text{test}} \cdot k)\).