A modern and flexible approach to Bayesian Optimization / Model
Based Optimization building on the 'bbotk' package. 'mlr3mbo' is a toolbox
providing both ready-to-use optimization algorithms as well as their fundamental
building blocks allowing for straightforward implementation of custom
algorithms. Single- and multi-objective optimization is supported as well as
mixed continuous, categorical and conditional search spaces. Moreover, using
'mlr3mbo' for hyperparameter optimization of machine learning models within the
'mlr3' ecosystem is straightforward via 'mlr3tuning'. Examples of ready-to-use
optimization algorithms include Efficient Global Optimization by Jones et al.
(1998)
Package website: release | dev
A new R6 and much more modular implementation for single- and multi-objective Bayesian Optimization.
The best entry point to get familiar with mlr3mbo is provided via the
Bayesian
Optimization
chapter in the mlr3book.
mlr3mbo is built modular relying on the following
R6 classes:
Surrogate: Surrogate ModelAcqFunction: Acquisition FunctionAcqOptimizer: Acquisition Function OptimizerBased on these, Bayesian Optimization (BO) loops can be written, see,
e.g., bayesopt_ego for sequential single-objective BO.
mlr3mbo also provides an OptimizerMbo class behaving like any other
Optimizer from the bbotk
package as well as a TunerMbo class behaving like any other Tuner
from the mlr3tuning
package.
mlr3mbo uses sensible defaults for the Surrogate, AcqFunction,
AcqOptimizer, and the loop_function. See
mbo_defaults
for more details on all defaults.
Minimize the two-dimensional Branin function via sequential BO using a GP as surrogate and EI as acquisition function optimized via a local search:
library(bbotk)
library(mlr3mbo)
library(mlr3learners)
set.seed(1)
fun = function(xdt) {
y = branin(xdt[["x1"]], xdt[["x2"]])
data.table(y = y)
}
domain = ps(
x1 = p_dbl(-5, 10),
x2 = p_dbl(0, 15)
)
codomain = ps(
y = p_dbl(tags = "minimize")
)
objective = ObjectiveRFunDt$new(
fun = fun,
domain = domain,
codomain = codomain
)
instance = oi(
objective = objective,
terminator = trm("evals", n_evals = 25)
)
surrogate = srlrn(lrn("regr.km", control = list(trace = FALSE)))
acq_function = acqf("ei")
acq_optimizer = acqo("local_search", n_searches = 10, n_steps = 5, n_neighs = 10)
optimizer = opt("mbo",
loop_function = bayesopt_ego,
surrogate = surrogate,
acq_function = acq_function,
acq_optimizer = acq_optimizer
)
optimizer$optimize(instance)
## x1 x2 x_domain y
## <num> <num> <list> <num>
## 1: -3.152173 12.30826 <list[2]> 0.3984859
We can quickly visualize the contours of the objective function (on log scale) as well as the sampling behavior of our BO run (lighter blue colors indicating points that were evaluated in later stages of the optimization process; the first batch is given by the initial design).
library(ggplot2)
grid = generate_design_grid(instance$search_space, resolution = 1000L)$data
grid[, y := branin(x1 = x1, x2 = x2)]
ggplot(aes(x = x1, y = x2, z = log(y)), data = grid) +
geom_contour(color = "black") +
geom_point(aes(x = x1, y = x2, color = batch_nr), data = instance$archive$data) +
labs(x = expression(x[1]), y = expression(x[2])) +
theme_minimal() +
theme(legend.position = "bottom")
Note that you can also use bb_optimize as a shorthand instead of
constructing an optimization instance.
library(mlr3)
library(mlr3learners)
library(mlr3tuning)
library(mlr3mbo)
set.seed(1)
task = tsk("sonar")
learner = lrn("classif.rpart", cp = to_tune(lower = 1e-04, upper = 1, logscale = TRUE))
instance = tune(
tuner = tnr("mbo"),
task = task,
learner = learner,
resampling = rsmp("holdout"),
measure = msr("classif.ce"),
term_evals = 10)
instance$result
## cp learner_param_vals x_domain classif.ce
## <num> <list> <list> <num>
## 1: -6.220556 <list[2]> <list[1]> 0.2382812
If you use mlr3mbo, please cite our paper.
Becker M, Schneider L, Binder M, Kotthoff L, Bischl B (2026). “mlr3mbo: Bayesian Optimization in R.” Patterns. https://doi.org/10.1016/j.patter.2026.101614.
@Article{becker2026mlr3mbo,
title = {mlr3mbo: Bayesian Optimization in R},
author = {Marc Becker and Lennart Schneider and Martin Binder and Lars Kotthoff and Bernd Bischl},
year = {2026},
journal = {Patterns},
doi = {10.1016/j.patter.2026.101614},
url = {https://doi.org/10.1016/j.patter.2026.101614},
}