This is the R version of Python's Techtonique/GPopt
(https://docs.techtonique.net/GPopt/GPopt.html), a package for
'Bayesian' optimization of black-box functions (and machine learning hyperparameter tuning) using Gaussian
Process Regression and other surrogate models.
Keep in mind that this package is for Machine Learning hyperparameter tuning. The global minimum won't always be found, but it isn't an issue, since it means you aren't overfitting the training set.
It's ported the same way as nnetsauce for R was: with uv to
create an isolated Python virtual environment containing the Python GPopt package, and reticulate to call
into it from R. Every function in this R package is a thin wrapper that returns the underlying Python object;
the general rule is: object accesses with .'s in Python are replaced by $'s in R.
See this post for the technique: Finally figured out a way to port python packages to R using uv and reticulate.
uv
# pip install uv # if necessary
uv venv venv
source venv/bin/activate # on Windows: venv\Scripts\activate
uv pip install pip GPopt
Keep track of where venv/ lives -- you'll pass its path as venv_path to every function in this package.
install.packages("remotes")
remotes::install_github("Techtonique/GPopt_r") # or wherever this package is hosted
reticulate will be installed automatically as a dependency.
library(GPopt)
branin <- function(x) {
x1 <- x[1]; x2 <- x[2]
term1 <- (x2 - (5.1 * x1^2) / (4 * pi^2) + (5 * x1) / pi - 6)^2
term2 <- 10 * (1 - 1 / (8 * pi)) * cos(x1)
term1 + term2 + 10
}
opt <- GPOpt(
lower_bound = c(-5, 0),
upper_bound = c(10, 15),
objective_func = branin,
n_init = 10,
n_iter = 40,
venv_path = "./venv"
)
opt$optimize(verbose = 1L)
print(opt$x_min) # current best parameters
print(opt$y_min) # current best objective value
library(GPopt)
sklearn <- get_sklearn(venv_path = "./venv")
RandomForestClassifier <- sklearn$ensemble$RandomForestClassifier
X <- as.matrix(iris[, 1:4])
y <- as.integer(iris$Species) - 1L
mlopt <- MLOptimizer(scoring = "accuracy", cv = 5, venv_path = "./venv")
param_config <- list(
n_estimators = list(bounds = c(10, 300), dtype = "int"),
max_depth = list(bounds = c(1, 20), dtype = "int")
)
mlopt$optimize(
X_train = X, y_train = y,
estimator_class = RandomForestClassifier(),
param_config = param_config,
verbose = 1L
)
print(mlopt$get_best_parameters())
print(mlopt$get_best_score())
library(GPopt)
opt <- BOstopping(
f = branin,
bounds = rbind(c(-5, 10), c(0, 15)),
venv_path = "./venv"
)
result <- opt$optimize(n_iter = 100L)
library(GPopt)
sklearn <- get_sklearn(venv_path = "./venv")
ns <- get_nnetsauce(venv_path = "./venv")
opt <- GPOpt(
lower_bound = c(-5, 0),
upper_bound = c(10, 15),
objective_func = branin,
acquisition="ucb",
method="splitconformal",
surrogate_obj = ns$PredictionInterval(sklearn$ensemble$RandomForestRegressor()),
venv_path = "./venv"
)
opt$optimize(verbose = 1L)
GPOpt() -- main Bayesian optimizer (wraps GPopt.GPOpt)MLOptimizer() -- cross-validated hyperparameter tuning for scikit-learn estimators (wraps GPopt.MLOptimizer)GenericSurrogate() -- wrap any scikit-learn-compatible regressor as a surrogate (wraps GPopt.GenericSurrogate)GeneralizationOpt() -- diagnostics for the generalization gap of hyperparameters (wraps GPopt.GeneralizationOpt)BOstopping() -- Bayesian optimization with early stopping (wraps GPopt.BOstopping)get_GPopt(), get_numpy(), get_sklearn() -- access the raw Python modules for anything not (yet) covered abovevenv_path argument pointing at the uv-created virtual environment; this must be
the same environment across a given script/session for object identity between calls to work correctly.objective_func (or f) are called from Python with a 1-D numpy array converted back
to an R numeric vector -- so index with x[1], x[2], ... as usual in R, not x[0], x[1], ...GPopt API is available -- consult
the Python package's documentation and blog posts for anything not
covered in this README.BSD-3-Clause-Clear, matching the original Python GPopt package and nnetsauce_r.