注意
前往末尾 以下载完整的示例代码。
如何在 OptunaHub 中实现您的基准问题(高级)
OptunaHub 提供了 optunahub.benchmarks
模块用于实现基准问题。在本教程中,我们将解释如何使用 optunahub.benchmarks
来实现复杂的基准问题,例如具有动态搜索空间的问题。
对于简单基准问题的实现,请参考 如何在 OptunaHub 中实现您的基准问题(基础)。
实现具有动态搜索空间的问题
在这里,我们来实现一个具有动态搜索空间的问题。
首先,导入 optuna 和其他所需的模块。
from __future__ import annotations
import optuna
from optunahub.benchmarks import BaseProblem
from optunahub.benchmarks import ConstrainedMixin
接下来,通过继承 BaseProblem
类来定义您自己的问题类。为了实现具有动态搜索空间的问题,必须重写 __call__(self, trial: optuna.Trial)
方法,以便我们可以通过 define-by-run 的方式定义动态搜索空间。请注意,还必须实现 directions
属性。
class DynamicProblem(BaseProblem):
def __call__(self, trial: optuna.Trial) -> float:
x = trial.suggest_float("x", -5, 5)
if x < 0:
# Parameter `y` exists only when `x` is negative.
y = trial.suggest_float("y", -5, 5)
return x**2 + y
else:
return x**2
@property
def directions(self) -> list[optuna.study.StudyDirection]:
return [optuna.study.StudyDirection.MINIMIZE]
@property
def search_space(self) -> dict[str, optuna.distributions.BaseDistribution]:
# You can implement this property as you like, or leave it unimplemented (``BaseProblem`` provides this default behavior).
raise NotImplementedError
def evaluate(self, params: dict[str, float]) -> float:
# You can implement this method as you like, or leave it unimplemented (``BaseProblem`` provides this default behavior).
raise NotImplementedError
当搜索空间是动态的时,search_space
和 evaluate
的实现并非易事。然而,由于 __call__(self, trial: optuna.Trial)
内部不必依赖 evaluate
方法和 search_space
属性,它们的实现取决于用户。如果可能,您可以提供它们的实现,但这并非使您的基准问题起作用的必要条件。请注意,如果您不实现它们,调用它们将导致 NotImplementedError
。
然后,您可以像往常一样使用 Optuna 优化问题。
dynamic_problem = DynamicProblem()
study = optuna.create_study(directions=dynamic_problem.directions)
study.optimize(dynamic_problem, n_trials=20)
实现带约束的问题
在这里,我们来实现一个带约束的问题。为了实现带约束的问题,除了继承 BaseProblem
类之外,还需要继承 ConstrainedMixin
类,并实现 evaluate_constraints
方法。evaluate_constraints
方法根据输入的参数字典评估约束函数,并返回一个约束值列表。然后,ConstrainedMixin
在内部为 Optuna 采样器定义了 constraints_func
方法。
class ConstrainedProblem(ConstrainedMixin, DynamicProblem):
def evaluate_constraints(self, params: dict[str, float]) -> tuple[float, float]:
x = params["x"]
c0 = x - 2
if "y" not in params:
c1 = 0.0 # c1 <= 0, so c1 is satisfied in this case.
return c0, c1
else:
y = params["y"]
c1 = x + y - 3
return c0, c1
然后,您可以像往常一样使用 Optuna 优化问题。请不要忘记将 constraints_func 参数设置为要使用的采样器。
problem = ConstrainedProblem()
sampler = optuna.samplers.TPESampler(
constraints_func=problem.constraints_func
) # Pass the constraints_func to the sampler.
study = optuna.create_study(sampler=sampler, directions=problem.directions)
study.optimize(problem, n_trials=20)
/opt/hostedtoolcache/Python/3.11.12/x64/lib/python3.11/site-packages/optuna/_experimental.py:31: ExperimentalWarning:
Argument ``constraints_func`` is an experimental feature. The interface can change in the future.
实现您自己的基准问题后,您可以将其注册到 OptunaHub。关于如何将您的基准问题注册到 OptunaHub,请参阅 如何将您的包注册到 OptunaHub。
脚本总运行时间: (0 分 0.086 秒)