Skip to content
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

Support constrained optimization in best_trial #5426

Merged

Conversation

not522
Copy link
Member

@not522 not522 commented May 1, 2024

Motivation

Resolve #5184.
This change breaks backward compatibility but results in intuitive behavior for constrained optimization.

Description of the changes

best_trial: We need to check all feasible trials to support constrained optimization in best_trial while keeping the current storage schema. However, there is a concern about speed degradation if all trials are checked, so the best_trial is first determined without regard to constraints, and all trials are checked only if the best-valued trial violates constraints.

best_trials: Since best_trials needs to calculate the Pareto front, the impact of filtering on speed should be small.

@not522 not522 added the compatibility Change that breaks compatibility. label May 1, 2024
@not522
Copy link
Member Author

not522 commented May 1, 2024

@HideakiImamura @nabenabe0928 Could you review this PR?

Copy link
Collaborator

@nabenabe0928 nabenabe0928 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the PR, I left some comments!

# violation value in the best-valued trial.
constraints = best_trial.system_attrs.get(_CONSTRAINTS_KEY)
if constraints is not None and any([x > 0.0 for x in constraints]):
complete_trials = self.get_trials(deepcopy=False, states=[TrialState.COMPLETE])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to use cache here or would it be buggy because some trials might finish between the last query and this query of self.get_trials?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my understanding, the cache in _get_trials is taken at the beginning of the trial, so it is not appropriate to use that cache in best_trial. It can be a strange value since best_trial is expected to be called after the trial.

feasible_trials = []
for trial in trials:
constraints = trial.system_attrs.get(_CONSTRAINTS_KEY)
if constraints is None or all([x <= 0.0 for x in constraints]):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TPE and NSGA-II consider constraints is None worse than trials with constraints is not None, implying that constraints is None is infeasible.

Suggested change
if constraints is None or all([x <= 0.0 for x in constraints]):
if constraints is not None and all(x <= 0.0 for x in constraints):

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your suggestion. I've updated it and _multi_objective.py's one. There is some duplicate code, but I will do the refactoring in another PR.

not522 and others added 3 commits May 8, 2024 11:50
Co-authored-by: Shuhei Watanabe <47781922+nabenabe0928@users.noreply.github.com>
Copy link
Member

@HideakiImamura HideakiImamura left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Almost, LGTM. I have one comment. Could you take a look?

@@ -58,6 +59,15 @@ class _ThreadLocalStudyAttribute(threading.local):
cached_all_trials: list["FrozenTrial"] | None = None


def _get_feasible_trials(trials: Sequence[FrozenTrial]) -> list[FrozenTrial]:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that this is identical to that of study/_multi_objective.py. Can we remove either one?

Copy link
Collaborator

@nabenabe0928 nabenabe0928 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM after addressing the mamu's comment!

@nabenabe0928 nabenabe0928 removed their assignment May 10, 2024
Copy link
Contributor

This pull request has not seen any recent activity.

@github-actions github-actions bot added the stale Exempt from stale bot labeling. label May 19, 2024
@not522
Copy link
Member Author

not522 commented May 20, 2024

I added _constrained_optimization.py and moved _get_feasible_trials. What do you think?

@github-actions github-actions bot removed the stale Exempt from stale bot labeling. label May 20, 2024
Copy link
Member

@HideakiImamura HideakiImamura left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the late. LGTM.

@HideakiImamura HideakiImamura merged commit c38896c into optuna:master May 21, 2024
14 checks passed
@HideakiImamura HideakiImamura added this to the v4.0.0 milestone May 21, 2024
@not522 not522 deleted the best-trial-constrained-optimization branch May 21, 2024 02:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compatibility Change that breaks compatibility.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support best value with constraint
3 participants