Skip to contents

Computer Experiment LEarning Curve eXtrapolation

Tools for active learning on computer experiments, with support for learning curve extrapolation and progress forecasting.

Status

Work in progress, nothing in here should be considered stable yet.

Installation

# you almost certainly need for the examples:
install.packages(c("mlr3learners", "DiceKriging", "kknn"))

# Install celecx
remotes::install_github("mlr-org/celecx")

Examples

Gaussian Process, Batch Size 2

Run active learning to explore an unknown function:

library("celecx")
library("mlr3")
library("mlr3learners")  # for regr.km

# Define objective (unknown function to learn)
objective <- ObjectiveRFun$new(
  fun = function(xs) list(y = sin(xs$x * pi)),
  domain = ps(x = p_dbl(lower = 0, upper = 2)),
  codomain = ps(y = p_dbl(tags = "learn"))
)

# Run active learning
result <- optimize_active(
  objective = objective,
  n_evals = 10L,
  learner = lrn("regr.km", covtype = "matern5_2"),
  se_method = "auto",
  batch_size = 2L,
  acq_evals = 20L,
  multipoint_method = "greedy"
)

# Access results
result$instance$archive$data  # All evaluated points

xvals <- seq(0, 2, length.out = 100)
yvals.true <- objective$fun(list(x = xvals))$y
surrogate <- result$optimizer$surrogates$uncertainty
yvals.pred <- surrogate$predict(data.table::data.table(x = xvals))
plot(xvals, yvals.true, col = "red", type = "l", xlab = "x", ylab = "y",
  main = "Active Learning sin(x) with batch_size = 2")
lines(xvals, yvals.pred$mean, col = "blue")
lines(xvals, with(yvals.pred, mean + 1.96 * se), col = "blue", lty = 2)
lines(xvals, with(yvals.pred, mean - 1.96 * se), col = "blue", lty = 2)
text(y ~ x, labels = batch_nr, data = result$instance$archive$data, pos = 1)

KNN on a 2D test function

Consider this more complex 2D test function:

This example requires the kknn package.

objective <- ObjectiveRFun$new(
  fun = function(xs) {
    bump_a <- exp(-((xs$x1 - 0.3)^2 + (xs$x2 - 0.3)^2) / 0.02)
    bump_b <- 0.7 * exp(-((xs$x1 - 0.8)^2 + (xs$x2 - 0.7)^2) / 0.01)
    list(y = bump_a + bump_b)
  },
  domain = ps(x1 = p_dbl(lower = 0, upper = 1), x2 = p_dbl(lower = 0, upper = 1)),
  codomain = ps(y = p_dbl(tags = "learn"))
)

library("ggplot2")
grid <- data.table::CJ(
  x1 = seq(0, 1, length.out = 100L),
  x2 = seq(0, 1, length.out = 100L)
)
grid[, y := objective$fun(list(x1 = x1, x2 = x2))$y]

ggplot(grid, aes(x1, x2, z = y)) +
  geom_contour_filled() +
  coord_equal()

Here we use a KNN surrogate model, deliberately chosen because it does not do its own SE estimation. We therefore give the se_method = "bootstrap" argument, with n_bootstrap = 10 trials (chosen to be small for quick demonstration). We propose batch_size = 10 points in each iteration, which are the top 10 from acq_evals = 100 candidate points. We can modify the candidate set further by influencing the acq_optimizer. In the current interface, this is translated to a candidate sampler for the acquisition step; here we use Latin hypercube sampling.

acq_optimizer <- clx_sps("lhs")

result <- optimize_active(
  objective = objective,
  n_evals = 200L,
  learner = lrn("regr.kknn", k = 4L),
  se_method = "bootstrap",
  n_bootstrap = 10L,
  batch_size = 10L,
  acq_evals = 100L,
  acq_optimizer = acq_optimizer
)

result_data <- result$instance$archive$data[, .(x1, x2, y, batch_nr)]
result_task <- as_task_regr(result_data[, .(x1, x2, y)], target = "y")
kknn_model <- lrn("regr.kknn", k = 3L)$train(result_task)

grid_knn <- data.table::copy(grid)
grid_knn[, y := kknn_model$predict_newdata(grid[, .(x1, x2)])$response]

ggplot(grid_knn, aes(x1, x2, z = y)) +
  geom_contour_filled() +
  geom_point(
    data = result_data,
    mapping = aes(x1, x2, color = batch_nr),
    inherit.aes = FALSE,
    shape = 4,
    size = 1.5,
    stroke = 0.6
  ) +
  scale_color_gradient(
    low = "steelblue",
    high = "firebrick",
    limits = c(1, 6)
  ) +
  coord_equal()

License

MIT