Hydra Optuna Sweeper 插件使用指南:从单目标到多目标超参数优化
2026/9/16 13:54:48 网站建设 项目流程

Hydra Optuna Sweeper 插件使用指南:从单目标到多目标超参数优化

【免费下载链接】hydraHydra is a framework for elegantly configuring complex applications项目地址: https://gitcode.com/GitHub_Trending/hyd/hydra

本指南聚焦 Hydra 官方插件hydra-optuna-sweeper,系统讲解如何在 Hydra 应用中接入 Optuna,通过--multirun模式自动完成超参数搜索与优化。读完本文,你将掌握插件的安装与启用、采样器与搜索空间(search space)的完整配置语法(命令行与配置文件两种方式)、单目标与多目标优化的完整实践,以及从源码层面理解其运行机制与结果序列化逻辑。

插件简介与安装

hydra-optuna-sweeper是一个让 Hydra 应用能够调用 Optuna 进行实验参数优化的插件。Optuna 是专注于超参数优化的框架,而该插件将其采样、调优能力接入 Hydra 的--multirun批量运行机制,从而在保留 Hydra 配置管理能力的同时获得智能的搜索策略。

该插件要求hydra-core>=1.1.0,安装前先升级 Hydra 核心:

pip install hydra-core --upgrade

然后通过 pip 安装插件:

pip install hydra-optuna-sweeper --upgrade

关于配置插件的几种标准方式(如通过defaults列表、Config Store 注册等),可参考仓库文档 配置插件指南。

启用 Optuna Sweeper

在应用的配置文件(或命令行)中,将 Hydra 的 sweeper 切换为optuna

defaults: - override hydra/sweeper: optuna

也可以在命令行追加hydra/sweeper=optuna参数完成切换。

插件的默认配置定义在 config.py,其结构化配置类OptunaSweeperConf通过ConfigStore.instance().store(group="hydra/sweeper", name="optuna", ...)注册到 Hydra 的配置仓库中(见 config.py)。核心字段含义如下:

配置项类型默认值说明
samplerSamplerConfigtpe采样算法,默认 TPE(Tree-structured Parzen Estimator)
directionDirection/List[Direction]minimize优化方向,多目标时传方向列表
storageOptional[Any]nullOptuna 存储后端 URL,如sqlite:///example.db,用于持久化优化结果
study_nameOptional[str]null优化研究(study)的名称
n_trialsint20函数评估总次数
n_jobsint2并行 worker 数量
max_failure_ratefloat0.0单批参数允许的最大失败率(0~1)
paramsOptional[Dict[str, str]]null配置文件形式的搜索空间定义
custom_search_spaceOptional[str]null指向自定义搜索空间配置函数的 dotpath

可以用以下命令查看当前生效的 sweeper 全部参数:

python example/sphere.py hydra/sweeper=optuna --cfg hydra -p hydra.sweeper

示例 1:单目标优化(Sphere 基准函数)

示例目录 plugins/hydra_optuna_sweeper/example 中的sphere.py实现了一个待最小化的简单基准函数。其核心逻辑(见 sphere.py):

@hydra.main(config_path="conf", config_name="config") def sphere(cfg: DictConfig) -> float: x: float = cfg.x y: float = cfg.y if cfg.get("error", False): raise RuntimeError("cfg.error is True") return x**2 + y**2

@hydra.main()装饰的函数返回一个 float 作为目标值,我们要最小化它。该函数的最小值为 0,在x: 0, y: 0处取得。

运行优化(需在plugins/hydra_optuna_sweeper目录下):

python example/sphere.py --multirun

对应的默认配置输出(通过--cfg hydra -p hydra.sweeper可查看)如下:

# @package hydra.sweeper sampler: _target_: optuna.samplers.TPESampler seed: 123 consider_prior: true prior_weight: 1.0 consider_magic_clip: true consider_endpoints: false n_startup_trials: 10 n_ei_candidates: 24 multivariate: false warn_independent_sampling: true _target_: hydra_plugins.hydra_optuna_sweeper.optuna_sweeper.OptunaSweeper direction: minimize storage: null study_name: sphere n_trials: 20 n_jobs: 1 search_space: x: type: float low: -5.5 high: 5.5 step: 0.5 'y': type: categorical choices: - -5 - 0 - 5

