简介
本实验比较机器学习中两种流行的参数搜索算法:网格搜索(Grid Search)和连续减半法(Successive Halving)。我们将使用 Python 中的 scikit-learn 库来进行比较。这些算法用于为给定的机器学习模型找到最佳超参数。
虚拟机使用提示
虚拟机启动完成后,点击左上角切换到“笔记本”标签页,以访问 Jupyter Notebook 进行练习。
有时,你可能需要等待几秒钟让 Jupyter Notebook 完成加载。由于 Jupyter Notebook 的限制,操作验证无法自动化。
如果你在学习过程中遇到问题,随时向 Labby 提问。课程结束后提供反馈,我们会及时为你解决问题。
导入必要的库和数据集
我们首先导入本实验所需的必要库和数据集。我们将使用 scikit-learn 库来生成一个合成数据集并执行参数搜索。
from time import time
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from sklearn.svm import SVC
from sklearn import datasets
from sklearn.model_selection import GridSearchCV
from sklearn.experimental import enable_halving_search_cv
from sklearn.model_selection import HalvingGridSearchCV
rng = np.random.RandomState(0)
X, y = datasets.make_classification(n_samples=1000, random_state=rng)
gammas = [1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7]
Cs = [1, 10, 100, 1e3, 1e4, 1e5]
param_grid = {"gamma": gammas, "C": Cs}
clf = SVC(random_state=rng)
执行网格搜索
我们将使用网格搜索对支持向量分类(SVC)模型进行参数搜索。我们将使用生成的合成数据集以及在步骤 1 中生成的参数网格。
tic = time()
gs = GridSearchCV(estimator=clf, param_grid=param_grid)
gs.fit(X, y)
gs_time = time() - tic
执行连续减半法
现在,我们将使用连续减半法对步骤 2 中使用的相同 SVC 模型和数据集进行参数搜索。
tic = time()
gsh = HalvingGridSearchCV(
estimator=clf, param_grid=param_grid, factor=2, random_state=rng
)
gsh.fit(X, y)
gsh_time = time() - tic
可视化结果
现在,我们将使用热力图来可视化参数搜索算法的结果。热力图展示了支持向量分类(SVC)实例中参数组合的平均测试分数。连续减半法的热力图还展示了这些组合最后一次被使用的迭代次数。
def make_heatmap(ax, gs, is_sh=False, make_cbar=False):
"""辅助函数,用于创建热力图。"""
results = pd.DataFrame(gs.cv_results_)
results[["param_C", "param_gamma"]] = results[["param_C", "param_gamma"]].astype(
np.float64
)
if is_sh:
## 连续减半法的数据框:获取最高迭代次数下的平均测试分数值
scores_matrix = results.sort_values("iter").pivot_table(
index="param_gamma",
columns="param_C",
values="mean_test_score",
aggfunc="last",
)
else:
scores_matrix = results.pivot(
index="param_gamma", columns="param_C", values="mean_test_score"
)
im = ax.imshow(scores_matrix)
ax.set_xticks(np.arange(len(Cs)))
ax.set_xticklabels(["{:.0E}".format(x) for x in Cs])
ax.set_xlabel("C", fontsize=15)
ax.set_yticks(np.arange(len(gammas)))
ax.set_yticklabels(["{:.0E}".format(x) for x in gammas])
ax.set_ylabel("gamma", fontsize=15)
## 旋转刻度标签并设置其对齐方式。
plt.setp(ax.get_xticklabels(), rotation=45, ha="right", rotation_mode="anchor")
if is_sh:
iterations = results.pivot_table(
index="param_gamma", columns="param_C", values="iter", aggfunc="max"
).values
for i in range(len(gammas)):
for j in range(len(Cs)):
ax.text(
j,
i,
iterations[i, j],
ha="center",
va="center",
color="w",
fontsize=20,
)
if make_cbar:
fig.subplots_adjust(right=0.8)
cbar_ax = fig.add_axes([0.85, 0.15, 0.05, 0.7])
fig.colorbar(im, cax=cbar_ax)
cbar_ax.set_ylabel("mean_test_score", rotation=-90, va="bottom", fontsize=15)
fig, axes = plt.subplots(ncols=2, sharey=True)
ax1, ax2 = axes
make_heatmap(ax1, gsh, is_sh=True)
make_heatmap(ax2, gs, make_cbar=True)
ax1.set_title("连续减半法\ntime = {:.3f}s".format(gsh_time), fontsize=15)
ax2.set_title("网格搜索\ntime = {:.3f}s".format(gs_time), fontsize=15)
plt.show()
总结
我们比较了机器学习中两种流行的参数搜索算法:网格搜索(Grid Search)和连续减半法(Successive Halving)。我们使用 Python 中的 scikit-learn 库来进行比较。我们生成了一个合成数据集,并使用这两种算法对支持向量分类(SVC)模型进行参数搜索。然后,我们使用热力图可视化结果。我们发现,连续减半法算法能够在更短的时间内找到与网格搜索同样准确的参数组合。