Closed hvy closed 3 years ago
Ready for review. I think these are the minimum changes required to support Optuna's upcoming v2.4.
Verified with the following toy example.
```python from kurobako import problem class BinhAndKornProblemFactory(problem.ProblemFactory): def specification(self): params = [ problem.Var("x", problem.ContinuousRange(0, 5)), problem.Var("y", problem.ContinuousRange(0, 3)), ] return problem.ProblemSpec( name="Binh and Korn Function", params=params, values=[ problem.Var("4 * x ** 2 + 4 * y ** 2"), problem.Var("(x - 5) ** 2 + (y - 5) ** 2"), ], ) def create_problem(self, seed): return BinhAndKornProblem() class BinhAndKornProblem(problem.Problem): def create_evaluator(self, params): return BinhAndKornEvaluator(params) class BinhAndKornEvaluator(problem.Evaluator): def __init__(self, params): self._x, self._y = params self._current_step = 0 def current_step(self): return self._current_step def evaluate(self, next_step): self._current_step = 1 return [4 * self._x ** 2 + 4 * self._y ** 2, (self._x - 5) ** 2 + (self._y - 5) ** 2] if __name__ == "__main__": runner = problem.ProblemRunner(BinhAndKornProblemFactory()) runner.run() ```
```python from kurobako import problem from kurobako import solver from kurobako.solver.optuna import OptunaSolverFactory import numpy as np import optuna class RandomSolverFactory(solver.SolverFactory): def specification(self): return solver.SolverSpec(name="Random Search") def create_solver(self, seed, problem): return RandomSolver(seed, problem) class RandomSolver(solver.Solver): def __init__(self, seed, problem): self._rng = np.random.RandomState(seed) self._problem = problem def ask(self, idg): params = [] for p in self._problem.params: if p.distribution == problem.Distribution.UNIFORM: params.append(self._rng.uniform(p.range.low, p.range.high)) else: low = np.log(p.range.low) high = np.log(p.range.high) params.append(float(np.exp(self._rng.uniform(low, high)))) trial_id = idg.generate() next_step = self._problem.last_step return solver.NextTrial(trial_id, params, next_step) def tell(self, trial): pass if __name__ == "__main__": runner = solver.SolverRunner(RandomSolverFactory()) runner.run() ```
```python from kurobako import problem from kurobako import solver from kurobako.solver.optuna import OptunaSolverFactory import numpy as np import optuna import argparse parser = argparse.ArgumentParser() parser.add_argument("--directions", nargs="+") args = parser.parse_args() def create_study(seed): sampler = optuna.integration.BoTorchSampler() return optuna.create_study(directions=args.directions, sampler=sampler) if __name__ == "__main__": factory = OptunaSolverFactory(create_study) runner = solver.SolverRunner(factory) runner.run() ```
I think that I'll publish the next version of kurkobako-py
once Optuna-v2.4 is released.
Please let me know if you need the new version soon.
Thanks for checking, it's not a hurry actually. With v2.4 sounds good, since this change depends on it. It should be released rather soon.
Multi-objective optimization (e.g. specifying
directions
instead ofdirection
inoptuna.create_study
) is becoming a first class citizen in Optuna. C.f. https://github.com/optuna/optuna/issues/1980. Some private APIs that we rely on here were updated during the course. This PR aims to fix those compatibility issues.Let me know if I'm missing something since I'm not that familiar with the internals of Kurobako. Thanks.