library(randomsearch) set.seed(123) knitr::opts_chunk$set(cache = TRUE, collapse = FALSE)
The package randomsearch optimizes a given smoof function.
Use makeSingleObjectiveFunction()
to wrap any function into a smoof function.
It can make use of parallel resources through prallelMap.
randomsearch has three internal operating modes:
max.evals
is defined as termination criterion. max.execbudget
and target.fun.value
have to be NULL
.max.execbudget
or target.fun.value
have been set and parallelStart
has been called without defined level
or with level = randomsearch.feval
.
In this mode par.jobs
(defaults to parallelGetOptions()$settings$cpus
) instances are started.
Each instance conducts a random search until the termination criterion is met.
The instances communicate using a shared folder (par.dir = ~/.randomsearch/
).max.execbudget
or target.fun.value
have been set. Note, that this introduces an overhead to fast.parallel even without parallelization because the termination criterion is checked after each evaluation.Simple usage with functions that use a vector as input:
fun = function(x) x[1]^2 + sin(x[2]) res = randomsearch(fun, lower = c(-1, -1), upper = c(2,2), minimize = TRUE, max.evals = 30) rs = summary(res) rs$best.x rs$best.y tail(as.data.frame(res))
For usage with more complicated search spaces you have to define a smoof function.
This allows you to tune over discrete parameters and even hierarchical parameter sets like in this example.
Here the parameter y
is only active if a==a2
.
fun = function(x) { if (x$a == "a1") { x$x^2 } else if (x$a == "a2") { sin(x$x * x$z) + 1 } } obj.fun = makeSingleObjectiveFunction( fn = fun, par.set = makeParamSet( makeDiscreteParam("a", values = c("a1", "a2")), makeNumericParam("x", lower = -3, upper = 3), makeNumericParam("z", lower = 0, upper = 2, requires = quote(a == "a2")) ), minimize = TRUE, has.simple.signature = FALSE ) res = randomsearch(obj.fun, max.evals = 30) rs = summary(res) rs$best.x rs$best.y tail(as.data.frame(res))
Note: For Windows use parallelStartSocket()
.
fun = function(x) { Sys.sleep(runif(1)) x[1]^2 + sin(x[2]) } parallelMap::parallelStartMulticore(cpus = 2, level = "randomsearch.feval") res = randomsearch(fun, lower = c(-1, -1), upper = c(2,2), minimize = TRUE, max.execbudget = 2, max.evals = 1000) parallelMap::parallelStop() summary(res)
Note: randomsearch()
detects a multi-objective optimization by the length of the minimize
vector.
obj.fun = function(x) c(x[1]^2 + sin(x[2]), cos(x[1])) res = randomsearch(obj.fun, lower = c(-1, -1), upper = c(2,2), minimize = c(TRUE, TRUE), max.evals = 30) summary(res)
Of course multi-objective optimization works with smoof functions as well. A multi-objective smoof function is constructed as follows:
obj.fun = makeMultiObjectiveFunction( fn = function(x) c(x[1]^2 + sin(x[2]), cos(x[1])), par.set = makeNumericParamSet(len = 2, lower = -1, upper = 2), minimize = c(TRUE, TRUE) ) res = randomsearch(obj.fun, max.evals = 10)
You can simply augment the results of a random search with additional random search results by converting the old result to a data.frame
and use it as an input for a new random search.
fun = function(x) x[1]^2 + sin(x[2]) res = randomsearch(fun, lower = c(-1, -1), upper = c(2,2), minimize = TRUE, max.evals = 10) summary(res) des = as.data.frame(res) res = randomsearch(fun, lower = c(-1, -1), upper = c(2,2), minimize = TRUE, max.evals = 1000, target.fun.value = -0.4) summary(res)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.