Obtains optimal stacking weights given leave-one-out predictive densities for each candidate model.
Arguments
- log_loopd
an \(n \times M\) matrix with \(i\)-th row containing the leave-one-out predictive densities for the \(i\)-th data point for the \(M\) candidate models.
- solver
specifies the solver to use for obtaining optimal weights. Default is
"CLARABEL". Internally callsCVXR::psolve().- verbose
if
TRUE, prints output of optimization routine.
Value
A list with elements:
weightsoptimal stacking weights as a numeric vector of length \(M\) (
NAif no solver succeeded, see Details).statussolver status, returns
"optimal"if solver succeeded, and"failed"if no solver succeeded.solvername of the solver used (
"none"if no solver succeeded).detailsa list with the installed CVXR solvers (
installed), the requested solver(s) (requested) and those of them not installed (missing.requested), the order in which the solvers were tried (search.order), a data frame of the attempts with the status or error of each solver (attempts), and whether the fallbackloo::stacking_weights()was used (fallback).
Details
The weights maximize the log score of the stacked leave-one-out
predictive densities (Yao et al. 2018) over the simplex, using the CVXR
solvers in the order given above. If none of them reaches an optimal
solution, loo::stacking_weights() is used as a fallback when the
package loo is installed; otherwise the weights are returned as
NA with status "failed".
References
Yao Y, Vehtari A, Simpson D, Gelman A (2018). "Using Stacking to Average Bayesian Predictive Distributions (with Discussion)." Bayesian Analysis, 13(3), 917-1007. doi:10.1214/17-BA1091 .
Author
Soumyakanti Pan span18@ucla.edu,
Sudipto Banerjee sudipto@ucla.edu
Examples
set.seed(1234)
data(simSpatial)
dat <- simSpatial[1:100, ]
cand.mod <- candidateModels(list(phi = c(2, 4, 6),
nu = c(1, 1.5, 1.75),
noise_sp_ratio = c(0.1)), "cartesian")
mod1 <- spLMstack(y_gauss ~ x1 + x2, data = dat,
coords = as.matrix(dat[, c("s1", "s2")]),
cor.fn = "matern",
candidate.models = cand.mod,
n.samples = 1000, loopd.method = "exact",
parallel = FALSE, verbose = TRUE)
#>
#> STACKING WEIGHTS:
#>
#> | phi | nu | noise_sp_ratio | weight |
#> +---------+-----+------+----------------+--------+
#> | Model 1 | 2| 1.00| 0.1| 0 |
#> | Model 2 | 4| 1.00| 0.1| 0 |
#> | Model 3 | 6| 1.00| 0.1| 0 |
#> | Model 4 | 2| 1.50| 0.1| 0 |
#> | Model 5 | 4| 1.50| 0.1| 0 |
#> | Model 6 | 6| 1.50| 0.1| 0 |
#> | Model 7 | 2| 1.75| 0.1| 0 |
#> | Model 8 | 4| 1.75| 0.1| 1 |
#> | Model 9 | 6| 1.75| 0.1| 0 |
#> +---------+-----+------+----------------+--------+
#>
loopd_mat <- do.call('cbind', mod1$loopd)
w_hat <- get_stacking_weights(loopd_mat)
#> --------------------------------------------------
#> Solver diagnostics:
#> Installed solvers: CLARABEL, SCS, OSQP, HIGHS
#> Requested solver: DEFAULT (CLARABEL -> ECOS -> SCS)
#> Solver search order: CLARABEL -> SCS
#> --------------------------------------------------
#> ────────────────────────────────── CVXR v1.9.2 ─────────────────────────────────
#> ℹ Problem: 1 variable, 2 constraints (DCP)
#> ℹ Compilation: "CLARABEL" via CVXR::FlipObjective -> CVXR::Dcp2Cone -> CVXR::CvxAttr2Constr -> CVXR::ConeMatrixStuffing -> CVXR::Clarabel_Solver
#> ℹ Compile time: 0.273s
#> ─────────────────────────────── Numerical solver ───────────────────────────────
#> ──────────────────────────────────── Summary ───────────────────────────────────
#> ✔ Status: optimal
#> ✔ Optimal value: -68.4263
#> ℹ Compile time: 0.273s
#> ℹ Solver time: 0.055s
print(round(w_hat$weights, 4))
#> [1] 0 0 0 0 0 0 0 1 0
print(w_hat$solver)
#> [1] "CVXR:CLARABEL"
print(w_hat$status)
#> [1] "optimal"
