## ----setup, include=FALSE----------------------------------------------------- is_check_env <- nzchar(Sys.getenv("_R_CHECK_PACKAGE_NAME_")) .vig_tmp_root <- file.path(tempdir(), "ddesonn-vig-s1-s2") dir.create(.vig_tmp_root, recursive = TRUE, showWarnings = FALSE) options(DDESONN_OUTPUT_ROOT = .vig_tmp_root) Sys.setenv(DDESONN_ARTIFACTS_ROOT = .vig_tmp_root) # ============================================================ # FILE: vignettes/plot-controls_scenario1-2_single-run_scenarioA.Rmd # FULL WORKING — DDESONN Plot Controls — Scenario 1 & 2 — Single Run: Scenario A # # GOAL: # - Demonstrate TWO supported user-facing interfaces for plot control: # (1) Scenario 1: training_overrides knobs (minimal integration) # (2) Scenario 2: plot_controls umbrella (recommended) # # IMPORTANT (binary eval): # - To emit BOTH confusion matrix heatmaps (fixed + tuned), # users must set: # accuracy_plot = TRUE # accuracy_plot_mode = "both" # # IMPORTANT (performance/relevance): # - This vignette uses the *current* naming shown in your branch: # plot_controls$performance_relevance # and Scenario 1 uses the same key so the bridge can map it. # - No "boxplot" naming anywhere in config. # ============================================================ # ============================================================ # FIX: VIGNETTE PARSE-SAFE opts_chunk$set # ============================================================ # knitr options (SINGLE consolidated set) # ============================================================ knitr::opts_chunk$set( echo = TRUE, message = FALSE, warning = FALSE, fig.width = 6.5, fig.height = 4, dpi = 96, fig.retina = 1, out.width = "85%", fig.path = file.path(.vig_tmp_root, "figures", ""), cache.path = file.path(.vig_tmp_root, "cache", "") ) # ============================================================ # FIX: VIGNETTE-SAFE LOAD (no devtools::load_all) # ============================================================ if (!requireNamespace("DDESONN", quietly = TRUE)) { stop( "DDESONN must be installed to build this vignette. ", "Run: install.packages('DDESONN') (or your install flow) then rebuild vignettes.", call. = FALSE ) } library(DDESONN) ## ============================================================ ## SECTION: Recommended knitr figure options (consistency) ## ============================================================ ## For consistent ggplot title sizing across HTML/PDF output, ## keep these chunk options stable: ## - fig.width / fig.height set explicit device size (inches). ## - fig.retina controls display scaling (avoid implicit CSS). ## - out.width affects HTML scaling; keep constant across plots. # ============================================================ # Output roots for vignette artifacts # - Keep artifact paths short and outside vignette *_files trees. # - Disable persistent plot saving during R CMD check. # ============================================================ .dd_out_root <- file.path(.vig_tmp_root, "outputs") out1 <- file.path(.dd_out_root, "DDESONN_plots_scenarioA_s1") out2 <- file.path(.dd_out_root, "DDESONN_plots_scenarioA_s2") if (!is_check_env) { dir.create(out1, recursive = TRUE, showWarnings = FALSE) dir.create(out2, recursive = TRUE, showWarnings = FALSE) } # Make package helpers resolve to a short temp root. options(DDESONN_OUTPUT_ROOT = if (is_check_env) .vig_tmp_root else out1) Sys.setenv(DDESONN_ARTIFACTS_ROOT = if (is_check_env) .vig_tmp_root else out1) # ============================================================ # Helper: include_saved_plots() # - Uses knitr::image_uri() to embed PNGs as data: URIs # ============================================================ include_saved_plots <- function(output_root, header) { plot_dir <- ddesonn_plots_dir(output_root) if (!dir.exists(plot_dir)) { return(knitr::asis_output( paste0("\n\n[plot-controls:scenarioA] plots dir does not exist: ", plot_dir, "\n\n") )) } pngs <- list.files(plot_dir, pattern = "\\.png$", recursive = TRUE, full.names = TRUE) pngs <- pngs[nzchar(pngs)] pngs <- pngs[order(pngs)] if (!length(pngs)) { return(knitr::asis_output( paste0("\n\n[plot-controls:scenarioA] no PNGs found under: ", plot_dir, "\n\n") )) } out <- character() out <- c(out, paste0("\n\n## ", header, "\n\n")) for (p in pngs) { uri <- knitr::image_uri(p) out <- c(out, paste0('\n\n')) out <- c(out, "

