## ----setup, include = FALSE--------------------------------------------------- knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) library(lame) ## ----benchmark_self, eval = FALSE--------------------------------------------- # set.seed(1) # n <- 100 # Y <- matrix(rnorm(n*n), n, n); diag(Y) <- NA # rownames(Y) <- colnames(Y) <- paste0("a", sprintf("%03d", 1:n)) # # t_als <- system.time(ame_als(Y, R = 2, family = "normal", verbose = FALSE)) # t_mcmc <- system.time(ame(Y, R = 2, family = "normal", burn = 500, # nscan = 4000, odens = 25, verbose = FALSE, plot = FALSE)) # cat("ALS: ", round(t_als["elapsed"], 2), "s\n", # "MCMC: ", round(t_mcmc["elapsed"], 2), "s\n", # "ratio:", round(t_mcmc["elapsed"] / t_als["elapsed"], 1), "x\n") ## ----------------------------------------------------------------------------- set.seed(1) n <- 40 a <- rnorm(n, 0, 0.5); b <- rnorm(n, 0, 0.5) Xd <- matrix(rnorm(n * n), n, n) Y <- 0.5 + 0.8 * Xd + outer(a, b, "+") + matrix(rnorm(n * n), n, n) diag(Y) <- NA fit <- ame_als(Y, Xdyad = Xd, R = 1, family = "normal", verbose = FALSE) fit ## ----------------------------------------------------------------------------- devs <- sapply(0:3, function(r) ame_als(Y, Xdyad = Xd, R = r, family = "normal", verbose = FALSE)$deviance) data.frame(R = 0:3, deviance = round(devs, 1)) ## ----------------------------------------------------------------------------- set.seed(2) Yb <- 1 * (Y > median(Y, na.rm = TRUE)); diag(Yb) <- NA fb <- ame_als(Yb, Xdyad = Xd, R = 0, family = "binary", verbose = FALSE) coef(fb) ## ----------------------------------------------------------------------------- bt <- ame_als_bootstrap(fb, R = 100, type = "parametric", seed = 1, verbose = FALSE) summary(bt) ## ----als-vs-mcmc, fig.width = 7, fig.height = 3.5, fig.alt="Side-by-side coefficient plot comparing the ALS bootstrap and MCMC posterior on the same binary network. Each coefficient (intercept and the single dyadic covariate) has two horizontal intervals: one for the ALS bootstrap, one for the MCMC posterior. A dashed vertical line at zero marks the no-effect reference; intervals on the same side of zero and with overlapping range indicate the two estimators agree."---- # wrap Xd into a 3-D array with an explicit slice name so the ALS and MCMC # paths produce identical coefficient names (the auto-naming default differs # between the two engines) Xd_arr <- array(Xd, dim = c(nrow(Xd), ncol(Xd), 1), dimnames = list(NULL, NULL, "Xd")) # refit the binary ALS fit with the bootstrap attached so tidy() returns # bootstrap-based intervals fb_b <- ame_als(Yb, Xdyad = Xd_arr, R = 0, family = "binary", verbose = FALSE, bootstrap = 100, bootstrap_seed = 1) # fit the same data with MCMC using a short chain for a quick comparison fit_mcmc <- ame(Yb, Xdyad = Xd_arr, family = "binary", R = 0, burn = 30, nscan = 100, odens = 5, verbose = FALSE, plot = FALSE, gof = FALSE, seed = 1) # collect the common coefficient interval columns without relying on # vignette-time s3 dispatch through broom coef_interval_table <- function(fit) { est <- coef(fit) ci <- confint(fit) terms <- intersect(names(est), rownames(ci)) data.frame( term = terms, estimate = unname(est[terms]), conf.low = unname(ci[terms, 1]), conf.high = unname(ci[terms, 2]), row.names = NULL ) } als_tdy <- coef_interval_table(fb_b) mcmc_tdy <- coef_interval_table(fit_mcmc) df <- rbind( cbind(estimator = "ALS bootstrap", als_tdy[, c("term", "estimate", "conf.low", "conf.high")]), cbind(estimator = "MCMC posterior", mcmc_tdy[, c("term", "estimate", "conf.low", "conf.high")]) ) library(ggplot2) ggplot(df, aes(x = estimate, y = term, colour = estimator, shape = estimator)) + geom_vline(xintercept = 0, linetype = "dashed", colour = "grey60") + geom_pointrange(aes(xmin = conf.low, xmax = conf.high), position = position_dodge(width = 0.45), size = 0.5) + scale_colour_manual(values = c("ALS bootstrap" = "#0072B2", "MCMC posterior" = "#D55E00")) + scale_shape_manual(values = c("ALS bootstrap" = 16, "MCMC posterior" = 17)) + labs(x = "coefficient (probit scale)", y = NULL, colour = NULL, shape = NULL) + theme_bw() + theme(panel.border = element_blank(), axis.ticks = element_blank(), legend.position = "top") ## ----------------------------------------------------------------------------- set.seed(3) Yl <- replicate(5, { # intercept 0.4 + sender/receiver structure + noise (no dyadic # covariate is passed below, so only the intercept is recoverable) m <- 0.4 + outer(a, b, "+") + matrix(rnorm(n * n), n, n) diag(m) <- NA m }, simplify = FALSE) lf <- lame_als(Yl, R = 1, family = "normal", verbose = FALSE) coef(lf)