Hide the interface so that all samplers can use HyperbandPruner#1168
Hide the interface so that all samplers can use HyperbandPruner#1168HideakiImamura wants to merge 9 commits intooptuna:masterfrom
HyperbandPruner#1168Conversation
Codecov Report
@@ Coverage Diff @@
## master #1168 +/- ##
==========================================
- Coverage 91.02% 91.00% -0.02%
==========================================
Files 142 142
Lines 12276 12300 +24
==========================================
+ Hits 11174 11194 +20
- Misses 1102 1106 +4
Continue to review full report at Codecov.
|
HyperbandPrunerHyperbandPruner
optuna/study.py
Outdated
| self.sampler = sampler or samplers.TPESampler() | ||
| self.pruner = pruner or pruners.MedianPruner() | ||
| if isinstance(self.pruner, pruners.HyperbandPruner): | ||
| self.sampler = pruners.hyperband._HyperbandSampler(self.sampler, self.pruner) |
There was a problem hiding this comment.
How about using custom getters and setters for self.sampler (and internally store self._sampler = _HyperbandSampler)? Study.sampler is a part of the public interface after all.
There was a problem hiding this comment.
Should we test this in e.g. test_hyperband.py?
There was a problem hiding this comment.
I implemented the custom getter and setter of _HyperbandSampler in hyperband.py. I think it addresses the suggestion as pointed out.
There was a problem hiding this comment.
Hm, I'm not so sure about that. study.sampler here return an instance of _HyperbandSampler. I was imagining having study._sampler being the _HyperbandSampler while study.sampler being a custom, in this case, accessor that return study._sampler.sampler which is the original sampler object given by the user. Similarly for the setter.
There was a problem hiding this comment.
Note that we must also update Trial._suggest and Trial._init_relative_params.
hvy
left a comment
There was a problem hiding this comment.
Thanks for the PR, I left some early comments if you could take a look.
optuna/study.py
Outdated
| self.sampler = sampler or samplers.TPESampler() | ||
| self.pruner = pruner or pruners.MedianPruner() | ||
| if isinstance(self.pruner, pruners.HyperbandPruner): | ||
| self.sampler = pruners.hyperband._HyperbandSampler(self.sampler, self.pruner) |
There was a problem hiding this comment.
Should we test this in e.g. test_hyperband.py?
optuna/pruners/hyperband.py
Outdated
|
|
||
| @sampler.setter | ||
| def sampler(self, new_sampler: BaseSampler) -> None: | ||
| self._sampler = new_sampler |
There was a problem hiding this comment.
I believe we don't need custom getters/setters here as there's no logic involved.
optuna/study.py
Outdated
| self.sampler = sampler or samplers.TPESampler() | ||
| self.pruner = pruner or pruners.MedianPruner() | ||
| if isinstance(self.pruner, pruners.HyperbandPruner): | ||
| self.sampler = pruners.hyperband._HyperbandSampler(self.sampler, self.pruner) |
There was a problem hiding this comment.
Hm, I'm not so sure about that. study.sampler here return an instance of _HyperbandSampler. I was imagining having study._sampler being the _HyperbandSampler while study.sampler being a custom, in this case, accessor that return study._sampler.sampler which is the original sampler object given by the user. Similarly for the setter.
| return _BracketStudy(study, bracket_index) | ||
|
|
||
|
|
||
| class _HyperbandSampler(BaseSampler): |
There was a problem hiding this comment.
How about _BracketSampler? I think it better describes its logic/better aligned with _BracketStudy.
There was a problem hiding this comment.
I think the name of _BracketSampler is not good because the _HyperbandSampler depends on the underlying HyperbandPruner but _BracketStudy depends on each bracket of HyperbandPruner. Therefore, I think BracketStudy and _HyperbandSampler are appropriate as they are now.
|
@hvy Thank you for your insightful comments. I would like to talk about how If we implement custom getter/setter for On the other hand, if we do not implement a custom getter, then users need know about Which do you prefer in light of your experience? |
|
I decided to use the alternative implementation (#1196 ) to achieve this functionality, so I close this PR. |
Motivation
The current Hyperband implementation in Optuna imposes users who want to implement a new sampler to implement the specific logic. This annoys us because it is exactly the same logic for all samplers. This PR aims to hide the interface so that all samplers can use HyperbandPruner without any additional efforts.
Description of the changes
samplers/tpe/sampler.py.study.pywhen the pruner isHyperbandPruner._HyperbandSamplertopruners/hyperband.py.Note
This PR opposite PR #1196. If PR #1196 is merged, this PR should not be merged, and vice versa.
TODO
RandomSamplerandTPESampler.Benchmark results
(CPU: Intel Core i7-7820HQ, python: 3.6.5)
kurobakoRandomSamplerandTPESamplerHPO-bench-Naval,HPO-bench-Parkinson,HPO-bench-Protein,HPO-bench-Slice, andNASBench (A).RandomSamplerTPESampler