-
Notifications
You must be signed in to change notification settings - Fork 23
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
Custom SOBO objectives #229
Conversation
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.
Looks very promising, I let some minor comments.
from typing import List, Union | ||
|
||
import cloudpickle |
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.
cloudpickle is not a mandatory dependency, we have to guard the import here. Have a look at the empirical surrogate.
if data_model.dump is not None: | ||
self.loads(data_model.dump) | ||
else: | ||
self.f = None |
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.
The idea of not raising an error already here is to give the user the possibility to provide it at runtime?
if self.f is None: | ||
raise ValueError("No function has been provided for the strategy") | ||
return GenericMCObjective( | ||
objective=get_custom_botorch_objective( |
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.
One could think about having the possibility of output constraints here via a flag as for example in AdditiveSobo
, what do you think?
for i, feat in enumerate(outputs.get()) | ||
if feat.objective is not None # type: ignore | ||
] | ||
weights = [ |
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.
The question is if we should not just ignore the weights. If you go custom, then the weights do not apply, what do you think?
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.
Currently, the callable gets the weights and then has to decide how to handle them? I think this is even the best ..., or? Then the user can decide if he wants to use weights or not ...
) | ||
strategy2 = CustomSoboStrategy(data_model=data_model2) | ||
strategy2.loads(f_str) | ||
assert isinstance(strategy2.f, type(f)) |
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.
do we want to test here that evaluating objective of strategy
amounts to the same as evaluating the loaded objective of strategy2
?
Thanks for the suggestions. Responses to your comments:
|
From my side, this is not needed, my comment was more made as an explanation to myself in contrast to being a suggestion, because you can already setup the datamodel with
So no change needed. |
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.
LGTM!
Proposal to have custom functions for calculating SOBO objective values (c.f. AdditiveSoboStrategy, MultiplicativeSoboStrategy)
Functions can be dumped and loaded similarly to Empirical models
Still worth discussing as I think how weights for individual output features is not well handled at the moment. Happy for suggestions here. Maybe a choice for the user to have the weights be multiplied or be exponents? Or even more different: the function provided by the user should take the callables and weights as arguments so it becomes completely customisable.