\n\n") } knitr::asis_output(paste(out, collapse = "")) } ## What “both heatmaps” means (binary EvaluatePredictionsReport) ## (unchanged text section) set.seed(111) ext_dir <- system.file("extdata", package = "DDESONN") if (!nzchar(ext_dir)) stop("Could not find DDESONN extdata folder.", call. = FALSE) hf_path <- file.path(ext_dir, "heart_failure_clinical_records.csv") if (!file.exists(hf_path)) { csvs <- list.files(ext_dir, pattern = "\\.csv$", full.names = TRUE) if (!length(csvs)) stop("No .csv files found in extdata.", call. = FALSE) hf_path <- csvs[[1]] } df <- read.csv(hf_path) target_col <- if ("DEATH_EVENT" %in% names(df)) { "DEATH_EVENT" } else { cand <- names(df)[vapply(df, function(col) { v <- suppressWarnings(as.numeric(col)) if (all(is.na(v))) return(FALSE) u <- unique(v[is.finite(v)]) length(u) <= 2 && all(sort(u) %in% c(0, 1)) }, logical(1))] if (!length(cand)) stop("Could not infer a binary target column.", call. = FALSE) cand[[1]] } y_all <- matrix(as.integer(df[[target_col]]), ncol = 1) x_df <- df[, setdiff(names(df), target_col), drop = FALSE] x_all <- as.matrix(x_df) storage.mode(x_all) <- "double" n <- nrow(x_all) idx <- sample.int(n) n_train <- floor(0.70 * n) n_valid <- floor(0.15 * n) i_tr <- idx[1:n_train] i_va <- idx[(n_train + 1):(n_train + n_valid)] i_te <- idx[(n_train + n_valid + 1):n] x_train <- x_all[i_tr, , drop = FALSE] y_train <- y_all[i_tr, , drop = FALSE] x_valid <- x_all[i_va, , drop = FALSE] y_valid <- y_all[i_va, , drop = FALSE] x_test <- x_all[i_te, , drop = FALSE] y_test <- y_all[i_te, , drop = FALSE] # Scale train-only (no leakage) x_train_s <- scale(x_train) ctr <- attr(x_train_s, "scaled:center") scl <- attr(x_train_s, "scaled:scale") scl[!is.finite(scl) | scl == 0] <- 1 x_valid_s <- sweep(sweep(x_valid, 2, ctr, "-"), 2, scl, "/") x_test_s <- sweep(sweep(x_test, 2, ctr, "-"), 2, scl, "/") mx <- suppressWarnings(max(abs(x_train_s))) if (!is.finite(mx) || mx == 0) mx <- 1 x_train <- x_train_s / mx x_valid <- x_valid_s / mx x_test <- x_test_s / mx cat(sprintf("[split] train=%d valid=%d test=%d\n", nrow(x_train), nrow(x_valid), nrow(x_test))) ## ----scenarioA_s1_plots, results="asis", echo=FALSE--------------------------- options(DDESONN_OUTPUT_ROOT = if (is_check_env) .vig_tmp_root else out1) Sys.setenv(DDESONN_ARTIFACTS_ROOT = if (is_check_env) .vig_tmp_root else out1) res_scenarioA_s1 <- tryCatch( ddesonn_run( x = x_train, y = y_train, classification_mode = "binary", hidden_sizes = c(64, 32), seeds = 1L, do_ensemble = FALSE, validation = list(x = x_valid, y = y_valid), test = list(x = x_test, y = y_test), training_overrides = list( init_method = "he", optimizer = "adagrad", lr = 0.125, lambda = 0.00028, activation_functions = list(relu, relu, sigmoid), dropout_rates = list(0.10), loss_type = "CrossEntropy", validation_metrics = TRUE, num_epochs = 360, final_summary_decimals = 6L, per_epoch_plots = list( saveEnabled = !is_check_env, loss_curve = TRUE, probe_plots = TRUE, verbose = TRUE ), # ============================================================ # SECTION: performance_relevance (Scenario 1) # - This key is bridged into plot_controls$performance_relevance # ============================================================ performance_relevance = list( saveEnabled = !is_check_env, viewAllPlots = FALSE, performance_high_mean_plots = TRUE, performance_low_mean_plots = TRUE, relevance_high_mean_plots = TRUE, relevance_low_mean_plots = TRUE, verbose = TRUE ), evaluate_predictions_report_plots = list( accuracy_plot = TRUE, accuracy_plot_mode = "both", plot_roc = TRUE, plot_pr = TRUE, show_auprc = TRUE, viewAllPlots = FALSE, verbose = TRUE ) ) ), error = function(e) { cat("\n================ DDESONN ERROR — Scenario 1 | Scenario A =================\n") cat(conditionMessage(e), "\n\n") cat("-------------- TRACEBACK -----------------------\n") traceback(2) cat("================================================\n\n") stop(e) } ) if (!is_check_env) include_saved_plots(out1, "Scenario 1 — Saved plots") ## ----scenarioA_s2_run, donttest=TRUE------------------------------------------ options(DDESONN_OUTPUT_ROOT = if (is_check_env) .vig_tmp_root else out2) Sys.setenv(DDESONN_ARTIFACTS_ROOT = if (is_check_env) .vig_tmp_root else out2) res_scenarioA_s2 <- ddesonn_run( x = x_train, y = y_train, classification_mode = "binary", hidden_sizes = c(64, 32), seeds = 1L, do_ensemble = FALSE, validation = list(x = x_valid, y = y_valid), test = list(x = x_test, y = y_test), training_overrides = list( init_method = "he", optimizer = "adagrad", lr = 0.125, lambda = 0.00028, activation_functions = list(relu, relu, sigmoid), dropout_rates = list(0.10), loss_type = "CrossEntropy", validation_metrics = TRUE, num_epochs = 1, final_summary_decimals = 6L ), plot_controls = list( per_epoch = list( saveEnabled = !is_check_env, loss_curve = TRUE, probe_plots = TRUE, verbose = TRUE ), # ============================================================ # SECTION: performance_relevance (Scenario 2) # ============================================================ performance_relevance = list( saveEnabled = !is_check_env, viewAllPlots = FALSE, performance_high_mean_plots = TRUE, performance_low_mean_plots = TRUE, relevance_high_mean_plots = TRUE, relevance_low_mean_plots = TRUE, verbose = TRUE ), evaluate_report = list( accuracy_plot = TRUE, accuracy_plot_mode = "both", plot_roc = TRUE, plot_pr = TRUE, show_auprc = TRUE, viewAllPlots = FALSE, verbose = TRUE ) ) ) ## ----scenarioA_s2_plots, results="asis", echo=FALSE--------------------------- if (!is_check_env) include_saved_plots(out2, "Scenario 2 — Saved plots")