Skip to content

Commit f656a00

Browse files
authored
Fix Issue #407 scalarize parego infill (#408)
* try to fix this mess * finalize fix * rename convertOptPathToDf * remove test file * documentation * fix * allow less vectors in infill crits * get design from task data * implement paego plot (WIP) * Make exampleRunMultiobj plots work again
1 parent 93a06f4 commit f656a00

26 files changed

+178
-109
lines changed

R/OptState_getter.R

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ getOptStateTasks = function(opt.state) {
3434
tasks
3535
}
3636

37+
getOptStateDesigns = function(opt.state) {
38+
tasks = getOptStateTasks(opt.state)
39+
lapply(tasks, getTaskData)
40+
}
41+
3742
getOptStateTimeModel = function(opt.state) {
3843
opt.path = getOptStateOptPath(opt.state)
3944
time.model = opt.state$time.model

R/SMBO.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ updateSMBO = function(opt.state, x, y) {
6969
assertNumeric(y[[1]], len = control$n.objectives)
7070

7171

72-
infill.values = control$infill.crit$fun(points = x, models = getOptStateModels(opt.state)[[1]], control = control, design = convertOptPathToDf(opt.path, control), attributes = TRUE, iter = getOptStateLoop(opt.state))
72+
infill.values = control$infill.crit$fun(points = x, models = getOptStateModels(opt.state)[[1]], control = control, designs = getOptStateDesigns(opt.state), attributes = TRUE, iter = getOptStateLoop(opt.state))
7373

7474
prop = makeProposal(
7575
control = control,
Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
# Takes x.vals and y.vals from the opt.path, possibly imputes missing x.vals and
22
# returns a data.frame.
33
#
4+
# @param opt.state [OptState]
45
# @param opt.path [\code{\link[ParamHelpers]{optPath}}]\cr
56
# Optimization path.
7+
# Might be altered for multipoint proposals etc.
68
# @param control [\code{\link{MBOControl}}]\cr
79
# MBO control object.
10+
# Might be altered for multipoint proposals etc.
811
# @return [\code{data.frame}]
9-
convertOptPathToDf = function(opt.path, control) {
12+
# With x and y columns
13+
14+
convertToDesign = function(opt.path, control) {
1015
df = as.data.frame(opt.path, include.rest = FALSE)
11-
df = convertDataFrameCols(df, ints.as.num = TRUE, logicals.as.factor = TRUE)
12-
return(df)
13-
}
16+
convertDataFrameCols(df, ints.as.num = TRUE, logicals.as.factor = TRUE)
17+
}

R/infillOptCMAES.R

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@
55
# @param infill.crit [\code{function}]\cr
66
# Infill criterion function.
77
# @param models [\code{\link{WrappedModel}}]\cr
8-
# Model fitted on design.
8+
# Model fitted on designs.
99
# @param control [\code{\link{MBOControl}}]\cr
1010
# Control object.
1111
# @param par.set [\code{\link[ParamHelpers]{ParamSet}}]\cr
1212
# Parameter set.
1313
# @param opt.path [\code{\link[ParamHelpers{OptPath}}]\cr
1414
# Optimization path / archive.
15-
# @param design [\code{data.frame}]\cr
16-
# Design of already visited points.
15+
# @param designs [list of \code{data.frame}]\cr
16+
# List with usually one element containing the Design of already visited points.
1717
# @param iter [\integer(1)]
1818
# Current iteration
1919
# @param ... [\code{ANY}]\cr
@@ -24,15 +24,15 @@
2424

2525
# the first start is always at the best point of the current opt.path.
2626
# works only for numerics and integers, latter are simply rounded.
27-
infillOptCMAES = function(infill.crit, models, control, par.set, opt.path, design, iter, ...) {
27+
infillOptCMAES = function(infill.crit, models, control, par.set, opt.path, designs, iter, ...) {
2828
rep.pids = getParamIds(par.set, repeated = TRUE, with.nr = TRUE)
2929
cmaes.control = control$infill.opt.cmaes.control
3030

3131
fn = smoof::makeSingleObjectiveFunction(
3232
fn = function(x) {
3333
newdata = as.data.frame(t(x))
3434
colnames(newdata) = rep.pids
35-
infill.crit(newdata, models, control, par.set, design, iter, ...)
35+
infill.crit(newdata, models, control, par.set, designs, iter, ...)
3636
},
3737
par.set = par.set,
3838
vectorized = TRUE

R/infillOptEA.R

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# kind of mimics our multi-objective approach, so we can
33
# compare more honestly.
44
# See infillOptCMAES.R for interface explanation.
5-
infillOptEA = function(infill.crit, models, control, par.set, opt.path, design, iter, ...) {
5+
infillOptEA = function(infill.crit, models, control, par.set, opt.path, designs, iter, ...) {
66
requirePackages("emoa", why = "infillOptEA")
77

88
# get constants and init shit
@@ -23,7 +23,7 @@ infillOptEA = function(infill.crit, models, control, par.set, opt.path, design,
2323

2424
# random inital population:
2525
X = generateDesign(mu, par.set, fun = randomLHS)
26-
y = infill.crit(X, models, control, par.set, design, iter, ...)
26+
y = infill.crit(X, models, control, par.set, designs, iter, ...)
2727

2828
for (i in seq_len(control$infill.opt.ea.maxit)) {
2929
# Create new individual (mu + lambda)
@@ -44,7 +44,7 @@ infillOptEA = function(infill.crit, models, control, par.set, opt.path, design,
4444
# Add new individual:
4545
X[nrow(X) + 1, ] = child1
4646
child2 = setColNames(as.data.frame(as.list(child1)), repids)
47-
y[length(y) + 1] = infill.crit(child2, models, control, par.set, design, iter, ...)
47+
y[length(y) + 1] = infill.crit(child2, models, control, par.set, designs, iter, ...)
4848
}
4949

5050
# get elements we want to remove from current population

R/infillOptFocus.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#FIXME should we shrink if a local value is NA (dependent param)
77
#
88
# See infillOptCMAES.R for interface explanation.
9-
infillOptFocus = function(infill.crit, models, control, par.set, opt.path, ...) {
9+
infillOptFocus = function(infill.crit, models, control, par.set, opt.path, designs, iter, ...) {
1010
global.y = Inf
1111

1212
# restart the whole crap some times
@@ -22,7 +22,7 @@ infillOptFocus = function(infill.crit, models, control, par.set, opt.path, ...)
2222
# convert to param encoding our model was trained on and can use
2323
newdesign = convertDataFrameCols(newdesign, ints.as.num = TRUE, logicals.as.factor = TRUE)
2424

25-
y = infill.crit(newdesign, models, control, ps.local, ...)
25+
y = infill.crit(newdesign, models, control, ps.local, designs, iter, ...)
2626

2727

2828
# get current best value

R/infillOptNSGA2.R

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# NSGA2 is used to create set of candidate soluation
33
# Greedy cypervolume contribution selection is used to select prop.point from
44
# from candidate points
5-
infillOptMultiObjNSGA2 = function(infill.crit, models, control, par.set, opt.path, design, iter, ...) {
5+
infillOptMultiObjNSGA2 = function(infill.crit, models, control, par.set, opt.path, designs, iter, ...) {
66

77
# build target function for vectorized nsga2 and run it
88
rep.pids = getParamIds(par.set, repeated = TRUE, with.nr = TRUE)
@@ -13,8 +13,9 @@ infillOptMultiObjNSGA2 = function(infill.crit, models, control, par.set, opt.pat
1313
asMatrixRows(lapply(seq_len(m), function(i) {
1414
# we need to make sure mininimize in control is a scalar, so we can multiply it in infill crits...
1515
control$minimize = control$minimize[i]
16+
control$y.name = control$y.name[i]
1617
infill.crit(points = newdata, models = models[i], control = control,
17-
par.set = par.set, design = design, iter = iter, ...)
18+
par.set = par.set, designs = designs[i], iter = iter, ...)
1819
}))
1920
}
2021
res = mco::nsga2(fun.tmp, idim = getParamNr(par.set, devectorize = TRUE), odim = control$n.objectives,
@@ -34,17 +35,18 @@ infillOptMultiObjNSGA2 = function(infill.crit, models, control, par.set, opt.pat
3435
candidate.vals = asMatrixCols(lapply(seq_len(m), function(i) {
3536
# we need to make sure mininimize in control is a scalar, so we can multiply it in infill crits...
3637
control$minimize = control$minimize[i]
37-
38+
control$y.name = control$y.name[i]
3839
newdata = as.data.frame(res$par)
3940
colnames(newdata) = rep.pids
4041
hv.contr.crit(points = newdata, models = models[i], control = control,
41-
par.set = par.set, design = design, iter = iter, ...)
42+
par.set = par.set, designs = designs[i], iter = iter, ...)
4243
}))
4344

4445
prop.points = matrix(nrow = 0, ncol = ncol(candidate.points))
4546
prop.vals = matrix(nrow = 0, ncol = ncol(candidate.vals))
4647
colnames(prop.vals) = control$y.name
47-
ys = design[, control$y.name]
48+
ys = Map(function(i, y.name) designs[[i]][,y.name], i = seq_along(control$y.name), y.name = control$y.name)
49+
ys = do.call(cbind, ys)
4850

4951
ref.point = getMultiObjRefPoint(ys, control)
5052
prop.hv.contrs = numeric(control$propose.points)
@@ -62,6 +64,6 @@ infillOptMultiObjNSGA2 = function(infill.crit, models, control, par.set, opt.pat
6264

6365
# FIXME: cleanup - i'm reall unsure how to set the names of prop.points technically
6466
prop.points = as.data.frame(prop.points)
65-
colnames(prop.points) = names(design[, colnames(design) %nin% control$y.name])
67+
colnames(prop.points) = getParamIds(par.set, repeated = TRUE, with.nr = TRUE)
6668
list(prop.points = prop.points, prop.hv.contrs = prop.hv.contrs)
6769
}

R/infill_crits.R

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ NULL
5454
#' @rdname infillcrits
5555
makeMBOInfillCritMeanResponse = function() {
5656
makeMBOInfillCrit(
57-
fun = function(points, models, control, par.set, design, iter, progress, attributes = FALSE) {
57+
fun = function(points, models, control, par.set, designs, iter, progress, attributes = FALSE) {
5858
ifelse(control$minimize, 1, -1) * predict(models[[1L]], newdata = points)$data$response
5959
},
6060
name = "Mean response",
@@ -67,7 +67,7 @@ makeMBOInfillCritMeanResponse = function() {
6767
#' @rdname infillcrits
6868
makeMBOInfillCritStandardError = function() {
6969
makeMBOInfillCrit(
70-
fun = function(points, models, control, par.set, design, iter, progress, attributes = FALSE) {
70+
fun = function(points, models, control, par.set, designs, iter, progress, attributes = FALSE) {
7171
-predict(models[[1L]], newdata = points)$data$se
7272
},
7373
name = "Standard error",
@@ -83,10 +83,13 @@ makeMBOInfillCritEI = function(se.threshold = 1e-6) {
8383
assertNumber(se.threshold, lower = 1e-20)
8484
force(se.threshold)
8585
makeMBOInfillCrit(
86-
fun = function(points, models, control, par.set, design, iter, progress, attributes = FALSE) {
86+
fun = function(points, models, control, par.set, designs, iter, progress, attributes = FALSE) {
8787
model = models[[1L]]
88-
maximize.mult = ifelse(control$minimize, 1, -1)
88+
design = designs[[1]]
89+
maximize.mult = if (control$minimize) 1 else -1
90+
assertString(control$y.name)
8991
y = maximize.mult * design[, control$y.name]
92+
assertNumeric(y, any.missing = FALSE)
9093
p = predict(model, newdata = points)$data
9194
p.mu = maximize.mult * p$response
9295
p.se = p$se
@@ -117,9 +120,9 @@ makeMBOInfillCritCB = function(cb.lambda = NULL) {
117120
assertNumber(cb.lambda, lower = 0, null.ok = TRUE)
118121
force(cb.lambda)
119122
makeMBOInfillCrit(
120-
fun = function(points, models, control, par.set, design, iter, progress, attributes = FALSE) {
123+
fun = function(points, models, control, par.set, designs, iter, progress, attributes = FALSE) {
121124
model = models[[1L]]
122-
maximize.mult = ifelse(control$minimize, 1, -1)
125+
maximize.mult = if (control$minimize) 1 else -1
123126
p = predict(model, newdata = points)$data
124127
#FIXME: removed cb.inflate.se for now (see issue #309)
125128
# if (cb.inflate.se) {
@@ -159,9 +162,10 @@ makeMBOInfillCritAEI = function(aei.use.nugget = FALSE, se.threshold = 1e-6) {
159162
force(se.threshold)
160163

161164
makeMBOInfillCrit(
162-
fun = function(points, models, control, par.set, design, iter, progress, attributes = FALSE) {
165+
fun = function(points, models, control, par.set, designs, iter, progress, attributes = FALSE) {
163166
model = models[[1L]]
164-
maximize.mult = ifelse(control$minimize, 1, -1)
167+
design = designs[[1L]]
168+
maximize.mult = if (control$minimize) 1 else -1
165169
p = predict(model, newdata = points)$data
166170
p.mu = maximize.mult * p$response
167171
p.se = p$se
@@ -205,9 +209,10 @@ makeMBOInfillCritEQI = function(eqi.beta = 0.75, se.threshold = 1e-6) {
205209
force(se.threshold)
206210

207211
makeMBOInfillCrit(
208-
fun = function(points, models, control, par.set, design, iter, progress, attributes = FALSE) {
212+
fun = function(points, models, control, par.set, designs, iter, progress, attributes = FALSE) {
209213
model = models[[1L]]
210-
maximize.mult = ifelse(control$minimize, 1, -1)
214+
design = designs[[1L]]
215+
maximize.mult = if (control$minimize) 1 else -1
211216
# compute q.min
212217
design_x = design[, (colnames(design) %nin% control$y.name), drop = FALSE]
213218
p.current.model = predict(object = model, newdata = design_x)$data
@@ -258,10 +263,11 @@ makeMBOInfillCritDIB = function(cb.lambda = 1, sms.eps = NULL) {
258263
if (!is.null(sms.eps))
259264
assertNumber(sms.eps, lower = 0, finite = TRUE)
260265
makeMBOInfillCrit(
261-
fun = function(points, models, control, par.set, design, iter, progress, attributes = FALSE) {
266+
fun = function(points, models, control, par.set, designs, iter, progress, attributes = FALSE) {
262267
# get ys and cb-value-matrix for new points, minimize version
263268
maximize.mult = ifelse(control$minimize, 1, -1)
264-
ys = as.matrix(design[, control$y.name]) %*% diag(maximize.mult)
269+
ys = Map(function(i, y.name) designs[[i]][, y.name], i = seq_along(control$y.name), y.name = control$y.name)
270+
ys = do.call(cbind, ys) %*% diag(maximize.mult)
265271

266272
ps = lapply(models, predict, newdata = points)
267273
means = extractSubList(ps, c("data", "response"), simplify = "cols")

R/makeMBOInfillCrit.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ makeMBOInfillCrit = function(fun, name, id,
5252
requires.se = FALSE) {
5353
assertFunction(
5454
fun,
55-
args = c("points", "models", "control", "par.set", "design", "iter", "progress", "attributes"),
55+
args = c("points", "models", "control", "par.set", "designs", "iter", "progress", "attributes"),
5656
ordered = TRUE)
5757

5858
assertString(name)

R/makeTaskSingleObj.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
# MBO control object.
1111
# @return [\code{\link[mlr]{SupervisedTask}}]
1212
makeTaskSingleObj = function(opt.path, control) {
13-
data = convertOptPathToDf(opt.path, control)
13+
data = convertToDesign(opt.path, control)
1414
data$dob = data$eol = NULL
1515

1616
# user selected to (log)-transform the y-column

0 commit comments

Comments
 (0)