はじめに
この実験では、機械学習における 2 つの人気のあるパラメータ探索アルゴリズム:グリッド探索(Grid Search)と逐次半分法(Successive Halving)を比較します。比較を行うために、Python の scikit-learn ライブラリを使用します。これらのアルゴリズムは、与えられた機械学習モデルの最適なハイパーパラメータを見つけるために使用されます。
VM のヒント
VM の起動が完了したら、左上隅をクリックしてノートブックタブに切り替え、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):
"""Helper to make a heatmap."""
results = pd.DataFrame(gs.cv_results_)
results[["param_C", "param_gamma"]] = results[["param_C", "param_gamma"]].astype(
np.float64
)
if is_sh:
## SH dataframe: get mean_test_score values for the highest iter
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)
## Rotate the tick labels and set their alignment.
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("Successive Halving\ntime = {:.3f}s".format(gsh_time), fontsize=15)
ax2.set_title("GridSearch\ntime = {:.3f}s".format(gs_time), fontsize=15)
plt.show()
まとめ
機械学習における 2 つの一般的なパラメータ探索アルゴリズム:グリッド探索と逐次半分法を比較しました。比較を行うために Python の scikit-learn ライブラリを使用しました。合成データセットを生成し、両方のアルゴリズムを使って SVC モデルに対してパラメータ探索を行いました。その後、ヒートマップを使って結果を可視化しました。逐次半分法アルゴリズムは、はるかに短い時間で、グリッド探索と同じくらい正確なパラメータの組み合わせを見つけることができることがわかりました。