对应示例仓库中的配置文件 example/conf/config.yaml:搜索空间定义在hydra.sweeper.params下,x使用range(-5.5, 5.5, step=0.5)y使用choice(-5, 0, 5)

也可以在命令行直接覆盖搜索空间参数化方式:

python example/sphere.py --multirun 'x=interval(-5.0, 5.0)' 'y=interval(0, 10)'

优化结束后,multirun日志目录下会生成optimization_results.yaml,记录最优参数与最优值:

name: optuna best_params: x: 0.0 'y': 0 best_value: 0.0

从源码看,该文件的序列化逻辑位于 optuna_sweeper.py 中OptunaSweeper类,它通过instantiate()实例化采样器(白名单限定hydra_plugins.hydra_optuna_sweeper.*optuna.samplers.*),并将实际逻辑委托给OptunaSweeperImpl。单目标情况下,sweep()结束时调用study.best_trial取出最优试验,写出best_paramsbest_value(见 optuna_sweeper.py)。

采样器(Sampler)配置

插件支持 Optuna 的全部采样器。可通过覆盖hydra/sweeper/sampler切换采样器类型,或在hydra.sweeper.sampler下调整其内部参数。

从 config.py 可以看出,插件以结构化配置方式预注册了以下采样器,均挂载在hydra/sweeper/sampler配置组下:

