-
-
Notifications
You must be signed in to change notification settings - Fork 230
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix Multi-Objective cache #872
Conversation
""" | ||
Transform a multi-objective loss to a single loss. | ||
|
||
Parameters | ||
---------- | ||
values (np.ndarray): Normalized values. | ||
values : list[float] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would argue, that the normalization is part of the aggregation strategy and should probably be moved here instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see a reason why the values should not be normalized here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Normalization returns a one vector if budget = None. This may not be intuitive and desirable.
-
we might want to make normalization part of the aggregation strategy instead (making it explicit)
-
We could as well call the aggregationStrategy ScalarizationStrategy, implying that we want to make a scalar objective from the multi objective
|
||
# Normalize st all theta values sum up to 1 | ||
theta = theta / (np.sum(theta) + 1e-10) | ||
|
||
# Weight the values | ||
theta_f = theta * values | ||
|
||
return np.max(theta_f, axis=1) + self.rho * np.sum(theta_f, axis=1) | ||
return np.max(theta_f, axis=0) + self.rho * np.sum(theta_f, axis=0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm somewhat surprised to see that the summation over an axis changes without a respective test changing. Does this mean that there is no test for ParEGO?
numerator = data - min_value | ||
normalized_values.append(numerator / denominator) | ||
cost = p / q | ||
costs += [cost] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not costs.append()
?
## Features * [BOinG](https://arxiv.org/abs/2111.05834): A two-stage Bayesian optimization approach to allow the optimizer to focus on the most promising regions. * [TurBO](https://arxiv.org/abs/1910.01739): Reimplementaion of TurBO-1 algorithm. * Updated pSMAC: Can pass arbitrary SMAC facades now. Added example and fixed tests. ## Improvements * Enabled caching for multi-objectives (#872). Costs are now normalized in `get_cost` or optionally in `average_cost`/`sum_cost`/`min_cost` to receive a single float value. Therefore, the cached cost values do not need to be updated everytime a new entry to the runhistory was added. ## Interface changes * We changed the location of Gaussian processes and random forests. They are in the folders `epm/gaussian_process` and `epm/random_forest` now. * Also, we restructured the optimizer folder and therefore the location of the acquisition functions and configuration chooser. * Multi-objective functions are located in the folder `multi_objective`. * pSMAC facade was moved to the facade directory. Co-authored-by: Difan Deng <[email protected]> Co-authored-by: Eddie Bergman <[email protected]> Co-authored-by: Carolin Benjamins <[email protected]> Co-authored-by: timruhkopf <[email protected]>
Version 1.4.0 (automl#730, automl#855, automl#869, automl#872)
Closes #852.
I slightly rearranged the runhistory so that it's more intuitive.
What else did I do?
average_cost/min_cost/sum_cost
return a list of floats (instead of a float) now.For example, for
average_cost
, each objective is averaged separately. Imagine you have two runs with [100, 200] and [0, 0] then you'd get [50, 100]. However, once you callget_cost
, this (cached) [50, 100] is normalized based on all passed entries. That means thatget_cost
returns a float in the end.Edit: I added an argument in
average_cost/min_cost/sum_cost
to return the normalized (single float) values. Makes the code easier and scalable.One more thing which really is weird: In the runhistory2epm we iterate over the run dictionary (runkey, runvalue). But here we use the
run.cost
directly and hence we have to callnormalize_costs
in the case of MO again. I wonder why this is done this way? @mfeurer