## ----setup, include=FALSE----------------------------------------------------- knitr::opts_chunk$set( echo = TRUE, message = FALSE, warning = FALSE, collapse = TRUE, comment = "#>" ) have_cmdstan <- requireNamespace("cmdstanr", quietly = TRUE) ## ----build-uniform, eval=TRUE------------------------------------------------- library(gdpar) spec_uniform <- amm_spec( p = 2L, dims = dimwise(a = ~ x1 + x2, b = ~ x1), W = W_basis(type = "polynomial", degree = 2) ) print(spec_uniform) ## ----build-override, eval=TRUE------------------------------------------------ spec_mixed <- amm_spec( p = 3L, dims = dimwise(a = ~ x1 + x2, b = ~ x1) |> override(k = 2L, a = ~ x1) |> override(k = 3L, b = NULL), W = W_basis(type = "polynomial", degree = 2) ) print(spec_mixed) ## ----build-chainable, eval=TRUE----------------------------------------------- spec_chain <- amm_build(p = 3L) |> amm_set_a_uniform(~ x1 + x2) |> amm_set_a(k = 2L, ~ x1) |> amm_set_b_uniform(~ x1) |> amm_set_b(k = 3L, NULL) |> amm_set_W(W_basis(type = "polynomial", degree = 2)) |> amm_set_x_vars(c("x1", "x2")) |> as_amm_spec() print(spec_chain) ## ----serialize, eval=TRUE----------------------------------------------------- tmp <- tempfile(fileext = ".gdpar") amm_save_spec(spec_uniform, tmp) cat(readLines(tmp), sep = "\n") spec_roundtrip <- amm_load_spec(tmp) identical(spec_uniform$level, spec_roundtrip$level) ## ----families, eval=TRUE------------------------------------------------------ fam_mv1 <- gdpar_family_multi("gaussian", p = 2L) print(fam_mv1) fam_mv2 <- gdpar_family_multi(gdpar_family("poisson"), p = 3L) print(fam_mv2) fam_mv3 <- gdpar_family_multi( list( gdpar_family("gaussian"), gdpar_family("gaussian") ), p = 2L ) print(fam_mv3) ## ----promotion-illustrative, eval=FALSE--------------------------------------- # fit <- gdpar( # formula = y ~ x1 + x2, # family = gdpar_family("gaussian"), # auto-promoted to gdpar_family_multi # amm = amm_spec(p = 2L, # dims = dimwise(a = ~ x1 + x2)), # data = df # ) # # Informational message emitted (class gdpar_family_promotion_message): # # "Auto-promoted univariate family 'gaussian' to gdpar_family_multi # # via gdpar_family_multi(family, p = 2) because amm$p > 1. # # Pass an explicit gdpar_family_multi to silence." ## ----W-materialize, eval=TRUE------------------------------------------------- wb_poly_p2 <- W_basis(type = "polynomial", degree = 2, p = 2L) print(wb_poly_p2) wb_poly_p2$block_indices wb_bs <- W_basis(type = "bspline", degree = 3, df = 4, p = 2L) print(wb_bs) wb_bs$block_indices ## ----W-per-k, eval=TRUE------------------------------------------------------- subs <- as_per_k(wb_poly_p2) length(subs) subs[[1L]]$dim subs[[2L]]$dim ## ----outcome-illustrative, eval=FALSE----------------------------------------- # df$y <- cbind(y1, y2) # matrix column added to existing df # # or # df <- data.frame(x1 = ..., x2 = ...) # df$y <- y_matrix # y_matrix is a numeric matrix n x p ## ----gdpar-illustrative, eval=FALSE------------------------------------------- # fit <- gdpar( # formula = y ~ x1 + x2, # family = gdpar_family_multi("gaussian", p = 2L), # amm = spec_uniform, # data = df, # df$y is n x 2 matrix column # parametrization = "auto", # runs per-coord preflight # parametrization_aggregation = "any_ncp", # default; conservative # iter_warmup = 1000L, # iter_sampling = 1000L, # chains = 4L, # seed = 42L # ) ## ----preflight-shape, eval=FALSE---------------------------------------------- # # After the fit: # rep <- fit$parametrization$report # gdpar_preflight_report # print(rep) # default: level = "global" # print(rep, level = "dim") # per-coordinate detail # print(rep, level = "both") # global + per-coord # # preflight_per_dim(rep) # tidy data.frame, one row per (component, dim) # preflight_global_decision(rep) # one row per component # as.data.frame(rep) # same as preflight_per_dim() # summary(rep) # named list with aggregates ## ----predict-illustrative, eval=FALSE----------------------------------------- # arr <- predict(fit) # type = "theta_i", summary = "draws" # dim(arr) # (S, n, p) # # arr_resp <- predict(fit, type = "response") # per-coord inverse link applied # arr_se <- predict(fit, summary = "mean_se") # list of p data.frames # arr_q <- predict(fit, summary = "quantiles") # list of p data.frames # # arr_new <- predict(fit, newdata = df_new) # reconstruct from posterior draws ## ----coef-illustrative, eval=FALSE-------------------------------------------- # cf <- coef(fit) # print(cf) # level = "global", default # print(cf, level = "coord") # per-coord means only # print(cf, level = "full") # per-coord with full quantiles # # summary(cf) # aggregated counts + theta_ref mean # format(cf) # one-line representation ## ----asdf-illustrative, eval=FALSE-------------------------------------------- # df_coef <- as.data.frame(coef(fit)) # head(df_coef) # # # Using dplyr with explicit namespace to avoid library() in vignettes: # df_coef |> # dplyr::filter(component == "a") |> # dplyr::group_by(k) |> # dplyr::summarise(mean_abs = mean(abs(mean)), # max_q95 = max(q95)) ## ----smoke-data, eval=have_cmdstan-------------------------------------------- library(gdpar) set.seed(42L) n <- 300L df <- data.frame( x1 = rnorm(n), x2 = rnorm(n) ) # True theta_ref = c(0.5, -0.5), beta_a 2x2, sigma_y = 0.3 per coord true_theta_ref <- c(0.5, -0.5) true_beta_a <- matrix(c(0.8, -0.6, 0.4, 0.7), nrow = 2L, byrow = TRUE) y_mat <- matrix(NA_real_, nrow = n, ncol = 2L) for (k in seq_len(2L)) { y_mat[, k] <- true_theta_ref[k] + true_beta_a[k, 1L] * df$x1 + true_beta_a[k, 2L] * df$x2 + rnorm(n, sd = 0.3) } df$y <- y_mat str(df) ## ----smoke-spec, eval=have_cmdstan-------------------------------------------- spec <- amm_spec( p = 2L, dims = dimwise(a = ~ x1 + x2) ) print(spec) ## ----smoke-fit, eval=have_cmdstan--------------------------------------------- fit <- gdpar( formula = y ~ x1 + x2, family = gdpar_family("gaussian"), # auto-promoted amm = spec, data = df, parametrization = "auto", parametrization_aggregation = "any_ncp", iter_warmup = 300L, iter_sampling = 300L, chains = 2L, refresh = 0L, verbose = FALSE, seed = 42L ) print(fit) ## ----smoke-params, eval=have_cmdstan------------------------------------------ fit$parametrization$cp_a fit$parametrization$cp_W fit$parametrization$cp_a_per_k fit$parametrization$cp_W_per_k ## ----smoke-preflight, eval=have_cmdstan--------------------------------------- rep <- fit$parametrization$report print(rep, level = "both") ## ----smoke-coef, eval=have_cmdstan-------------------------------------------- cf <- coef(fit) print(cf, level = "coord") df_coef <- as.data.frame(cf) head(df_coef, 8L) ## ----smoke-predict, eval=have_cmdstan----------------------------------------- q_list <- predict(fit, type = "response", summary = "quantiles") length(q_list) head(q_list$dim_1, 4L) head(q_list$dim_2, 4L) ## ----smoke-diag, eval=have_cmdstan-------------------------------------------- diagnostics(fit) ## ----reporter-csv, eval=FALSE------------------------------------------------- # csv_path <- system.file( # "benchmarks", "results", "cp_ncp_hit_rate_multi.csv", # package = "gdpar" # ) # results <- utils::read.csv(csv_path, stringsAsFactors = FALSE) # str(results) ## ----reporter-agg, eval=FALSE------------------------------------------------- # sub <- results[!is.na(results$regime_truth) & !is.na(results$hit), ] # hits_comp <- aggregate(hit ~ component, data = sub, # FUN = function(x) mean(as.logical(x))) # hits_sc <- aggregate(hit ~ scenario, data = sub, # FUN = function(x) mean(as.logical(x))) # print(hits_comp) # print(hits_sc) ## ----reporter-plot, eval=FALSE------------------------------------------------ # # Using ggplot2 with explicit namespace to avoid library() in vignettes; # # the actual reporter at inst/benchmarks/scripts/report_hit_rate_multi.R # # follows the same convention. # results$hit_label <- ifelse( # is.na(results$hit), "borderline", # ifelse(as.logical(results$hit), "hit", "miss") # ) # ggplot2::ggplot( # results, # ggplot2::aes(x = factor(k), fill = hit_label) # ) + # ggplot2::geom_bar(width = 0.7) + # ggplot2::facet_grid(scenario ~ component, scales = "free_x", # space = "free_x") + # ggplot2::scale_fill_manual(values = c( # "hit" = "#2c7bb6", # "miss" = "#d7191c", # "borderline" = "#fdae61" # )) + # ggplot2::labs(x = "k (coordinate)", y = "count", fill = "verdict") + # ggplot2::theme_minimal() ## ----psis-loo-subject, eval = FALSE------------------------------------------- # fit <- gdpar( # formula = y ~ x1 + x2, # family = gdpar_family_multi("gaussian", p = 2L), # amm = amm_spec(p = 2L, dims = dimwise(a = ~ x1 + x2, b = NULL)), # data = train_df, # refresh = 0L, seed = 42L # ) # lo <- gdpar_loo(fit) # print(lo) # # elpd_loo, se_elpd_loo, Pareto-k summary as in loo::loo ## ----psis-loo-cell, eval = FALSE---------------------------------------------- # lo_cell <- gdpar_loo(fit, aggregation = "cell") # sum(lo_cell$diagnostics$pareto_k > 0.7) # per-cell concentration