Hyperopt 概念

注意

不再维护 Hyperopt 的开源版本。

Hyperopt 将不再预安装在 Databricks Runtime ML 17.0 及更高版本上。 Azure Databricks 建议改用 Optuna,以便获得类似的体验,并访问最新的超参数优化算法。

本文介绍使用分布式 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 TrialsSparkTrials 对象。 在目标函数中调用单机算法(如 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 会将并行度减少到等于此值。

  • timeoutfmin() 调用可使用的最大秒数。 超过此数目后,所有运行都将终止,且 fmin() 将退出。 系统将保存已完成的运行的相关信息。

实现

当定义传递给 fmin() 的目标函数 fn 时,以及在选择群集设置时,了解 SparkTrials 如何分配优化任务是很有帮助的。

在 Hyperopt 中,一次试验通常相当于在一组超参数上拟合一个模型。 Hyperopt 以迭代方式生成试用,评估它们,并重复执行。

使用 SparkTrials,群集的驱动程序节点生成新的试用,工作器节点评估这些试用。 每个试用都是由具有一个任务的 Spark 作业生成的,并在辅助角色计算机上的任务中进行评估。 如果群集设置为每个辅助角色运行多个任务,则可以在该辅助角色上同时评估多个试用。

SparkTrials 和 MLflow

Databricks Runtime ML 支持从工作器记录到 MLflow。 可以在传递给 Hyperopt 的目标函数中添加自定义日志代码。

SparkTrials 将优化结果记录为嵌套的 MLflow 运行,如下所示:

  • 主运行(也称为“父运行”):对 fmin() 的调用被记录为主运行。 如果有一个活动的运行,SparkTrials 将在此活动运行下记录,并且在 fmin() 返回时不会结束运行。 如果没有活动的运行,SparkTrials 将创建一个新的运行,在其中进行记录,并在 fmin() 返回之前结束该运行。
  • 子运行:经过测试的每个超参数设置(“试验”)都记录为主运行下的子运行。 来自工作器的 MLflow 日志记录也存储在相应的子运行下。

调用 fmin() 时,Databricks 建议使用活动 MLflow 运行管理;也就是说,将对 fmin() 的调用包装在 with mlflow.start_run(): 语句中。 这样可确保每个 fmin() 调用都记录在单独的 MLflow“主”运行中,并且可更轻松地将额外的标记、参数或指标记录到该运行中。

注意

在同一个活动 MLflow 运行中多次调用 fmin() 时,MLflow 会将这些调用记录到同一个“主”运行中。 为了解决记录的参数和标记所出现的名称冲突,MLflow 会在发生冲突的名称中追加一个 UUID。

从工作器进行日志记录时,不需要在目标函数中显式管理运行。 在目标函数中调用 mlflow.log_param("param_from_worker", x) 以将参数记录到子运行中。 你可在目标函数中记录参数、指标、标记和项目。