[機械学習のはじめ方] Part23: グリッドサーチとランダムサーチ

機械学習

機械学習モデルの性能は、「ハイパーパラメータ」と呼ばれる設定値によって大きく左右されます。最適なハイパーパラメータを見つける作業は「ハイパーパラメータチューニング」と呼ばれ、モデルの精度を最大限に引き出すために非常に重要です。

今回は、ハイパーパラメータチューニングの代表的な手法であるグリッドサーチ (Grid Search)ランダムサーチ (Random Search) について、初心者の方にも分かりやすく解説します。それぞれの仕組み、メリット・デメリット、そしてPythonのライブラリ scikit-learn を使った実装例を見ていきましょう!😊

ハイパーパラメータって何? 🤔

機械学習モデルには、大きく分けて2種類のパラメータがあります。

  • パラメータ: モデルがデータから学習する値(例: 線形回帰の係数、ニューラルネットワークの重み)。
  • ハイパーパラメータ: モデルの学習プロセスや構造を制御するために、人間が事前に設定する値(例: 学習率、決定木の深さ、k近傍法のkの値)。

ハイパーパラメータはモデル自身が学習するわけではないため、私たちが試行錯誤して最適な値を見つける必要があります。これがハイパーパラメータチューニングの目的です。

網羅的に探す!グリッドサーチ (Grid Search) exhaustive

グリッドサーチは、最も基本的なハイパーパラメータチューニング手法の一つです。事前に指定したハイパーパラメータの値の候補をすべて組み合わせ、それぞれの組み合わせでモデルを学習・評価し、最も性能が良かった組み合わせを選びます。

例えば、ハイパーパラメータAの候補が [1, 10, 100]、ハイパーパラメータBの候補が [0.1, 0.01] だとすると、グリッドサーチは以下の (3 × 2 =) 6通りの組み合わせをすべて試します。

  • (A=1, B=0.1)
  • (A=1, B=0.01)
  • (A=10, B=0.1)
  • (A=10, B=0.01)
  • (A=100, B=0.1)
  • (A=100, B=0.01)

メリット・デメリット

メリット 👍デメリット 👎
指定した範囲内のすべての組み合わせを試すため、最適な組み合わせを見逃さないハイパーパラメータの種類や候補値が増えると、試す組み合わせの数が爆発的に増加し、計算時間が非常にかかる。
実装が比較的簡単。計算リソースが多く必要になる場合がある。

Python (scikit-learn) での実装例

scikit-learnGridSearchCV を使うと簡単に実装できます。


from sklearn.model_selection import GridSearchCV
from sklearn.svm import SVC
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

# データの準備 (例としてirisデータセットを使用)
iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.3, random_state=42)

# モデルの定義
svm = SVC()

# 試したいハイパーパラメータの候補を指定 (辞書形式)
param_grid = {
    'C': [0.1, 1, 10, 100], # 正則化パラメータ
    'kernel': ['linear', 'rbf'], # カーネルの種類
    'gamma': [0.1, 0.01, 0.001] # RBFカーネルのパラメータ (kernel='rbf'の時のみ有効)
}

# グリッドサーチの設定 (cv=5は5分割交差検証を意味する)
grid_search = GridSearchCV(estimator=svm, param_grid=param_grid, cv=5, verbose=1)

# グリッドサーチの実行
grid_search.fit(X_train, y_train)

# 最適なパラメータの表示
print(f"Best parameters found: {grid_search.best_params_}")

# 最適なパラメータでのスコア表示
print(f"Best cross-validation score: {grid_search.best_score_:.3f}")

# テストデータでの評価 (最適なモデルは grid_search.best_estimator_ で取得可能)
best_model = grid_search.best_estimator_
test_score = best_model.score(X_test, y_test)
print(f"Test set score: {test_score:.3f}")
      

verbose を指定すると、どの組み合わせを試しているかのログが出力されます。

効率的に探す!ランダムサーチ (Random Search) 🎲

ランダムサーチは、グリッドサーチのようにすべての組み合わせを試すのではなく、指定されたハイパーパラメータの候補(または分布)からランダムに組み合わせを選んで試行する手法です。

試行回数(n_iter)を事前に決めることができ、その回数分だけランダムな組み合わせでモデルの学習・評価を行います。

メリット・デメリット

