Estimate out-of-sample predictive performance with PSIS-LOO (Pareto-smoothed importance sampling leave-one-out cross-validation). PSIS-LOO approximates exact LOO-CV without refitting the model once per observation: each held-out point is scored by reweighting the full-data posterior draws.
With the default measures = NULL, the result holds elpd_loo, the LOO
estimate of expected log pointwise predictive density (ELPD), and p_loo
(effective number of parameters, the difference between in-sample and LOO
log predictive density). p_loo is reported together with elpd_loo.
See loo() and the
Cross-validation FAQ for
interpretation.
Usage
loo_pred_measure(
y = NULL,
ypred = NULL,
mupred = NULL,
ylp = NULL,
measures = NULL,
loo = NULL,
group_ids = NULL,
psis_object = NULL,
save_psis = FALSE,
control = list()
)Arguments
- y
Vector of observed values (
n). Required for every measure exceptelpd,mlpd, andic.- ypred
Matrix of posterior predictive draws (
Sdraws ×nobservations), typically frombrms::posterior_predict(). Required forrps,srps, andbrier.- mupred
Matrix of posterior expected values (
S×n), typically frombrms::posterior_epred(). Required formae,mse,rmse,r2,acc, andbacc.- ylp
Matrix of pointwise log predictive densities or probabilities (
S×n), typically frombrms::log_lik(), or a 3-D array (I×C×n: iterations, chains, observations). Required for density-based summaries (elpd,mlpd,ic).- measures
Measures to compute.
NULL(default) giveselpd(withp_loo/p_kfoldfor LOO and k-fold). Can be:A character vector of built-in names; see supported_measures_list.
A function built with
custom_measure()for one custom measure.A list mixing character scalars (built-in names) and named functions (custom measures), e.g.
list("rps", my_metric = my_fun).
Custom functions are called with any of
y,ypred,mupred,ylp, andlog_weightsthat appear in their formals, plus arguments fromcontrol. They must return a list withestimate,se, andpointwise. A length-2estimates(estimate and SE) can replaceestimateandse.A custom measure declares whether it is a loss (lower is better) or a utility (higher is better) with
lossincustom_measure(). Without it a custom measure is taken to be a utility.model_compare()uses the declaration to put all measures on a common utility scale and to rank models, so an undeclared loss is compared and ranked in the wrong direction.A custom measure can declare how the standard error of a difference between two models is computed, with
se_diff_funincustom_measure(). It accepts a functionfunction(ref, cmp) ...or the shorthands"sum"and"mean"for the paired pointwise formulas. Without a declaration,model_compare()reports the difference with anNAstandard error. A function receives one list per model with elementsestimate,se,pointwise, andextra, always on the measure's natural scale, and must return the standard error of the difference as a numeric scalar.extrais for anything the standard error needs that the pointwise values do not carry. Return it as an additional list elementextrafrom the measure function and it is stored alongside the estimates and passed on to itsmeasure_se_difffunction; the built-inr2uses it for the baseline(y_i - mean(y))^2, which cannot be recovered onceyis out of scope.- loo
A
loo()result, computed withsave_psis = TRUEso that PSIS weights are available for additional measures. Seeloo_pred_measure().- group_ids
Optional vector of group identifiers for grouped summaries (reserved; not yet implemented).
- psis_object
A
psisobject with LOO importance weights. An alternative to passing a fulllooobject; must be supplied together withylpwhen computingelpd.- save_psis
Logical. If
TRUE, store thepsisobject in the result so that additional measures can be added later withpred_measure()without recomputing PSIS weights.- control
Named list of per-measure settings. Each name must match an element of
measures; the value is a list of arguments passed to that measure's summary function (e.g.list(new_measure = list(add_arg = 10))).
Value
An object of class "loo_pred_measure", "pred_measure", and "loo".
When a loo object is supplied, additional classes from that object are
inherited (e.g. "psis_loo"). In addition to estimates and
pointwise, the list may contain:
diagnosticsPSIS diagnostics, including Pareto \(\hat{k}\) in
diagnostics$pareto_k. A value above the sample-size dependent threshold \(\min(1 - 1 / \log_{10}(S), 0.7)\), where \(S\) is the number of draws, suggests an unreliable LOO estimate for that observation. Theprint()method reports the threshold it used.log_weightsNormalized log importance weights used for LOO scoring.
psis_objectStored when
save_psis = TRUE; needed to add further measures withpred_measure()without recomputing weights.
Measure names carry a _loo suffix (e.g. elpd_loo, rps_loo).
Details
Three input patterns:
- Precomputed
looobject loo_pred_measure(loo = loo_fit, ...). Runloo()withsave_psis = TRUE.ylp+psis_objectPass both when you have already computed PSIS weights separately.
ylponlyPSIS weights are computed internally from
ylp.
If you corrected the loo object after PSIS, pass it as loo.
For example, loo_moment_match() or brms::reloo().
For distributional and point-prediction measures (rps, r2, etc.),
supply y, ypred, and/or mupred as for insample_pred_measure(). When
adding measures incrementally, call pred_measure() with predperf set to
an existing result; use save_psis = TRUE on the initial call so weights
are stored.
measure_info attribute
All *_pred_measure() and pred_measure() results include attribute
measure_info: a named list, keyed by bare measure name, recording what
model_compare() needs to know about each measure — loss (whether lower
values are better), diff_method (how the standard error of a difference is
obtained), and, where applicable, se_diff_fun and extra. When measures
are added incrementally with pred_measure(), the attribute is extended for
the newly computed measures.
Built-in measures take loss, diff_method, and se_diff_fun from the
package measure registry. Custom measures always get diff_method = "custom"
and take loss and se_diff_fun from custom_measure(). Without
loss = TRUE a custom measure is treated as a utility, so an undeclared
loss is compared and ranked in the wrong direction. See loo-glossary.
Examples
# \donttest{
if (requireNamespace("brms", quietly = TRUE)) {
fit <- brms::brm(
Reaction ~ Days, data = lme4::sleepstudy,
refresh = 0, chains = 2, iter = 1000
)
loo_fit <- loo::loo(fit, save_psis = TRUE)
loo_pred_measure(
loo = loo_fit,
y = fit$data$Reaction,
ypred = brms::posterior_predict(fit),
measures = c("rmse", "r2")
)
}
#> Compiling Stan program...
#> Start sampling
#> Error in .validate_numeric_matrix(mupred, arg = "mupred", ncol = length(y)): `mupred` must be a numeric matrix or array, not NULL.
# }