并行化 Hyperopt 超参数优化

注意

不再维护 Hyperopt 的开源版本。

在 16.4 LTS ML 之后,用于机器学习的 Databricks Runtime 中不包含 Hyperopt。 Azure Databricks 建议使用 Optuna 来进行单节点优化,或者使用 RayTune 来获得与已弃用的 Hyperopt 分布式超参数优化功能类似的体验。 详细了解如何在 Azure Databricks 上使用 RayTune

此示例笔记本演示如何使用 Hyperopt 和 SparkTrials 将单机超参数优化缩放到Azure Databricks群集。 优化鸢尾花数据集上的 scikit-learn 的 SVM 分类器,首先生成单机 fmin() 工作流,然后将其在 Spark 计算节点上并行化,使用 MLflow 自动跟踪每个试验。

导入所需的包和加载数据集

from sklearn.datasets import load_iris
from sklearn.model_selection import cross_val_score
from sklearn.svm import SVC

from hyperopt import fmin, tpe, hp, SparkTrials, STATUS_OK, Trials

# If you are running Databricks Runtime for Machine Learning, `mlflow` is already installed and you can skip the following line.
import mlflow
# Load the iris dataset from scikit-learn
iris = iris = load_iris()
X = iris.data
y = iris.target

第 1 部分。 单机 Hyperopt 工作流

下面是 Hyperopt 工作流中的步骤:

  1. 定义要最小化的函数。
  2. 在超参数上定义搜索空间。
  3. 选择搜索算法。
  4. 使用 Hyperopt fmin()运行优化算法。

有关详细信息,请参阅 Hyperopt 文档

定义要最小化的函数

在此示例中,我们使用支持向量机分类器。 目标是查找正则化参数 C的最佳值。

Hyperopt 工作流的大部分代码都位于目标函数中。 此示例使用 scikit-learn 中的支持向量分类器

如果群集使用 Databricks Runtime 11.3 ML,请编辑支持向量分类器以采用位置参数 clf = SVC(C)

def objective(C):
    # Create a support vector classifier model
    clf = SVC(C=C)

    # Use the cross-validation accuracy to compare the models' performance
    accuracy = cross_val_score(clf, X, y).mean()

    # Hyperopt tries to minimize the objective function. A higher accuracy value means a better model, so you must return the negative accuracy.
    return {'loss': -accuracy, 'status': STATUS_OK}

在超参数上定义搜索空间

有关定义搜索空间和参数表达式的详细信息,请参阅 Hyperopt 文档

search_space = hp.lognormal('C', 0, 1.0)

选择搜索算法

两个主要选择是:

  • hyperopt.tpe.suggest:Parzen 估算器树,一种贝叶斯方法,它以迭代和自适应方式选择新的超参数设置,以基于过去的结果进行探索
  • hyperopt.rand.suggest:随机搜索,这是一种非自适应方法,用于对搜索空间进行采样
algo=tpe.suggest

使用 Hyperopt 运行优化算法 fmin()

max_evals 设置为超参数空间中要测试的最大点数,即要拟合和评估的最大模型数。

argmin = fmin(
  fn=objective,
  space=search_space,
  algo=algo,
  max_evals=16)
# Print the best value found for C
print("Best value found: ", argmin)

第 2 部分。 使用 Apache Spark 和 MLflow 进行分布式优化

若要分发调优,请在fmin()中添加一个额外的参数:一个名为TrialsSparkTrials的类。

SparkTrials 采用 2 个可选参数:

  • parallelism:要同时拟合和评估的模型个数。 默认值为可用的 Spark 任务槽数。
  • timeout:可以运行的最大时间(以秒 fmin() 为单位)。 默认值不是最长时间限制。

此示例使用 Cmd 7 中定义的非常简单的目标函数。 在这种情况下,函数运行得很快,启动 Spark 作业的开销在计算时间中占据主导地位,因此在分布式情况下,计算所需的时间更长。 对于典型的实际问题,目标函数更加复杂,使用 SparkTrails 来分配计算,比单机调优更快。

默认情况下启用自动 MLflow 跟踪。 若要使用它,如示例中所示,请先调用mlflow.start_run(),然后调用fmin()

from hyperopt import SparkTrials

# To display the API documentation for the SparkTrials class, uncomment the following line.
# help(SparkTrials)
spark_trials = SparkTrials()

with mlflow.start_run():
  argmin = fmin(
    fn=objective,
    space=search_space,
    algo=algo,
    max_evals=16,
    trials=spark_trials)
# Print the best value found for C
print("Best value found: ", argmin)

若要查看与笔记本关联的 MLflow 试验,请单击右上角笔记本上下文栏中的 “试验 ”图标。 在那里,可以查看所有运行。 若要查看 MLflow UI 中的运行,请单击 试验运行旁边的图标。

检查调整 C的效果:

  1. 选择生成的运行,然后单击“ 比较”。
  2. 在散点图中,为 X 轴选择 C ,为 Y 轴选择 损失

在笔记本的最后一个单元格中执行操作后,MLflow UI 应显示:

Hyperopt MLflow 演示

示例笔记本

并行化 Hyperopt 超参数优化

获取笔记本