Skip to content

Commit 9597c22

Browse files
mfeurerKEggensperger
authored andcommitted
First draft of multi-objective optimization (#1455)
* First draft of multi-objective optimization Co-authored-by: Katharina Eggensperger <[email protected]> * Feedback from Eddie * Make metric internally always a list * Fix most examples * Take further feedback into account * Fix unit tests * Fix one more example * Add multi-objective example * Simplify internal interface * Act on further feedback * Fix bug * Update cv_results_ for multi-objective sklearn compliance * Update leaderboard for multi-objective optimization * Include Feedback from Katharina * Take offline feedback into account * Take offline feedback into account * Eddie's feedback * Fix metadata generation unit test * Test for metrics with the same name * Fix? * Test CV results * Test leaderboard for multi-objective optimization * Last batch of unit tests added * Include Eddie's feedback Co-authored-by: Katharina Eggensperger <[email protected]>
1 parent a5610d5 commit 9597c22

23 files changed

+1421
-583
lines changed

autosklearn/automl.py

+96-48
Large diffs are not rendered by default.

autosklearn/ensemble_builder.py

+13-13
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
from autosklearn.automl_common.common.utils.backend import Backend
3131
from autosklearn.constants import BINARY_CLASSIFICATION
3232
from autosklearn.ensembles.ensemble_selection import EnsembleSelection
33-
from autosklearn.metrics import Scorer, calculate_loss, calculate_score
33+
from autosklearn.metrics import Scorer, calculate_losses, calculate_scores
3434
from autosklearn.util.logging_ import get_named_client_logger
3535
from autosklearn.util.parallel import preload_modules
3636

@@ -999,13 +999,13 @@ def compute_loss_per_model(self):
999999
# actually read the predictions and compute their respective loss
10001000
try:
10011001
y_ensemble = self._read_np_fn(y_ens_fn)
1002-
loss = calculate_loss(
1002+
loss = calculate_losses(
10031003
solution=self.y_true_ensemble,
10041004
prediction=y_ensemble,
10051005
task_type=self.task_type,
1006-
metric=self.metric,
1006+
metrics=[self.metric],
10071007
scoring_functions=None,
1008-
)
1008+
)[self.metric.name]
10091009

10101010
if np.isfinite(self.read_losses[y_ens_fn]["ens_loss"]):
10111011
self.logger.debug(
@@ -1511,34 +1511,34 @@ def _add_ensemble_trajectory(self, train_pred, valid_pred, test_pred):
15111511

15121512
performance_stamp = {
15131513
"Timestamp": pd.Timestamp.now(),
1514-
"ensemble_optimization_score": calculate_score(
1514+
"ensemble_optimization_score": calculate_scores(
15151515
solution=self.y_true_ensemble,
15161516
prediction=train_pred,
15171517
task_type=self.task_type,
1518-
metric=self.metric,
1518+
metrics=[self.metric],
15191519
scoring_functions=None,
1520-
),
1520+
)[self.metric.name],
15211521
}
15221522
if valid_pred is not None:
15231523
# TODO: valid_pred are a legacy from competition manager
15241524
# and this if never happens. Re-evaluate Y_valid support
1525-
performance_stamp["ensemble_val_score"] = calculate_score(
1525+
performance_stamp["ensemble_val_score"] = calculate_scores(
15261526
solution=self.y_valid,
15271527
prediction=valid_pred,
15281528
task_type=self.task_type,
1529-
metric=self.metric,
1529+
metrics=[self.metric],
15301530
scoring_functions=None,
1531-
)
1531+
)[self.metric.name]
15321532

15331533
# In case test_pred was provided
15341534
if test_pred is not None:
1535-
performance_stamp["ensemble_test_score"] = calculate_score(
1535+
performance_stamp["ensemble_test_score"] = calculate_scores(
15361536
solution=self.y_test,
15371537
prediction=test_pred,
15381538
task_type=self.task_type,
1539-
metric=self.metric,
1539+
metrics=[self.metric],
15401540
scoring_functions=None,
1541-
)
1541+
)[self.metric.name]
15421542

15431543
self.ensemble_history.append(performance_stamp)
15441544

autosklearn/ensembles/ensemble_selection.py

+16-26
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Any, Dict, List, Optional, Tuple, Union, cast
1+
from typing import Any, Dict, List, Optional, Tuple, Union
22

33
import random
44
from collections import Counter
@@ -8,7 +8,7 @@
88

99
from autosklearn.constants import TASK_TYPES
1010
from autosklearn.ensembles.abstract_ensemble import AbstractEnsemble
11-
from autosklearn.metrics import Scorer, calculate_loss
11+
from autosklearn.metrics import Scorer, calculate_losses
1212
from autosklearn.pipeline.base import BasePipeline
1313

1414

@@ -164,18 +164,13 @@ def _fast(
164164
out=fant_ensemble_prediction,
165165
)
166166

167-
# calculate_loss is versatile and can return a dict of losses
168-
# when scoring_functions=None, we know it will be a float
169-
losses[j] = cast(
170-
float,
171-
calculate_loss(
172-
solution=labels,
173-
prediction=fant_ensemble_prediction,
174-
task_type=self.task_type,
175-
metric=self.metric,
176-
scoring_functions=None,
177-
),
178-
)
167+
losses[j] = calculate_losses(
168+
solution=labels,
169+
prediction=fant_ensemble_prediction,
170+
task_type=self.task_type,
171+
metrics=[self.metric],
172+
scoring_functions=None,
173+
)[self.metric.name]
179174

180175
all_best = np.argwhere(losses == np.nanmin(losses)).flatten()
181176

@@ -211,18 +206,13 @@ def _slow(self, predictions: List[np.ndarray], labels: np.ndarray) -> None:
211206
for j, pred in enumerate(predictions):
212207
ensemble.append(pred)
213208
ensemble_prediction = np.mean(np.array(ensemble), axis=0)
214-
# calculate_loss is versatile and can return a dict of losses
215-
# when scoring_functions=None, we know it will be a float
216-
losses[j] = cast(
217-
float,
218-
calculate_loss(
219-
solution=labels,
220-
prediction=ensemble_prediction,
221-
task_type=self.task_type,
222-
metric=self.metric,
223-
scoring_functions=None,
224-
),
225-
)
209+
losses[j] = calculate_losses(
210+
solution=labels,
211+
prediction=ensemble_prediction,
212+
task_type=self.task_type,
213+
metrics=[self.metric],
214+
scoring_functions=None,
215+
)[self.metric.name]
226216
ensemble.pop()
227217
best = np.nanargmin(losses)
228218
ensemble.append(predictions[best])

0 commit comments

Comments
 (0)