配置名对应 Optuna 采样器关键参数(默认值)
tpeoptuna.samplers.TPESamplerseed=Nonen_startup_trials=10n_ei_candidates=24multivariate=False
randomoptuna.samplers.RandomSamplerseed=None
cmaesoptuna.samplers.CmaEsSamplerseed=Nonesigma0=Nonerestart_strategy=None
nsgaiioptuna.samplers.NSGAIISamplerseed=Nonepopulation_size=50crossover_prob=0.9swapping_prob=0.5
gridoptuna.samplers.GridSampler搜索空间在运行时根据hydra.sweeper.params填充(_partial_=True
gpoptuna.samplers.GPSamplerseed=Nonen_startup_trials=10
qmcoptuna.samplers.QMCSamplerseed=Noneqmc_type="sobol"scramble=False

此外,由于 Optuna 4.0 移除了motpe采样器,插件保留了motpe配置名但将其_target_指向 config.py 中的raise_motpe_removed函数——一旦使用该配置会抛出明确错误,提示改用hydra/sweeper/sampler=tpe(TPESampler 已原生支持多目标优化)。

搜索空间配置(Search Space)

插件支持用 Optuna 的分布(distributions)来配置搜索空间,既可以通过命令行覆盖定义,也可以在配置文件中定义。

命令行覆盖方式

Hydra 提供了语法丰富的覆盖解析器,其词法/语法定义位于 hydra/grammar/OverrideLexer.g4 与 hydra/grammar/OverrideParser.g4。三种常用的搜索空间覆盖语法如下。

interval 覆盖

默认情况下,interval被转换为FloatDistribution。将区间端点强制为int并使用log标签,可分别得到IntDistributionLogUniformDistribution语义(在 Optuna 当前 API 中体现为IntDistribution(log=True)/FloatDistribution(log=True))。

python example/sphere.py --multirun 'x=int(interval(-5.0, 5.0))' 'y=tag(log, interval(1, 10))'

运行输出示例:

[HYDRA] Study name: sphere [HYDRA] Storage: None [HYDRA] Sampler: TPESampler [HYDRA] Directions: ['minimize'] [HYDRA] Launching 1 jobs locally [HYDRA] #0 : x=-3 y=1.6859762540733367 [HYDRA] Launching 1 jobs locally [HYDRA] #1 : x=1 y=5.237816870668193 ... [HYDRA] Best parameters: {'x': 0, 'y': 1.0929184723430116} [HYDRA] Best value: 1.1944707871885822
range 覆盖

range默认转换为IntDistribution(整数均匀分布)。如果对其应用shuffle,则改用CategoricalDistribution,即先枚举区间内的整数再打乱作为类别选择。

python example/sphere.py --multirun 'x=range(-5.0, 5.0)' 'y=shuffle(range(-5, 5))'

运行输出示例:

[HYDRA] Study name: sphere [HYDRA] Storage: None [HYDRA] Sampler: TPESampler [HYDRA] Directions: ['minimize'] [HYDRA] Launching 1 jobs locally [HYDRA] #0 : x=-3 y=-4 [HYDRA] Launching 1 jobs locally [HYDRA] #1 : x=1 y=-1 ... [HYDRA] Best parameters: {'x': 0, 'y': -1} [HYDRA] Best value: 1.0
choice 覆盖

choice被转换为CategoricalDistribution

python example/sphere.py --multirun 'x=choice(-5.0, 0.0, 5.0)' 'y=choice(0, 1, 2, 3, 4, 5)'

运行输出示例:

[HYDRA] Study name: sphere [HYDRA] Storage: None [HYDRA] Sampler: TPESampler [HYDRA] Directions: ['minimize'] [HYDRA] Launching 1 jobs locally [HYDRA] #0 : x=5.0 y=5 [HYDRA] Launching 1 jobs locally [HYDRA] #1 : x=5.0 y=2 ... [HYDRA] Best parameters: {'x': 0.0, 'y': 0} [HYDRA] Best value: 0.0

从源码看,命令行覆盖到 Optuna 分布的转换逻辑集中在 _impl.py 的create_optuna_distribution_from_override函数中:interval结合log标签与端点类型决定分布类型;range依据端点/步长是否为 float 决定FloatDistributionIntDistribution,遇shuffle则转CategoricalDistributionchoice直接构造类别分布。

配置文件方式

配置文件方式支持三类参数,字段含义如下。

int 参数
  • type:int
  • low: 下界
  • high: 上界
  • step: 离散化步长(可选)
  • log: 若为true,搜索空间转换到对数域

log=false时映射为IntUniformDistribution(即IntDistribution),否则映射为IntLogUniformDistribution(即IntDistribution(log=True))。注意:log=true时不能设置step

float 参数
  • type:float
  • low: 下界
  • high: 上界
  • step: 离散化步长
  • log: 若为true,搜索空间转换到对数域

log=false时,依据是否存在step字段分别映射为UniformDistribution(即FloatDistribution,无step)或DiscreteUniformDistribution(即FloatDistribution(step=...),有step);否则映射为LogUniformDistribution(即FloatDistribution(log=True))。同样,log=true时不能设置step

categorical 参数
  • type:categorical
  • choices: 候选值列表

映射为CategoricalDistribution

配置示例(对应--cfg hydra -p hydra.sweeper的输出):

search_space: x: type: float low: -5.5 high: 5.5 step: 0.5 'y': type: categorical choices: [-5, 0, 5]

固定参数与删除覆盖

命令行解析器(create_params_from_overrides,见 _impl.py)还会把非 sweep 覆盖视为固定参数(fixed params),把~删除覆盖透传为固定覆盖(fixed overrides)。每个 trial 生成时,_configure_trials会调用trial._suggest()采样搜索空间参数、trial.set_user_attr()设置固定参数,并检测搜索空间参数与固定参数是否重叠(重叠会抛出ValueError)。固定参数在创建 study 前会被从 Optuna 搜索空间中移除(见 _impl.py),确保它们不参与采样。

自定义搜索空间扩展

除声明式搜索空间外,插件还支持通过custom_search_space指向一个 instantiate 风格的 dotpath,其签名应为Callable[[DictConfig, optuna.trial.Trial], None],用于在每次 trial 中按 Python 逻辑动态追加参数。仓库示例 example/custom-search-space-objective.py 演示了该能力:

def configure(cfg: DictConfig, trial: Trial) -> None: x_value = trial.params["x"] trial.suggest_float( "z", x_value - cfg.max_z_difference_from_x, x_value + cfg.max_z_difference_from_x, ) trial.suggest_float("+w", 0.0, 1.0) # note +w here, not w as w is a new parameter

这里z的取值区间依赖同一个 trial 中已采样的x+w前缀表示追加一个全新参数。对应的配置见 example/custom-search-space/config.yaml,其中custom_search_space: custom-search-space-objective.configure指向该函数。源码中,该函数在 _impl.py 中通过get_method(custom_search_space)解析,并在_configure_trials中对每个 trial 调用。

示例 2:多目标优化(Binh-and-Korn 基准函数)

同一示例目录下的multi-objective.py实现了具有两个目标值的基准函数,我们要同时最小化这两个目标。其核心逻辑(见 multi-objective.py):

@hydra.main(config_path="multi-objective-conf", config_name="config") def binh_and_korn(cfg: DictConfig) -> Tuple[float, float]: x: float = cfg.x y: float = cfg.y v0 = 4 * x**2 + 4 * y**2 v1 = (x - 5) ** 2 + (y - 5) ** 2 return v0, v1

运行优化(在plugins/hydra_optuna_sweeper目录下):

python example/multi-objective.py --multirun

对应的多目标配置(通过--cfg hydra -p hydra.sweeper查看):

# @package hydra.sweeper sampler: _target_: optuna.samplers.NSGAIISampler seed: 123 population_size: 50 mutation_prob: null crossover_prob: 0.9 swapping_prob: 0.5 constraints_func: null _target_: hydra_plugins.hydra_optuna_sweeper.optuna_sweeper.OptunaSweeper direction: - minimize - minimize storage: null study_name: multi-objective n_trials: 20 n_jobs: 1 search_space: x: type: float low: 0 high: 5 step: 0.5 'y': type: float low: 0 high: 3 step: 0.5

对应的仓库配置文件为 example/multi-objective-conf/config.yaml,其中通过override hydra/sweeper/sampler: nsgaii切换为多目标演化采样器 NSGA-II,direction: [minimize, minimize]声明两个目标均最小化。

对于目标之间存在权衡(trade-off)的问题,往往不存在同时最小化两个目标的单一解,而是得到一组最优解,即 Pareto 最优解,它们展示了各目标之间可能的最佳权衡。下图蓝点即为优化结果中的 Pareto 最优解:

多目标优化示例中的 Pareto 最优解,蓝点为 Pareto 前沿

从源码看,多目标分支的处理在 _impl.py:当direction数量大于 1 时,sweeper 不再取单一best_trial,而是收集study.best_trials组成 Pareto 前沿,序列化到optimization_results.yamlsolutions字段(每个解包含paramsvalues),并在日志中输出 Pareto 解的数量与明细。相应地,被优化的任务函数必须返回与目标数量一致的 float 可转换值列表/元组(见 _impl.py),否则会抛出明确的 ValueError。

底层运行机制:sweep 主循环

理解插件的运行闭环有助于排查问题。从 optuna_sweeper.py 的sweep()实现可以看到整体流程:

  1. 合并配置文件中的params与命令行参数,经create_params_from_overrides解析为搜索空间分布、固定参数与固定覆盖;
  2. 若使用grid采样器,先将离散分布展开为候选值列表(_to_grid_sampler_choices),并把n_trials裁剪为网格组合数;
  3. 通过optuna.create_study(study_name=..., storage=..., sampler=..., directions=..., load_if_exists=True)创建或复用 study;
  4. n_jobs分批:每批调用study.ask()生成 trial,_configure_trials将分布与固定参数翻译为 Hydra 覆盖串,再交给launcher.launch()批量启动任务;
  5. 收集返回的目标值后study.tell()回报给 Optuna;单目标要求返回值可转 float,多目标要求返回值与目标数量一致;
  6. 若失败批次占比超过max_failure_rate,则触发错误并委托给JobReturn抛出真实 traceback;
  7. 循环直至n_trials耗尽,最后将optimization_results.yaml写入hydra.sweep.dir目录。

这种「study.ask / launcher.launch / study.tell」的闭环设计,使得 Optuna 的采样策略与 Hydra 的并行启动、配置隔离机制解耦,用户自定义 launcher(如 Submitit、Ray 等)也可无缝复用该优化流程。

小结

  • 通过override hydra/sweeper: optuna一行配置即可将 Hydra 应用接入 Optuna 优化;
  • 搜索空间既可在配置文件中声明(int/float/categorical三种类型),也可用interval/range/choice在命令行灵活覆盖;
  • 采样器覆盖 TPE、随机、CMA-ES、NSGA-II、网格、GP、QMC 等多种算法,默认 TPE;
  • 多目标优化通过direction列表 + NSGA-II 等采样器实现,结果以 Pareto 前沿形式写入optimization_results.yaml
  • 自定义搜索空间可通过custom_search_space挂载 Python 回调函数,满足参数间存在依赖关系的复杂场景。

相关文件索引:插件默认配置 | 插件主实现 | 底层实现 | 单目标示例 | 多目标示例

【免费下载链接】hydraHydra is a framework for elegantly configuring complex applications项目地址: https://gitcode.com/GitHub_Trending/hyd/hydra

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询