Skip to content

Commit f03d02a

Browse files
author
Sarah Krebs
committed
Correct incumbent calculation when single objective should be maximized
1 parent edcbd3f commit f03d02a

File tree

2 files changed

+33
-24
lines changed

2 files changed

+33
-24
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
- Fix lower bounds of dependency versions.
1111
- Allow to load multi-objective SMAC3v2 and add example (#69).
1212
- Allow to load runs with multiple seeds and add examples (#70).
13+
- Correct incumbent calculation when single objective should be maximized.
1314
- Do not disable existing loggers.
1415
- Update author email.
1516
- Add exit button which first deletes running jobs and then terminates DeepCave.

deepcave/runs/__init__.py

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -951,55 +951,70 @@ def get_incumbent(
951951
RuntimeError
952952
If no incumbent was found.
953953
"""
954-
min_cost = np.inf
954+
if isinstance(objectives, Objective):
955+
single_objective = objectives
956+
elif isinstance(objectives, list) and len(objectives) == 1:
957+
single_objective = objectives[0]
958+
else:
959+
single_objective = None
960+
961+
if single_objective is not None and single_objective.optimize == "upper":
962+
best_cost = -np.inf
963+
else:
964+
best_cost = np.inf
955965
best_config_id = None
956966

957967
results = self.get_all_costs(
958968
budget=budget, statuses=statuses, seed=seed, selected_ids=selected_ids
959969
)
960970

961971
seed_count = {}
962-
for config_id, costs in results.items():
963-
seed_count[config_id] = len(costs)
972+
for config_id, seed_costs_dict in results.items():
973+
seed_count[config_id] = len(seed_costs_dict)
964974
max_seed_count = max(seed_count.values())
965975

966-
for config_id, costs in results.items():
976+
for config_id, seed_costs_dict in results.items():
967977
# If there are multiple seeds, only configurations evaluated on all seeds are
968978
# considered. From these configurations, the one with the highest average objective
969979
# value over the seeds is considered as the incumbent.
970980
if max_seed_count > 1:
971-
if len(costs) < max_seed_count:
981+
if len(seed_costs_dict) < max_seed_count:
972982
continue
973983

974984
# Get average over all seeds
975985
config_costs = np.zeros([max_seed_count, len(self.get_objectives())])
976-
for i, (_, seed_cost) in enumerate(costs.items()):
977-
config_costs[i] = seed_cost
986+
for i, (_, seed_costs) in enumerate(seed_costs_dict.items()):
987+
config_costs[i] = seed_costs
978988
avg_cost = np.mean(config_costs, axis=0)
979989

980990
# If there is only one seed, the costs can be used directly
981991
else:
982-
avg_cost = [*costs.values()][0]
992+
avg_cost = [*seed_costs_dict.values()][0]
983993

984994
# If there are multiple objectives, the costs are merged to one cost value
985-
if isinstance(objectives, list) and len(objectives) > 1:
995+
if single_objective is None:
986996
cost = self.merge_costs(avg_cost, objectives)
987997
else:
988998
cost = avg_cost[0]
989999

9901000
if cost is None:
9911001
continue
9921002

993-
if cost < min_cost:
994-
min_cost = cost
995-
best_config_id = config_id
1003+
if single_objective is not None and single_objective.optimize == "upper":
1004+
if cost > best_cost:
1005+
best_cost = cost
1006+
best_config_id = config_id
1007+
else:
1008+
if cost < best_cost:
1009+
best_cost = cost
1010+
best_config_id = config_id
9961011

9971012
if best_config_id is None:
9981013
raise RuntimeError("No incumbent found.")
9991014

10001015
config = self.get_config(best_config_id)
10011016
config = Configuration(self.configspace, config)
1002-
normalized_cost = min_cost
1017+
normalized_cost = best_cost
10031018

10041019
return config, normalized_cost
10051020

@@ -1168,19 +1183,12 @@ def get_trajectory(
11681183
for i, (id, _) in enumerate(order):
11691184
trial = self.history[id]
11701185

1171-
# All budgets should should be used
1172-
if budget != COMBINED_BUDGET:
1173-
# Only consider selected/last budget
1174-
if trial.budget != budget:
1175-
continue
1176-
1177-
if seed is not None:
1178-
if trial.seed != seed:
1179-
continue
1180-
11811186
# Get the incumbent over all trials up to this point
11821187
_, cost = self.get_incumbent(
1183-
objective, budget, selected_ids=[selected_id for selected_id, _ in order[: i + 1]]
1188+
objectives=objective,
1189+
budget=budget,
1190+
seed=seed,
1191+
selected_ids=[selected_id for selected_id, _ in order[: i + 1]],
11841192
)
11851193
if cost is None:
11861194
continue

0 commit comments

Comments
 (0)