连续减半迭代

Beginner

This tutorial is from open-source community. Access the source code

简介

在本实验中,你将学习如何使用连续减半搜索方法,从多个候选参数中迭代地选择最佳参数组合。此方法在 Scikit-learn 库的 HalvingGridSearchCVHalvingRandomSearchCV 类中实现。本实验将使用 HalvingRandomSearchCV 类。

虚拟机使用提示

虚拟机启动完成后,点击左上角切换到 笔记本 标签页,以访问 Jupyter Notebook 进行练习。

有时,你可能需要等待几秒钟让 Jupyter Notebook 完成加载。由于 Jupyter Notebook 的限制,操作验证无法自动化。

如果你在学习过程中遇到问题,请随时向 Labby 提问。课程结束后提供反馈,我们将立即为你解决问题。

导入所需库

本实验将使用以下库:pandasnumpymatplotlibsklearn.datasetsRandomForestClassifierrandintHalvingRandomSearchCV。使用以下代码导入它们:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.ensemble import RandomForestClassifier
from scipy.stats import randint
from sklearn.experimental import enable_halving_search_cv
from sklearn.model_selection import HalvingRandomSearchCV

加载数据集

sklearn.datasets 模块中的 make_classification 函数用于生成一个分类数据集。该数据集包含 400 个样本和 12 个特征。加载数据集的代码如下:

rng = np.random.RandomState(0)
X, y = datasets.make_classification(n_samples=400, n_features=12, random_state=rng)

定义参数空间

定义一个字典 param_dist,其中包含要搜索的超参数及其各自的值。超参数有 max_depthmax_featuresmin_samples_splitbootstrapcriterionmax_featuresmin_samples_split 的搜索范围使用 scipy.stats 模块中的 randint 函数定义。定义参数空间的代码如下:

param_dist = {
    "max_depth": [3, None],
    "max_features": randint(1, 6),
    "min_samples_split": randint(2, 11),
    "bootstrap": [True, False],
    "criterion": ["gini", "entropy"],
}

创建一个减半随机搜索对象

创建一个 HalvingRandomSearchCV 对象,用于在参数空间中进行搜索。该对象接受以下参数:

  • estimator:要优化的估计器
  • param_distributions:要搜索的参数空间
  • factor:每次迭代中候选数量减少的因子
  • random_state:用于搜索的随机状态

创建该对象的代码如下:

clf = RandomForestClassifier(n_estimators=20, random_state=rng)
rsh = HalvingRandomSearchCV(
    estimator=clf, param_distributions=param_dist, factor=2, random_state=rng
)

拟合减半随机搜索对象

使用 fit 方法将 HalvingRandomSearchCV 对象拟合到数据集上。拟合该对象的代码如下:

rsh.fit(X, y)

分析结果

搜索对象的 cv_results_ 属性包含搜索结果。使用以下代码将其转换为 pandas 数据框:

results = pd.DataFrame(rsh.cv_results_)

通过将 params 列转换为字符串来创建 params_str 列。删除具有相同 params_striter 值的重复行:

results["params_str"] = results.params.apply(str)
results.drop_duplicates(subset=("params_str", "iter"), inplace=True)

然后,使用 pivot 方法根据迭代次数和参数组合对平均测试分数进行透视:

mean_scores = results.pivot(
    index="iter", columns="params_str", values="mean_test_score"
)

最后,使用以下代码绘制迭代过程中的平均测试分数:

ax = mean_scores.plot(legend=False, alpha=0.6)

labels = [
    f"iter={i}\nn_samples={rsh.n_resources_[i]}\nn_candidates={rsh.n_candidates_[i]}"
    for i in range(rsh.n_iterations_)
]

ax.set_xticks(range(rsh.n_iterations_))
ax.set_xticklabels(labels, rotation=45, multialignment="left")
ax.set_title("Scores of candidates over iterations")
ax.set_ylabel("mean test score", fontsize=15)
ax.set_xlabel("iterations", fontsize=15)
plt.tight_layout()
plt.show()

结果解读

该图表展示了各候选方案在迭代过程中的平均测试分数。在第一次迭代时,所有候选方案都使用少量资源进行评估。在第二次迭代时,仅对表现最佳的一半候选方案使用两倍的资源进行评估。此过程会一直重复,直到最后一次迭代,此时仅剩下 2 个候选方案。最佳候选方案即为在最后一次迭代中平均测试分数最高的那个。

总结

在本实验中,你学习了如何使用连续减半搜索方法,从多个候选方案中迭代地选择最佳参数组合。我们使用了 Scikit-learn 库中的 HalvingRandomSearchCV 类来实现该搜索方法。通过绘制迭代过程中的平均测试分数图,对搜索结果进行了分析和解读。