メリット 👍デメリット 👎
グリッドサーチよりも計算時間が短縮できることが多い。特に探索空間が広い場合に有効。ランダムに探索するため、必ずしも最適な組み合わせを見つけられるとは限らない。(試行回数を増やせば見つかる可能性は高まる)
試行回数を指定できるため、計算リソースに応じて調整しやすい。実行ごとに結果が変わる可能性がある(random_stateを指定すれば再現可能)。
重要なハイパーパラメータとそうでないものが混在する場合、効率的に良い組み合わせを見つけやすいとされる。

Python (scikit-learn) での実装例

scikit-learnRandomizedSearchCV を使います。グリッドサーチと使い方は似ていますが、パラメータ候補に連続値の分布を指定することも可能です。


from sklearn.model_selection import RandomizedSearchCV
from sklearn.svm import SVC
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from scipy.stats import uniform, randint # 連続値・離散値の分布を指定するために使用

# データの準備 (グリッドサーチと同じ)
iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.3, random_state=42)

# モデルの定義
svm = SVC()

# 試したいハイパーパラメータの候補または分布を指定
# 連続値の場合は分布 (例: uniform(0.1, 10))、離散値の場合はリストや分布 (例: randint(1, 5)) を指定可能
param_distributions = {
    'C': uniform(0.1, 100), # 0.1から100.1の範囲の一様分布
    'kernel': ['linear', 'rbf'],
    'gamma': uniform(0.001, 1) # 0.001から1.001の範囲の一様分布
}

# ランダムサーチの設定 (n_iterで試行回数を指定, random_stateで乱数シードを固定)
# 例えば n_iter=50 なら50通りの組み合わせを試す
random_search = RandomizedSearchCV(
    estimator=svm,
    param_distributions=param_distributions,
    n_iter=50, # 試行回数
    cv=5,
    verbose=1,
    random_state=42 # 結果を再現可能にするための乱数シード
)

# ランダムサーチの実行
random_search.fit(X_train, y_train)

# 最適なパラメータの表示
print(f"Best parameters found: {random_search.best_params_}")

# 最適なパラメータでのスコア表示
print(f"Best cross-validation score: {random_search.best_score_:.3f}")

# テストデータでの評価
best_model = random_search.best_estimator_
test_score = best_model.score(X_test, y_test)
print(f"Test set score: {test_score:.3f}")
      

n_iter で試行回数をコントロールできるのがランダムサーチの大きな特徴です。

グリッドサーチ vs ランダムサーチ:どっちを選ぶ? 🤔

どちらの手法を選ぶかは、状況によって異なります。

  • グリッドサーチが適している場合:
    • 探索するハイパーパラメータ空間が比較的小さい場合。
    • 計算リソースに余裕がある場合。
    • 指定した範囲内で確実に最適な組み合わせを見つけたい場合。
  • ランダムサーチが適している場合:
    • 探索するハイパーパラメータ空間が大きい、または次元が高い場合。
    • 計算リソースや時間に制約がある場合。
    • すべての組み合わせを試す必要はなく、「十分に良い」組み合わせを効率的に見つけたい場合。
    • 一部のハイパーパラメータが特に重要である可能性がある場合(ランダムサーチはそのようなパラメータを効率的に探索できる傾向がある)。

一般的に、まずはランダムサーチで大まかなパラメータの範囲を探し、その後、有望な範囲に絞ってグリッドサーチを行うといった組み合わせも有効です。

最近では、ベイズ最適化 (Bayesian Optimization) など、より効率的な探索手法も登場しています (例: Optuna, Hyperopt)。これらは過去の試行結果をもとに、次に試すべき有望なハイパーパラメータを予測しながら探索を進めます。

まとめ ✨

今回は、ハイパーパラメータチューニングの基本的な手法であるグリッドサーチとランダムサーチについて学びました。

  • グリッドサーチ: すべての組み合わせを試し、最適な解を見つけるが、計算コストが高い。
  • ランダムサーチ: ランダムに組み合わせを試し、計算コストを抑えつつ良い解を見つける。

scikit-learn を使えば、これらの手法を簡単に実装できます。モデルの性能を最大限に引き出すために、ぜひハイパーパラメータチューニングに挑戦してみてください!💪

コメント

タイトルとURLをコピーしました