tensor_predictors/sim/sim_ising_perft.R

611 lines
22 KiB
R

library(microbenchmark)
library(tensorPredictors)
setwd("~/Work/tensorPredictors/sim/")
base.name <- "sim_ising_perft"
# Number of replications, sufficient for the performance test
reps <- 5
# Sets the dimensions to be tested for runtime per method
configs <- list(
exact = list( # Exact method
dim = 1:24,
use_MC = FALSE,
nr_threads = 1L # ignored in this case, but no special case neded
),
MC = list( # Monte-Carlo Estimate
dim = c(1:20, (3:13) * 10),
use_MC = TRUE,
nr_threads = 1L # default nr. of threads
),
MC8 = list( # Monte-Carlo Estimate using 8 threads
dim = c(1:20, (3:13) * 10),
use_MC = TRUE,
nr_threads = 8L # my machines nr of (virtual) cores
)
)
# Simple function creating a parameter vector to be passed to `ising_m2`, the values
# are irrelevant while its own execution time is (more or less) neglectable
params <- function(dim) double(dim * (dim + 1L) / 2L)
# Build expressions to be past to `microbenchmark` for performance testing
expressions <- Reduce(c, Map(function(method) {
config <- configs[[method]]
Map(function(dim) {
as.call(list(quote(ising_m2), params = substitute(params(dim), list(dim = dim)),
use_MC = config$use_MC, nr_threads = config$nr_threads))
}, config$dim)
}, names(configs)))
# Performance tests
perft.results <- microbenchmark(list = expressions, times = reps)
# Convert performance test results to data frame for further processing
(perft <- summary(perft.results))
# Ploting the performance simulation
################################################################################
### TODO: Fix plotting ###
################################################################################
if (FALSE) {
with(sim, {
par(mfrow = c(2, 2), mar = c(5, 4, 4, 4) + 0.1)
# Effect of Nr. of samples
plot(range(nr_samples), range(mse - sd, mse + sd),
type = "n", bty = "n", log = "xy", yaxt = "n",
xlab = "Nr. Samples", ylab = "MSE",
main = "Sample Size Effect (MSE)")
groups <- split(sim, warmup)
for (i in seq_along(groups)) {
with(groups[[i]], {
lines(nr_samples, mse, col = i, lwd = 2, type = "b", pch = 16)
lines(nr_samples, mse - sd, col = i, lty = 2)
lines(nr_samples, mse + sd, col = i, lty = 2)
})
}
right <- nr_samples == max(nr_samples)
axis(4, at = mse[right], labels = warmup[right], lwd = 0, lwd.ticks = 1, line = -1.5)
mtext("Warmup", side = 4, line = 1.5, at = exp(mean(range(log(mse[right])))))
y.pow <- -10:-1
axis(2, at = c(1, 10^y.pow),
labels = c(1, sapply(y.pow, function(pow) eval(substitute(expression(10^i), list(i = pow))))))
# Effect warmup length
plot(range(warmup + 1), range(mse - sd, mse + sd),
type = "n", bty = "n", log = "xy", xaxt = "n", yaxt = "n",
xlab = "Warmup", ylab = "MSE",
main = "Warmup Effect (MSE)")
axis(1, warmup + 1, labels = as.integer(warmup))
groups <- split(sim, nr_samples)
for (i in seq_along(groups)) {
with(groups[[i]], {
lines(warmup + 1, mse, col = i, lwd = 2, type = "b", pch = 16)
lines(warmup + 1, mse - sd, col = i, lty = 2)
lines(warmup + 1, mse + sd, col = i, lty = 2)
})
}
right <- warmup == max(warmup)
axis(4, at = mse[right], labels = nr_samples[right], lwd = 0, lwd.ticks = 1, line = -1.5)
mtext("Nr. Samples", side = 4, line = 1.5, at = exp(mean(range(log(mse[right])))))
axis(2, at = c(1, 10^y.pow),
labels = c(1, sapply(y.pow, function(pow) eval(substitute(expression(10^i), list(i = pow))))))
# Effect of Nr. of samples
plot(range(nr_samples), range(merr),
type = "n", bty = "n", log = "xy", yaxt = "n",
xlab = "Nr. Samples", ylab = "Max Abs Error Mean",
main = "Sample Size Effect (Abs Error)")
groups <- split(sim, warmup)
for (i in seq_along(groups)) {
with(groups[[i]], {
lines(nr_samples, merr, col = i, lwd = 2, type = "b", pch = 16)
})
}
right <- nr_samples == max(nr_samples)
axis(4, at = merr[right], labels = warmup[right], lwd = 0, lwd.ticks = 1, line = -1.5)
mtext("Warmup", side = 4, line = 1.5, at = exp(mean(range(log(merr[right])))))
y.pow <- -10:-1
axis(2, at = c(1, 10^y.pow),
labels = c(1, sapply(y.pow, function(pow) eval(substitute(expression(10^i), list(i = pow))))))
# Effect of warmup length
plot(range(warmup + 1), range(merr),
type = "n", bty = "n", log = "xy", xaxt = "n", yaxt = "n",
xlab = "Warmup", ylab = "Max Abs Error Mean",
main = "Warmup Effect (Abs Error)")
axis(1, warmup + 1, labels = as.integer(warmup))
groups <- split(sim, nr_samples)
for (i in seq_along(groups)) {
with(groups[[i]], {
lines(warmup + 1, merr, col = i, lwd = 2, type = "b", pch = 16)
})
}
right <- warmup == max(warmup)
axis(4, at = merr[right], labels = nr_samples[right], lwd = 0, lwd.ticks = 1, line = -1.5)
mtext("Nr. Samples", side = 4, line = 1.5, at = exp(mean(range(log(merr[right])))))
axis(2, at = c(1, 10^y.pow),
labels = c(1, sapply(y.pow, function(pow) eval(substitute(expression(10^i), list(i = pow))))))
})
# Add common title
mtext(main, side = 3, line = -2, outer = TRUE, font = 2, cex = 1.5)
}
# test_unscaled_prob <- function() {
# test <- function(p) {
# y <- sample.int(2, p, replace = TRUE) - 1L
# theta <- vech(matrix(rnorm(p^2), p))
# C <- ising_m2(y, theta)
# R <- exp(sum(vech(outer(y, y)) * theta))
# if (all.equal(C, R) == TRUE) {
# cat("\033[92mSUCCESS: ")
# } else {
# cat("\033[91mFAILED: ")
# }
# cat(sprintf("p = %d, C = %e, R = %e\n", p, C, R))
# cat(" ", paste0(format(seq_along(y) - 1), collapse = " "), "\n")
# cat(" y = ", paste0(c(".", "1")[y + 1], collapse = " "))
# cat("\033[0m\n\n")
# }
# devtools::load_all()
# for (p in c(1, 10, 30:35, 62:66, 70, 128, 130)) {
# test(p)
# }
# }
# test_ising_sample <- function() {
# test <- function(p) {
# # theta <- vech(matrix(rnorm(p^2), p))
# # theta <- vech(matrix(0, p, p))
# theta <- -0.01 * vech(1 - diag(p))
# # theta <- vech(0.2 * diag(p))
# sample <- ising_sample(11, theta)
# print.table(sample, zero.print = ".")
# print(mean(sample))
# }
# devtools::load_all()
# for (p in c(1, 10, 30:35, 62:66, 70, 128, 130)) {
# test(p)
# }
# }
# test_ising_partition_func_MC <- function() {
# test <- function(p) {
# # theta <- vech(matrix(rnorm(p^2), p))
# # theta <- vech(matrix(0, p, p))
# theta <- -0.01 * vech(1 - diag(p))
# time_gmlm <- system.time(val_gmlm <- ising_partition_func_MC(theta))
# time_gmlm <- round(1000 * time_gmlm[["elapsed"]])
# if (p < 21) {
# time_mvb <- system.time(val_mvb <- 1 / mvbernoulli::ising_prob0(theta))
# time_mvb <- round(1000 * time_mvb[["elapsed"]])
# } else {
# val_mvb <- NaN
# time_mvb <- -1
# }
# cat(sprintf(
# "dim = %d\n GMLM: time = %4d ms, val = %.4e\n MVB: time = %4d ms, val = %.4e\n",
# p, time_gmlm, val_gmlm, time_mvb, val_mvb))
# }
# devtools::load_all()
# system.time(
# # for (p in c(1, 10, 20, 30:35, 64, 70, 128, 130)) {
# for (p in c(1, 10, 20, 30:35, 64)) {
# test(p)
# }
# )
# }
# # test_ising_partition_func_MC()
# validate_ising_partition_func_MC <- function(theta_func) {
# est_var <- function(dim) {
# theta <- theta_func(dim)
# time <- system.time(rep <- replicate(100, ising_partition_func_MC(theta)))
# cat(sprintf("dim = %d, time = %.2e s, mean = %.2e, std.dev = %.2e\n",
# dim, time[["elapsed"]], mean(rep), sd(rep)))
# }
# for (dim in 10 * (1:13)) {
# est_var(dim)
# }
# }
# # validate_ising_partition_func_MC(function(dim) { vech(matrix(rnorm(dim^2), dim)) })
# # validate_ising_partition_func_MC(function(dim) { vech(matrix(0, dim, dim)) })
# # validate_ising_partition_func_MC(function(dim) { -0.01 * vech(1 - diag(dim)) })
# # validate_ising_partition_func_MC(function(dim) { vech(0.2 * diag(dim)) })
# test_ising_partition_func_exact <- function(theta_func) {
# test <- function(dim) {
# theta <- theta_func(dim)
# reps <- if (dim < 10) 100 else 10
# time <- system.time(replicate(reps, ising_partition_func_exact(theta)))
# time <- time[["elapsed"]] / reps
# cat(sprintf("dim = %d, time = %.2e s\n", dim, time))
# }
# for (dim in 1:20) {
# test(dim)
# }
# }
# test_ising_partition_func_exact(function(dim) { vech(matrix(rnorm(dim^2), dim)) })
# ### Performance Measurement/Comparison
# local({
# perft_exact <- local({
# dims <- 2:22
# cat("Exact perft:\n")
# times <- sapply(dims, function(dim) {
# reps <- if (dim < 10) 1000 else if (dim < 15) 100 else if (dim < 20) 10 else 4
# theta <- vech(matrix(rnorm(dim^2), dim))
# time <- system.time(replicate(reps,
# ising_m2(theta, use_MC = FALSE)
# ))
# time <- time[["elapsed"]] / reps
# cat(sprintf(" dim = %3d, reps = %3d, time per rep = %.2e s\n", dim, reps, time))
# time
# })
# list(dims = dims, times = times)
# })
# perft_MC <- local({
# dims <- c(2:21, 30, 40, 70, 100)
# cat("Monte-Carlo perft:\n")
# times <- sapply(dims, function(dim) {
# reps <- if (dim < 20) 25 else if (dim < 40) 10 else 4
# theta <- vech(matrix(rnorm(dim^2), dim))
# time <- system.time(replicate(reps,
# ising_m2(theta, use_MC = TRUE)
# ))
# time <- time[["elapsed"]] / reps
# cat(sprintf(" dim = %3d, reps = %3d, time per rep = %.2e s\n", dim, reps, time))
# time
# })
# list(dims = dims, times = times)
# })
# perft_MC_thrd <- local({
# dims <- c(2:21, 30, 40, 70, 100)
# cat("Monte-Carlo Multi-Threaded perft:\n")
# times <- sapply(dims, function(dim) {
# reps <- if (dim < 15) 25 else if (dim < 40) 10 else 4
# theta <- vech(matrix(rnorm(dim^2), dim))
# time <- system.time(replicate(reps,
# ising_m2(theta, use_MC = TRUE, nr_threads = 6L)
# ))
# time <- time[["elapsed"]] / reps
# cat(sprintf(" dim = %3d, reps = %3d, time per rep = %.2e s\n", dim, reps, time))
# time
# })
# list(dims = dims, times = times)
# })
# # Plot results
# par(mfrow = c(1, 1))
# plot(
# range(c(perft_MC_thrd$dims, perft_MC$dims, perft_exact$dims)),
# range(c(perft_MC_thrd$times, perft_MC$times, perft_exact$times)),
# type = "n", log = "xy", xlab = "Dimension p", ylab = "Time", xaxt = "n", yaxt = "n",
# main = "Performance Comparison"
# )
# # Add custom Y-axis
# x.major.ticks <- as.vector(outer(c(2, 5, 10), 10^(0:5)))
# x.minor.ticks <- as.vector(outer(2:10, 10^(0:5)))
# axis(1, x.major.ticks, labels = as.integer(x.major.ticks))
# axis(1, x.minor.ticks, labels = NA, tcl = -0.25, lwd = 0, lwd.ticks = 1)
# abline(v = x.major.ticks, col = "gray", lty = "dashed")
# abline(v = x.minor.ticks, col = "lightgray", lty = "dotted")
# # Add custom Y-axis
# y.major.ticks <- c(10^(-9:1), 60, 600, 3600)
# y.labels <- c(
# expression(paste(n, s)),
# expression(paste(10, n, s)),
# expression(paste(100, n, s)),
# expression(paste(mu, s)),
# expression(paste(10, mu, s)),
# expression(paste(100, mu, s)),
# expression(paste(1, m, s)),
# expression(paste(10, m, s)),
# expression(paste(100, m, s)),
# expression(paste(1, s)),
# expression(paste(10, s)),
# expression(paste(1, min)),
# expression(paste(10, min)),
# expression(paste(1, h))
# )
# y.minor.ticks <- c(as.vector(outer((1:10), 10^(-10:0))), 10 * (1:6), 60 * (2:10), 600 * (2:6))
# axis(2, at = y.major.ticks, labels = y.labels)
# axis(2, at = y.minor.ticks, labels = NA, tcl = -0.25, lwd = 0, lwd.ticks = 1)
# abline(h = y.major.ticks, col = "gray", lty = "dashed")
# abline(h = y.minor.ticks, col = "lightgray", lty = "dotted")
# legend("bottomright", col = c("red", "darkgreen", "blue"), lty = c(1, 1, 1),
# bg = "white",
# legend = c(
# expression(paste("Exact ", O(2^p))),
# expression(paste("MC ", O(p^2))),
# expression(paste("MC Thrd ", O(p^2)))
# )
# )
# with(perft_exact, {
# points(dims, times, pch = 16, col = "red")
# with(list(dims = tail(dims, -4), times = tail(times, -4)), {
# lines(dims, exp(predict(lm(log(times) ~ dims))), col = "red")
# })
# })
# with(perft_MC, {
# points(dims, times, pch = 16, col = "darkgreen")
# lines(dims, predict(lm(sqrt(times) ~ dims))^2, col = "darkgreen")
# })
# with(perft_MC_thrd, {
# points(dims, times, pch = 16, col = "blue")
# lines(dims, predict(lm(sqrt(times) ~ dims))^2, col = "blue")
# })
# })
# # dim <- 10
# # theta <- vech(matrix(rnorm(dim^2, 0, 1), dim, dim))
# # nr_threads <- 6L
# # (m2.exact <- ising_m2(theta, use_MC = FALSE))
# # (m2.MC <- ising_m2(theta, use_MC = TRUE))
# # (m2.MC_thrd <- ising_m2(theta, use_MC = TRUE, nr_threads = nr_threads))
# # tcrossprod(ising_sample(1e4, theta)) / 1e4
# local({
# dim <- 20
# theta <- vech(matrix(rnorm(dim^2, 0, 1), dim, dim))
# A <- matrix(NA_real_, dim, dim)
# A[lower.tri(A, diag = TRUE)] <- theta
# A[lower.tri(A)] <- A[lower.tri(A)] / 2
# A[upper.tri(A)] <- t(A)[upper.tri(A)]
# nr_threads <- 6L
# time.exact <- system.time(m2.exact <- ising_m2(theta, use_MC = FALSE))
# time.MC <- system.time(m2.MC <- ising_m2(theta, use_MC = TRUE))
# time.MC_thrd <- system.time(m2.MC_thrd <- ising_m2(A, use_MC = TRUE, nr_threads = nr_threads))
# time.sample <- system.time(m2.sample <- tcrossprod(ising_sample(1e4, theta)) / 1e4)
# range <- range(m2.exact, m2.MC, m2.MC_thrd)
# par(mfrow = c(2, 2))
# matrixImage(m2.exact, main = sprintf("M2 Exact (time %.2f s)", time.exact[["elapsed"]]), zlim = range)
# matrixImage(m2.MC, main = sprintf("M2 MC (time %.2f s)", time.MC[["elapsed"]]), zlim = range)
# matrixImage(m2.MC_thrd, main = sprintf("M2 MC (%d threads, time %.2f s)", nr_threads, time.MC_thrd[["elapsed"]]), zlim = range)
# matrixImage(m2.sample, main = sprintf("E_n(X X') (time %.2f s)", time.sample[["elapsed"]]), zlim = range)
# # matrixImage(abs(m2.exact - m2.MC), main = "Abs. Error (Exact to MC)", zlim = c(-1, 1))
# })
# # Simulation
# dims <- c(5, 10, 15, 20)
# config.grid <- expand.grid(
# nr_samples = c(10, 100, 1000, 10000),
# warmup = c(0, 2, 10, 100),
# dim = dims
# )
# params <- Map(function(dim) vech(matrix(rnorm(dim^2, 0, 1), dim, dim)), dims)
# names(params) <- dims
# m2s.exact <- Map(ising_m2, params, use_MC = FALSE)
# sim <- data.frame(t(apply(config.grid, 1, function(conf) {
# # get same theta for every dimension
# theta <- params[[as.character(conf["dim"])]]
# m2.exact <- m2s.exact[[as.character(conf["dim"])]]
# rep <- replicate(25, {
# time <- system.time(
# m2.MC <- ising_m2(theta, nr_samples = conf["nr_samples"], warmup = conf["warmup"], use_MC = TRUE)
# )
# c(mse = mean((m2.exact - m2.MC)^2), err = max(abs(m2.exact - m2.MC)), time = time[["elapsed"]])
# })
# cat(sprintf("dim = %d, nr_samples = %6d, warmup = %6d, mse = %.4f\n",
# conf["dim"], conf["nr_samples"], conf["warmup"], mean(rep["mse", ])))
# c(
# conf,
# mse = mean(rep["mse", ]), sd = sd(rep["mse", ]), merr = mean(rep["err", ]),
# time = mean(rep["time", ])
# )
# })))
# plot.sim <- function(sim, main) {
# with(sim, {
# par(mfrow = c(2, 2), mar = c(5, 4, 4, 4) + 0.1)
# # Effect of Nr. of samples
# plot(range(nr_samples), range(mse - sd, mse + sd),
# type = "n", bty = "n", log = "xy", yaxt = "n",
# xlab = "Nr. Samples", ylab = "MSE",
# main = "Sample Size Effect (MSE)")
# groups <- split(sim, warmup)
# for (i in seq_along(groups)) {
# with(groups[[i]], {
# lines(nr_samples, mse, col = i, lwd = 2, type = "b", pch = 16)
# lines(nr_samples, mse - sd, col = i, lty = 2)
# lines(nr_samples, mse + sd, col = i, lty = 2)
# })
# }
# right <- nr_samples == max(nr_samples)
# axis(4, at = mse[right], labels = warmup[right], lwd = 0, lwd.ticks = 1, line = -1.5)
# mtext("Warmup", side = 4, line = 1.5, at = exp(mean(range(log(mse[right])))))
# y.pow <- -10:-1
# axis(2, at = c(1, 10^y.pow),
# labels = c(1, sapply(y.pow, function(pow) eval(substitute(expression(10^i), list(i = pow))))))
# # Effect warmup length
# plot(range(warmup + 1), range(mse - sd, mse + sd),
# type = "n", bty = "n", log = "xy", xaxt = "n", yaxt = "n",
# xlab = "Warmup", ylab = "MSE",
# main = "Warmup Effect (MSE)")
# axis(1, warmup + 1, labels = as.integer(warmup))
# groups <- split(sim, nr_samples)
# for (i in seq_along(groups)) {
# with(groups[[i]], {
# lines(warmup + 1, mse, col = i, lwd = 2, type = "b", pch = 16)
# lines(warmup + 1, mse - sd, col = i, lty = 2)
# lines(warmup + 1, mse + sd, col = i, lty = 2)
# })
# }
# right <- warmup == max(warmup)
# axis(4, at = mse[right], labels = nr_samples[right], lwd = 0, lwd.ticks = 1, line = -1.5)
# mtext("Nr. Samples", side = 4, line = 1.5, at = exp(mean(range(log(mse[right])))))
# axis(2, at = c(1, 10^y.pow),
# labels = c(1, sapply(y.pow, function(pow) eval(substitute(expression(10^i), list(i = pow))))))
# # Effect of Nr. of samples
# plot(range(nr_samples), range(merr),
# type = "n", bty = "n", log = "xy", yaxt = "n",
# xlab = "Nr. Samples", ylab = "Max Abs Error Mean",
# main = "Sample Size Effect (Abs Error)")
# groups <- split(sim, warmup)
# for (i in seq_along(groups)) {
# with(groups[[i]], {
# lines(nr_samples, merr, col = i, lwd = 2, type = "b", pch = 16)
# })
# }
# right <- nr_samples == max(nr_samples)
# axis(4, at = merr[right], labels = warmup[right], lwd = 0, lwd.ticks = 1, line = -1.5)
# mtext("Warmup", side = 4, line = 1.5, at = exp(mean(range(log(merr[right])))))
# y.pow <- -10:-1
# axis(2, at = c(1, 10^y.pow),
# labels = c(1, sapply(y.pow, function(pow) eval(substitute(expression(10^i), list(i = pow))))))
# # Effect of warmup length
# plot(range(warmup + 1), range(merr),
# type = "n", bty = "n", log = "xy", xaxt = "n", yaxt = "n",
# xlab = "Warmup", ylab = "Max Abs Error Mean",
# main = "Warmup Effect (Abs Error)")
# axis(1, warmup + 1, labels = as.integer(warmup))
# groups <- split(sim, nr_samples)
# for (i in seq_along(groups)) {
# with(groups[[i]], {
# lines(warmup + 1, merr, col = i, lwd = 2, type = "b", pch = 16)
# })
# }
# right <- warmup == max(warmup)
# axis(4, at = merr[right], labels = nr_samples[right], lwd = 0, lwd.ticks = 1, line = -1.5)
# mtext("Nr. Samples", side = 4, line = 1.5, at = exp(mean(range(log(merr[right])))))
# axis(2, at = c(1, 10^y.pow),
# labels = c(1, sapply(y.pow, function(pow) eval(substitute(expression(10^i), list(i = pow))))))
# })
# # Add common title
# mtext(main, side = 3, line = -2, outer = TRUE, font = 2, cex = 1.5)
# }
# plot.sim(subset(sim, sim$dim == 5), main = "Dim = 5")
# plot.sim(subset(sim, sim$dim == 10), main = "Dim = 10")
# plot.sim(subset(sim, sim$dim == 15), main = "Dim = 15")
# plot.sim(subset(sim, sim$dim == 20), main = "Dim = 20")
# dim <- 120
# params <- rnorm(dim * (dim + 1) / 2)
# A <- matrix(NA_real_, dim, dim)
# A[lower.tri(A, diag = TRUE)] <- params
# A[lower.tri(A)] <- A[lower.tri(A)] / 2
# A[upper.tri(A)] <- t(A)[upper.tri(A)]
# seed <- abs(as.integer(100000 * rnorm(1)))
# all.equal(
# { set.seed(seed); ising_sample(11, params) },
# { set.seed(seed); ising_sample(11, A) }
# )
# x <- sample(0:1, 10, TRUE)
# sum(vech(outer(x, x)) * params)
# sum(x * (A %*% x))
# # M <- matrix(NA, dim, dim)
# # M[lower.tri(M, diag = TRUE)] <- seq_len(dim * (dim + 1) / 2) - 1
# # rownames(M) <- (1:dim) - 1
# # colnames(M) <- (1:dim) - 1
# # print.table(M)
# # i <- seq(0, dim - 1)
# # (i * (2 * dim + 1 - i)) / 2
# # I <- 0
# # for (i in seq(0, dim - 1)) {
# # print(I)
# # I <- I + dim - i
# # }
# m2.exact <- vech.pinv(ising_m2(params, use_MC = FALSE))
# m2.MC <- vech.pinv(ising_m2(params, use_MC = TRUE))
# m2.mat <- tcrossprod(ising_sample(1e4, A)) / 1e4
# m2.vech <- tcrossprod(ising_sample(1e4, params)) / 1e4
# par(mfrow = c(2, 2))
# matrixImage(m2.exact, main = "exact")
# matrixImage(m2.MC, main = "MC")
# matrixImage(m2.mat, main = "Sample mat")
# matrixImage(m2.vech, main = "Sample vech")