Title: | Parallel Bayesian Optimization of Hyperparameters |
---|---|
Description: | Fast, flexible framework for implementing Bayesian optimization of model hyperparameters according to the methods described in Snoek et al. <arXiv:1206.2944>. The package allows the user to run scoring function in parallel, save intermediary results, and tweak other aspects of the process to fully utilize the computing resources available to the user. |
Authors: | Samuel Wilson [aut, cre] |
Maintainer: | Samuel Wilson <[email protected]> |
License: | GPL-2 |
Version: | 1.2.5 |
Built: | 2025-03-06 03:34:53 UTC |
Source: | https://github.com/anothersamwilson/parbayesianoptimization |
Use this function to continue optimization of a bayesOpt object.
addIterations( optObj, iters.n = 1, iters.k = 1, otherHalting = list(timeLimit = Inf, minUtility = 0), bounds = optObj$bounds, acq = optObj$optPars$acq, kappa = optObj$optPars$kappa, eps = optObj$optPars$eps, gsPoints = optObj$optPars$gsPoints, convThresh = optObj$optPars$convThresh, acqThresh = optObj$optPars$acqThresh, errorHandling = "stop", saveFile = optObj$saveFile, parallel = FALSE, plotProgress = FALSE, verbose = 1, ... )
addIterations( optObj, iters.n = 1, iters.k = 1, otherHalting = list(timeLimit = Inf, minUtility = 0), bounds = optObj$bounds, acq = optObj$optPars$acq, kappa = optObj$optPars$kappa, eps = optObj$optPars$eps, gsPoints = optObj$optPars$gsPoints, convThresh = optObj$optPars$convThresh, acqThresh = optObj$optPars$acqThresh, errorHandling = "stop", saveFile = optObj$saveFile, parallel = FALSE, plotProgress = FALSE, verbose = 1, ... )
optObj |
an object of class |
iters.n |
The total number of additional times to sample the scoring function. |
iters.k |
integer that specifies the number of times to sample FUN
at each Epoch (optimization step). If running in parallel, good practice
is to set |
otherHalting |
Same as |
bounds |
Same as |
acq |
Same as |
kappa |
Same as |
eps |
Same as |
gsPoints |
Same as |
convThresh |
Same as |
acqThresh |
Same as |
errorHandling |
Same as |
saveFile |
Same as |
parallel |
Same as |
plotProgress |
Same as |
verbose |
Same as |
... |
Same as |
By default, this function uses the original parameters used to create
optObj
, however the parameters (including the bounds) can be customized.
If new bounds are used which cause some of the prior runs to fall outside of
the bounds, these samples are removed from the optimization procedure, but
will remain in scoreSummary
. FUN
should return the same elements
and accept the same inputs as the original, or this function may fail.
An object of class bayesOpt
having run additional iterations.
scoringFunction <- function(x) { a <- exp(-(2-x)^2)*1.5 b <- exp(-(4-x)^2)*2 c <- exp(-(6-x)^2)*1 return(list(Score = a+b+c)) } bounds <- list(x = c(0,8)) Results <- bayesOpt( FUN = scoringFunction , bounds = bounds , initPoints = 3 , iters.n = 1 , gsPoints = 10 ) Results <- addIterations(Results,iters.n=1)
scoringFunction <- function(x) { a <- exp(-(2-x)^2)*1.5 b <- exp(-(4-x)^2)*2 c <- exp(-(6-x)^2)*1 return(list(Score = a+b+c)) } bounds <- list(x = c(0,8)) Results <- bayesOpt( FUN = scoringFunction , bounds = bounds , initPoints = 3 , iters.n = 1 , gsPoints = 10 ) Results <- addIterations(Results,iters.n=1)
Maximizes a user defined function within a set of bounds. After the function is sampled a pre-determined number of times, a Gaussian process is fit to the results. An acquisition function is then maximized to determine the most likely location of the global maximum of the user defined function. This process is repeated for a set number of iterations.
bayesOpt( FUN, bounds, saveFile = NULL, initGrid, initPoints = 4, iters.n = 3, iters.k = 1, otherHalting = list(timeLimit = Inf, minUtility = 0), acq = "ucb", kappa = 2.576, eps = 0, parallel = FALSE, gsPoints = pmax(100, length(bounds)^3), convThresh = 1e+08, acqThresh = 1, errorHandling = "stop", plotProgress = FALSE, verbose = 1, ... )
bayesOpt( FUN, bounds, saveFile = NULL, initGrid, initPoints = 4, iters.n = 3, iters.k = 1, otherHalting = list(timeLimit = Inf, minUtility = 0), acq = "ucb", kappa = 2.576, eps = 0, parallel = FALSE, gsPoints = pmax(100, length(bounds)^3), convThresh = 1e+08, acqThresh = 1, errorHandling = "stop", plotProgress = FALSE, verbose = 1, ... )
FUN |
the function to be maximized. This function should return a
named list with at least 1 component. The first component must be named
|
bounds |
named list of lower and upper bounds for each |
saveFile |
character filepath (including file name and extension, .RDS) that
specifies the location to save results as they are obtained. A |
initGrid |
user specified points to sample the scoring function, should
be a |
initPoints |
Number of points to initialize the process with. Points are chosen with latin hypercube sampling within the bounds supplied. |
iters.n |
The total number of times FUN will be run after initialization. |
iters.k |
integer that specifies the number of times to sample FUN
at each Epoch (optimization step). If running in parallel, good practice
is to set |
otherHalting |
A list of other halting specifications. The process will stop if any of the following is true. These checks are only performed in between optimization steps:
|
acq |
acquisition function type to be used. Can be "ucb", "ei", "eips" or "poi".
|
kappa |
tunable parameter kappa of the upper confidence bound. Adjusts exploitation/exploration. Increasing kappa will increase the importance that uncertainty (unexplored space) has, therefore incentivising exploration. This number represents the standard deviations above 0 of your upper confidence bound. Default is 2.56, which corresponds to the ~99th percentile. |
eps |
tunable parameter epsilon of ei, eips and poi. Adjusts exploitation/exploration. This value is added to y_max after the scaling, so should between -0.1 and 0.1. Increasing eps will make the "improvement" threshold for new points higher, therefore incentivising exploitation. |
parallel |
should the process run in parallel? If TRUE, several criteria must be met:
|
gsPoints |
integer that specifies how many initial points to try when searching for the optimum of the acquisition function. Increase this for a higher chance to find global optimum, at the expense of more time. |
convThresh |
convergence threshold passed to |
acqThresh |
number 0-1. Represents the minimum percentage of the global optimal utility required for a local optimum to be included as a candidate parameter set in the next scoring function. If 1.0, only the global optimum will be used as a candidate parameter set. If 0.5, only local optimums with 50 percent of the utility of the global optimum will be used. |
errorHandling |
If FUN returns an error, how to proceed. All errors are
stored in |
plotProgress |
Should the progress of the Bayesian optimization be printed? Top graph shows the score(s) obtained at each iteration. The bottom graph shows the estimated utility of each point. This is useful to display how much utility the Gaussian Process is assuming still exists. If your utility is approaching 0, then you can be confident you are close to an optimal parameter set. |
verbose |
Whether or not to print progress to the console. If 0, nothing will be printed. If 1, progress will be printed. If 2, progress and information about new parameter-score pairs will be printed. |
... |
Other parameters passed to |
An object of class bayesOpt
containing information about the process.
FUN
The scoring function.
bounds
The bounds originally supplied.
iters
The total iterations that have been run.
initPars
The initialization parameters.
optPars
The optimization parameters.
GauProList
A list containing information on the Gaussian Processes used in optimization.
scoreSummary
A data.table
with results from the execution of FUN
at different inputs. Includes information on the epoch, iteration, function inputs, score, and any other
information returned by FUN
.
stopStatus
Information on what caused the function to stop running. Possible explenations are
time limit, minimum utility not met, errors in FUN
, iters.n was reached, or the Gaussian Process encountered
an error.
elapsedTime
The total time in seconds the function was executing.
It is highly recommended to read the GitHub for examples. There are also several vignettes available from the official CRAN Listing.
Jasper Snoek, Hugo Larochelle, Ryan P. Adams (2012) Practical Bayesian Optimization of Machine Learning Algorithms
# Example 1 - Optimization of a continuous single parameter function scoringFunction <- function(x) { a <- exp(-(2-x)^2)*1.5 b <- exp(-(4-x)^2)*2 c <- exp(-(6-x)^2)*1 return(list(Score = a+b+c)) } bounds <- list(x = c(0,8)) Results <- bayesOpt( FUN = scoringFunction , bounds = bounds , initPoints = 3 , iters.n = 2 , gsPoints = 10 ) ## Not run: # Example 2 - Hyperparameter Tuning in xgboost if (requireNamespace('xgboost', quietly = TRUE)) { library("xgboost") data(agaricus.train, package = "xgboost") Folds <- list( Fold1 = as.integer(seq(1,nrow(agaricus.train$data),by = 3)) , Fold2 = as.integer(seq(2,nrow(agaricus.train$data),by = 3)) , Fold3 = as.integer(seq(3,nrow(agaricus.train$data),by = 3)) ) scoringFunction <- function(max_depth, min_child_weight, subsample) { dtrain <- xgb.DMatrix(agaricus.train$data,label = agaricus.train$label) Pars <- list( booster = "gbtree" , eta = 0.01 , max_depth = max_depth , min_child_weight = min_child_weight , subsample = subsample , objective = "binary:logistic" , eval_metric = "auc" ) xgbcv <- xgb.cv( params = Pars , data = dtrain , nround = 100 , folds = Folds , prediction = TRUE , showsd = TRUE , early_stopping_rounds = 5 , maximize = TRUE , verbose = 0 ) return( list( Score = max(xgbcv$evaluation_log$test_auc_mean) , nrounds = xgbcv$best_iteration ) ) } bounds <- list( max_depth = c(2L, 10L) , min_child_weight = c(1, 100) , subsample = c(0.25, 1) ) ScoreResult <- bayesOpt( FUN = scoringFunction , bounds = bounds , initPoints = 3 , iters.n = 2 , iters.k = 1 , acq = "ei" , gsPoints = 10 , parallel = FALSE , verbose = 1 ) } ## End(Not run)
# Example 1 - Optimization of a continuous single parameter function scoringFunction <- function(x) { a <- exp(-(2-x)^2)*1.5 b <- exp(-(4-x)^2)*2 c <- exp(-(6-x)^2)*1 return(list(Score = a+b+c)) } bounds <- list(x = c(0,8)) Results <- bayesOpt( FUN = scoringFunction , bounds = bounds , initPoints = 3 , iters.n = 2 , gsPoints = 10 ) ## Not run: # Example 2 - Hyperparameter Tuning in xgboost if (requireNamespace('xgboost', quietly = TRUE)) { library("xgboost") data(agaricus.train, package = "xgboost") Folds <- list( Fold1 = as.integer(seq(1,nrow(agaricus.train$data),by = 3)) , Fold2 = as.integer(seq(2,nrow(agaricus.train$data),by = 3)) , Fold3 = as.integer(seq(3,nrow(agaricus.train$data),by = 3)) ) scoringFunction <- function(max_depth, min_child_weight, subsample) { dtrain <- xgb.DMatrix(agaricus.train$data,label = agaricus.train$label) Pars <- list( booster = "gbtree" , eta = 0.01 , max_depth = max_depth , min_child_weight = min_child_weight , subsample = subsample , objective = "binary:logistic" , eval_metric = "auc" ) xgbcv <- xgb.cv( params = Pars , data = dtrain , nround = 100 , folds = Folds , prediction = TRUE , showsd = TRUE , early_stopping_rounds = 5 , maximize = TRUE , verbose = 0 ) return( list( Score = max(xgbcv$evaluation_log$test_auc_mean) , nrounds = xgbcv$best_iteration ) ) } bounds <- list( max_depth = c(2L, 10L) , min_child_weight = c(1, 100) , subsample = c(0.25, 1) ) ScoreResult <- bayesOpt( FUN = scoringFunction , bounds = bounds , initPoints = 3 , iters.n = 2 , iters.k = 1 , acq = "ei" , gsPoints = 10 , parallel = FALSE , verbose = 1 ) } ## End(Not run)
Use this to change the saveFile parameter in a pre-existing bayesOpt object.
changeSaveFile(optObj, saveFile = NULL)
changeSaveFile(optObj, saveFile = NULL)
optObj |
An object of class bayesOpt |
saveFile |
A filepath stored as a character. Must include the filename and extension as a .RDS. |
The same optObj
with the updated saveFile.
## Not run: scoringFunction <- function(x) { a <- exp(-(2-x)^2)*1.5 b <- exp(-(4-x)^2)*2 c <- exp(-(6-x)^2)*1 return(list(Score = a+b+c)) } bounds <- list(x = c(0,8)) Results <- bayesOpt( FUN = scoringFunction , bounds = bounds , initPoints = 3 , iters.n = 2 , gsPoints = 10 , saveFile = "filepath.RDS" ) Results <- changeSaveFile(Results,saveFile = "DifferentFile.RDS") ## End(Not run)
## Not run: scoringFunction <- function(x) { a <- exp(-(2-x)^2)*1.5 b <- exp(-(4-x)^2)*2 c <- exp(-(6-x)^2)*1 return(list(Score = a+b+c)) } bounds <- list(x = c(0,8)) Results <- bayesOpt( FUN = scoringFunction , bounds = bounds , initPoints = 3 , iters.n = 2 , gsPoints = 10 , saveFile = "filepath.RDS" ) Results <- changeSaveFile(Results,saveFile = "DifferentFile.RDS") ## End(Not run)
Returns the N parameter sets which resulted in the maximum scores from FUN
.
getBestPars(optObj, N = 1)
getBestPars(optObj, N = 1)
optObj |
An object of class |
N |
The number of parameter sets to return |
A list containing the FUN
inputs which resulted in the highest returned Score.
If N > 1, a data.table
is returned. Each row is a result from FUN
, with results ordered by
descending Score.
scoringFunction <- function(x) { a <- exp(-(2-x)^2)*1.5 b <- exp(-(4-x)^2)*2 c <- exp(-(6-x)^2)*1 return(list(Score = a+b+c)) } bounds <- list(x = c(0,8)) Results <- bayesOpt( FUN = scoringFunction , bounds = bounds , initPoints = 3 , iters.n = 2 , gsPoints = 10 ) print(getBestPars(Results))
scoringFunction <- function(x) { a <- exp(-(2-x)^2)*1.5 b <- exp(-(4-x)^2)*2 c <- exp(-(6-x)^2)*1 return(list(Score = a+b+c)) } bounds <- list(x = c(0,8)) Results <- bayesOpt( FUN = scoringFunction , bounds = bounds , initPoints = 3 , iters.n = 2 , gsPoints = 10 ) print(getBestPars(Results))
Returns all local optimums of the acquisition function, no matter the utility.
getLocalOptimums( optObj, bounds = optObj$bounds, acq = optObj$optPars$acq, kappa = optObj$optPars$kappa, eps = optObj$optPars$eps, convThresh = optObj$optPars$convThresh, gsPoints = optObj$optPars$gsPoints, parallel = FALSE, verbose = 1 )
getLocalOptimums( optObj, bounds = optObj$bounds, acq = optObj$optPars$acq, kappa = optObj$optPars$kappa, eps = optObj$optPars$eps, convThresh = optObj$optPars$convThresh, gsPoints = optObj$optPars$gsPoints, parallel = FALSE, verbose = 1 )
optObj |
an object of class |
bounds |
Same as in |
acq |
Same as in |
kappa |
Same as in |
eps |
Same as in |
convThresh |
Same as in |
gsPoints |
Same as in |
parallel |
Same as in |
verbose |
Should warnings be shown before results are returned prematurely? |
gsPoints
points in the parameter space are randomly initialized, and
the L-BFGS-B method is used to find the closest local optimum to each point.
dbscan is then used to cluster points together which converged to the same
optimum - only unique optimums are returned.
A data table of local optimums, including the utility (gpUtility), the utility relative to the max utility (relUtility), and the steps taken in the L-BFGS-B method (gradCount).
scoringFunction <- function(x) { a <- exp(-(2-x)^2)*1.5 b <- exp(-(4-x)^2)*2 c <- exp(-(6-x)^2)*1 return(list(Score = a+b+c)) } bounds <- list(x = c(0,8)) Results <- bayesOpt( FUN = scoringFunction , bounds = bounds , initPoints = 3 , iters.n = 2 , gsPoints = 10 ) print(getLocalOptimums(Results))
scoringFunction <- function(x) { a <- exp(-(2-x)^2)*1.5 b <- exp(-(4-x)^2)*2 c <- exp(-(6-x)^2)*1 return(list(Score = a+b+c)) } bounds <- list(x = c(0,8)) Results <- bayesOpt( FUN = scoringFunction , bounds = bounds , initPoints = 3 , iters.n = 2 , gsPoints = 10 ) print(getLocalOptimums(Results))
bayesOpt
objectReturns 2 stacked plots - the top shows the results from FUN at each iteration. The bottom shows the utility from each point before the search took place.
## S3 method for class 'bayesOpt' plot(x, ...)
## S3 method for class 'bayesOpt' plot(x, ...)
x |
An object of class bayesOpt |
... |
Passed to |
an object of class ggarrange
from the ggpubr
package.
scoringFunction <- function(x) { a <- exp(-(2-x)^2)*1.5 b <- exp(-(4-x)^2)*2 c <- exp(-(6-x)^2)*1 return(list(Score = a+b+c)) } bounds <- list(x = c(0,8)) Results <- bayesOpt( FUN = scoringFunction , bounds = bounds , initPoints = 3 , iters.n = 2 , gsPoints = 10 ) # This plot will also show in real time with parameter plotProgress = TRUE in bayesOpt() plot(Results)
scoringFunction <- function(x) { a <- exp(-(2-x)^2)*1.5 b <- exp(-(4-x)^2)*2 c <- exp(-(6-x)^2)*1 return(list(Score = a+b+c)) } bounds <- list(x = c(0,8)) Results <- bayesOpt( FUN = scoringFunction , bounds = bounds , initPoints = 3 , iters.n = 2 , gsPoints = 10 ) # This plot will also show in real time with parameter plotProgress = TRUE in bayesOpt() plot(Results)
bayesOpt
objectPrint a bayesOpt
object
## S3 method for class 'bayesOpt' print(x, ...)
## S3 method for class 'bayesOpt' print(x, ...)
x |
Object of class |
... |
required to use S3 method |
NULL
To save time, Gaussian processes are not updated after the last iteration
in addIterations()
. The user can do this manually, using this function
if they wish. This is not necessary to continue optimization using addIterations
.
updateGP(optObj, bounds = optObj$bounds, verbose = 1, ...)
updateGP(optObj, bounds = optObj$bounds, verbose = 1, ...)
optObj |
an object of class bayesOpt |
bounds |
The bounds to scale the parameters within. |
verbose |
Should the user be warned if the GP is already up to date? |
... |
passed to |
An object of class bayesOpt
with updated Gaussian processes.
# Create initial object scoringFunction <- function(x) { a <- exp(-(2-x)^2)*1.5 b <- exp(-(4-x)^2)*2 c <- exp(-(6-x)^2)*1 return(list(Score = a+b+c)) } bounds <- list(x = c(0,8)) Results <- bayesOpt( FUN = scoringFunction , bounds = bounds , initPoints = 3 , iters.n = 2 , gsPoints = 10 ) # At this point, the Gaussian Process has not been updated # with the most recent results. We can update it manually: Results <- updateGP(Results)
# Create initial object scoringFunction <- function(x) { a <- exp(-(2-x)^2)*1.5 b <- exp(-(4-x)^2)*2 c <- exp(-(6-x)^2)*1 return(list(Score = a+b+c)) } bounds <- list(x = c(0,8)) Results <- bayesOpt( FUN = scoringFunction , bounds = bounds , initPoints = 3 , iters.n = 2 , gsPoints = 10 ) # At this point, the Gaussian Process has not been updated # with the most recent results. We can update it manually: Results <- updateGP(Results)