注意
不再维护 Hyperopt 的开源版本。
在 16.4 LTS ML 之后,用于机器学习的 Databricks Runtime 中不包含 Hyperopt。 Azure Databricks 建议使用 Optuna 来进行单节点优化,或者使用 RayTune 来获得与已弃用的 Hyperopt 分布式超参数优化功能类似的体验。 详细了解如何在 Azure Databricks 上使用 RayTune。
本文介绍使用分布式 Hyperopt 所需了解的一些概念。
本节内容:
有关如何在 Azure Databricks 中使用 Hyperopt 的示例,请参阅 Hyperopt。
fmin()
使用 fmin() 执行 Hyperopt 作业。 表中显示了 fmin() 的参数;有关详细信息,请参阅 Hyperopt 文档。 若要查看示例了解如何使用每个参数,请参阅示例笔记本。
| 参数名称 | 描述 |
|---|---|
fn |
目标函数。 Hyperopt 使用根据 space 参数中提供的超参数空间生成的值来调用此函数。 此函数可以标量值或字典的形式返回损失(有关详细信息,请参阅 Hyperopt 文档)。 此函数通常包含用于训练模型和计算损失的代码。 |
space |
定义要搜索的超参数空间。 借助 Hyperopt,可在如何定义此空间方面获得极大的灵活性。 你可选择分类选项(如算法),也可选择数值的概率分布(如均匀和对数)。 |
algo |
用于搜索超参数空间的 Hyperopt 搜索算法。 最常用的是随机搜索的 hyperopt.rand.suggest 和 TPE 的 hyperopt.tpe.suggest。 |
max_evals |
要尝试的超参数设置的数量(也就是要匹配的模型数量)。 |
max_queue_len |
Hyperopt 应提前生成的超参数设置数目。 由于 Hyperopt TPE 生成算法可能需要一些时间,因此将其数值调高至默认值 1 以上可能会有所帮助,但通常不应超过 SparkTrials 设置 parallelism。 |
trials |
Trials 或 SparkTrials 对象。 在目标函数中调用单机算法(如 scikit-learn 方法)时,请使用 SparkTrials。 在目标函数中调用分布式训练算法(如 MLlib 方法或 Horovod)时,请使用 Trials。 |
early_stop_fn |
一个可选的提前停止函数,用于确定 fmin 是否应该在到达 max_evals 之前停止。 默认为 None。 函数的输入签名为 Trials, *args,输出签名为 bool, *args。 输出的布尔值指示是否应停止。
*args 可以是任何状态,调用early_stop_fn的输出作为下一个调用的输入。
Trials 可以是 SparkTrials 对象。 使用SparkTrials时,不能保证每次尝试后都执行提前停止机制,而是通过轮询来实现。
提前停止功能示例 |
SparkTrials 类
SparkTrials 是 Databricks 开发的 API,可用于在不对 Hyperopt 代码进行其他更改的情况下分发 Hyperopt 运行。
SparkTrials 通过将试验分发到 Spark 工作节点,加速单机调优。
注意
SparkTrials 旨在并行化处理单机 ML 模型(如 scikit-learn)的计算。 对于使用分布式 ML 算法(如 MLlib 或 Horovod)创建的模型,请勿使用 SparkTrials。 在这种情况下,模型构建过程会在群集上自动并行化,你应使用默认的 Hyperopt 类 Trials。
本部分描述如何配置传递给 SparkTrials 的参数和 SparkTrials 的实现方面。
参数列表
SparkTrials 采用两个可选参数:
parallelism:要同时评估的试验的最大数量。 数字越大,您可以在更多的超参数设置上进行横向扩展测试。 Hyperopt 会基于过去的结果提议新试验,因此需在并行度和适应度之间进行权衡。 对于固定的max_evals,并行度越大,计算速度越快;但并行度较小时,由于每次迭代都可以访问更多的过去结果,因此可能会获得更好的结果。默认值:可用的 Spark 执行程序数目。 最大值:128。 如果该值大于群集配置允许的并发任务数,则
SparkTrials会将并行度减少到等于此值。timeout:fmin()调用可使用的最大秒数。 超过此数目后,所有运行都将终止,且fmin()将退出。 系统将保存已完成的运行的相关信息。
实现
当定义传递给 fn 的目标函数 fmin() 时,以及在选择群集设置时,了解 SparkTrials 如何分配优化任务是很有帮助的。
在 Hyperopt 中,一次试验通常相当于在一组超参数上拟合一个模型。 Hyperopt 以迭代方式生成试用,评估它们,并重复执行。
使用 SparkTrials,群集的驱动程序节点生成新的试用,工作器节点评估这些试用。 每次实验通过一个包含单一任务的 Spark 作业生成,并在工作机器上的任务中进行评估。 如果集群设置为每个工作节点运行多个任务,那么可以在该工作节点上同时进行多个实验的评估。
SparkTrials 和 MLflow
Databricks Runtime ML 支持从工作节点记录到 MLflow。 可以在传递给 Hyperopt 的目标函数中添加自定义日志代码。
SparkTrials 将调优结果记录为嵌套的 MLflow 运行,如下所示:
- 主运行(也称为“父运行”):对
fmin()的调用被记录为主运行。 如果有活动运行,SparkTrials将在此活动运行下记录,并且在fmin()返回时不会结束运行。 如果没有活动的运行,SparkTrials将创建一个新的运行,在其中进行记录,并在fmin()返回之前结束该运行。 - zh-CN: 子运行:测试的每个超参数设置(“试验”)都会记录成主运行下的一个子运行。 来自工作节点的 MLflow 日志记录也存储在相应的子运行下。
调用 fmin() 时,Databricks 建议使用活动 MLflow 运行管理;也就是说,将对 fmin() 的调用包装在 with mlflow.start_run(): 语句中。 这样可确保每个 fmin() 调用都记录在单独的 MLflow“主”运行中,并且可更轻松地将额外的标记、参数或指标记录到该运行中。
注意
在同一个活动 MLflow 运行中多次调用 fmin() 时,MLflow 会将这些调用记录到同一个“主”运行中。 为了解决记录的参数和标记所出现的名称冲突,MLflow 会在发生冲突的名称中追加一个 UUID。
从工作器进行日志记录时,不需要在目标函数中显式管理运行。 在目标函数中调用 mlflow.log_param("param_from_worker", x) 以将参数记录到子运行中。 你可在目标函数中记录参数、指标、标记和项目。