Python Scikit-learnのGridSearchCVでハイパーパラメータ調整!使い方とコード例を徹底解説

Python

機械学習のモデルを作成したものの、「思っていたより予測精度が上がらない…」と悩んでいませんか?

実は、機械学習モデルの精度を限界まで引き上げるためには、「ハイパーパラメータのチューニング」という作業が欠かせません。この記事では、Pythonの代表的な機械学習ライブラリであるScikit-learn(サイキットラーン)に用意されている、最強のチューニングツールGridSearchCVの使い方を徹底的に解説します。

この記事を読むことで、以下のことが解決できます。

  • GridSearchCVの仕組みと、なぜ精度向上に必須なのかがわかる
  • コピペしてすぐに動かせる実践的なPythonコードが手に入る
  • param_gridcvなど、重要な設定値(引数)の意味が理解できる
  • 計算時間がかかりすぎる場合の対処法(RandomizedSearchCVとの使い分け)がわかる

機械学習エンジニアやデータサイエンティストの必須スキルですので、この記事を通してハイパーパラメータ調整の基本をマスターしましょう。本記事で解説している内容の公式ドキュメントはこちらです。

結論:GridSearchCVはモデルの「最適解」を自動で探すツールです

結論から言うと、GridSearchCVは、人間があらかじめ指定した複数の設定値(ハイパーパラメータ)の組み合わせをすべて試し、最も精度の高いモデルを自動で見つけ出してくれる非常に便利な関数です。

機械学習における「グリッドサーチ(Grid Search)」という総当たり戦の手法と、「交差検証(Cross-Validation)」というモデルの評価手法を組み合わせたものであり、Scikit-learnの現行バージョン(1.0以降)であれば、広く一般的に利用できる標準機能です。

ハイパーパラメータとは何か?

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

  1. パラメータ: モデルが学習データから自動的に学習して決定する値(例:回帰分析の重みやバイアスなど)。
  2. ハイパーパラメータ: 人間が学習前にあらかじめ設定しておかなければならない値(例:決定木の深さ、ランダムフォレストの決定木の数、学習率など)。

GridSearchCVが調整するのは、後者の「ハイパーパラメータ」です。これを適切に設定しないと、モデルが学習データに過剰に適合してしまう「過学習」を起こしたり、逆に全く学習できない「学習不足」に陥ったりします。

交差検証(CV)を同時に行ってくれるメリット

結論として、GridSearchCVの最大の強みは、総当たり戦のパラメータ探索と同時に「交差検証(Cross-Validation)」を行ってくれる点にあります。

交差検証とは、手元の学習データをさらにいくつかに分割し、「学習」と「テスト」を繰り返すことで、データの偏りによる評価のブレをなくす手法です。GridSearchCVは、それぞれのパラメータの組み合わせに対してこの交差検証を行うため、たまたま特定のデータ分割で運良く高スコアが出ただけの「偽の最適パラメータ」を掴まされるリスクを大幅に減らすことができます。

GridSearchCVの基本的な使い方と実践コード

結論から言うと、GridSearchCVを使うには、①試したいパラメータの辞書を作成し、②モデルと一緒にGridSearchCVに渡し、③fitメソッドで学習を実行する、という3ステップで完了します。

ここでは、Scikit-learnに用意されている乳がんデータセット(分類問題)と、ランダムフォレスト(RandomForestClassifier)を使って、実際に最適なパラメータを探索するコードを紹介します。

インポートとデータの準備

まずは必要なライブラリとデータセットを読み込み、学習用とテスト用にデータを分割します。

import pandas as pd
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.ensemble import RandomForestClassifier

# 乳がんデータセットの読み込み
data = load_breast_cancer()
X = pd.DataFrame(data.data, columns=data.feature_names)
y = data.target

# データを学習用(80%)とテスト用(20%)に分割
# ※分類問題なのでstratify=yを指定してラベルの比率を保ちます
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)

パラメータグリッドの定義と学習の実行

次に、ランダムフォレストのモデルを用意し、探索したいハイパーパラメータの候補を辞書型(dict)で定義します。

# 1. ベースとなるモデルのインスタンスを作成
rf_model = RandomForestClassifier(random_state=42)

# 2. 探索したいハイパーパラメータの組み合わせ(辞書型)を定義
# n_estimators: 決定木の数, max_depth: 木の深さ
param_grid = {
    'n_estimators': [50, 100, 200],
    'max_depth': [3, 5, 7, None]
}

# 3. GridSearchCVのインスタンスを作成
# cv=5 は5分割交差検証を行うという意味です
grid_search = GridSearchCV(
    estimator=rf_model, 
    param_grid=param_grid, 
    cv=5, 
    scoring='accuracy', # 評価指標に正解率(accuracy)を指定
    n_jobs=-1 # 全てのCPUコアを使って並列処理を行う
)

# 4. 学習の実行(総当たりで探索開始!)
grid_search.fit(X_train, y_train)

print("探索が完了しました!")

このコードを実行すると、n_estimators(3通り)× max_depth(4通り)= 合計12通りの組み合わせをすべて試し、それぞれに対して5分割交差検証を行います。つまり、裏側では合計60回のモデル学習と評価が自動で行われています。

絶対に覚えておきたい主要パラメータ5選

結論として、実務でGridSearchCVを使う場合、引数(パラメータ)を適切に設定することで、探索の効率と評価の質をコントロールする必要があります。

GridSearchCVを初期化する際に指定する、非常に重要な5つの引数について詳しく解説します。

1. estimator(評価対象のモデル)

探索を行いたい機械学習モデルのインスタンスを指定します。RandomForestClassifier()SVC()など、Scikit-learnのモデルであれば基本的にどれでも指定可能です。

2. param_grid(探索するパラメータの辞書)

試したいハイパーパラメータの名前をキー(文字列)、試したい値のリストをバリューとした辞書を指定します。キーの名前は、estimatorで指定したモデルが実際に持っている引数名と完全に一致している必要があります。タイポ(打ち間違い)に注意してください。

3. cv(交差検証の分割数)

交差検証でデータをいくつに分割するかを指定します。デフォルトは5(5分割交差検証)です。数値を大きくするとより厳密な評価ができますが、その分学習にかかる時間が比例して長くなります。一般的な実務では cv=5 または cv=3 がよく使われます。

4. scoring(モデルの評価指標)

どの指標を使って「一番良いモデル」を決めるかを文字列で指定します。 分類問題であれば 'accuracy'(正解率)や 'f1'(F値)、 'roc_auc'(AUC)などがよく使われます。回帰問題(数値を予測する問題)であれば 'neg_mean_squared_error'(負の平均二乗誤差)などを指定します。目的に応じて適切な指標を選びましょう。

5. n_jobs(並列処理の指定)

結論から言うと、データ量が多い場合は必ず n_jobs=-1 を指定して処理を高速化しましょう。

GridSearchCVは独立したパターンの学習を何度も繰り返すため、並列処理と非常に相性が良いです。-1 を指定すると、お使いのパソコンのすべてのCPUコアを使って同時に計算してくれるため、探索にかかる時間を大幅に短縮できます。

探索結果の確認!最適なパラメータはどう取り出す?

結論として、fitメソッドを実行した後のGridSearchCVオブジェクトには、一番良かった結果を取り出すための便利な属性(アトリビュート)が用意されています。

探索が終わった後、結果をどのように確認して、どのように未知のデータ(テストデータ)の予測に使うのかを解説します。

最適なパラメータとスコアの確認

一番成績が良かったハイパーパラメータの組み合わせは best_params_ で、その時の交差検証の平均スコアは best_score_ で確認できます。

# 最適なハイパーパラメータの組み合わせを表示
print("最適なパラメータ:", grid_search.best_params_)
# 出力例: {'max_depth': 5, 'n_estimators': 100}

# その時の交差検証の最高スコアを表示
print("最高の交差検証スコア:", grid_search.best_score_)

最適なモデルを使ったテストデータの予測

結論から言うと、GridSearchCVは一番良かったパラメータを使って、全学習データで「自動的にモデルを再学習」してくれています。

そのため、新しくモデルを作り直す必要はありません。grid_searchオブジェクトに対して直接predictメソッドを呼ぶだけで、最適なモデルを使った予測が可能です。明示的に最適なモデルだけを取り出したい場合は best_estimator_ を使います。

# 最適なモデルを取得
best_model = grid_search.best_estimator_

# テストデータを使って最終的な予測精度を確認
test_score = best_model.score(X_test, y_test)
print("テストデータのスコア:", test_score)

このテストデータのスコアが、このモデルの最終的な実力(汎化性能)となります。

初心者が陥りやすい罠:計算時間の爆発に注意!

結論として、GridSearchCVは「組み合わせの数」が掛け算で増えていくため、欲張ってたくさんのパラメータを探索しようとすると、計算時間が数日〜数週間かかる「次元の呪い」に陥ります。

ここでは、計算時間が長すぎるときの実践的な対処法を解説します。

パラメータの候補を絞り込む

例えば、3つのハイパーパラメータに対して、それぞれ10個の候補を用意し、5分割交差検証を行ったとします。この場合、10 × 10 × 10 × 5 = 5,000回の学習が発生します。

まずは、候補を大雑把に(例:10, 100, 1000のように桁を変えて)設定してGridSearchCVを実行します。そして、当たりをつけてから、その周辺の細かい値を再度探索するという「2段階アプローチ」を取るのが実務では効果的です。

RandomizedSearchCVとの使い分け

どうしても探索範囲が広すぎて終わらない場合は、RandomizedSearchCV の使用を検討してください。

RandomizedSearchCVは、すべての組み合わせを試すのではなく、「指定した回数だけランダムにパラメータの組み合わせを選んで試す」という関数です。

from sklearn.model_selection import RandomizedSearchCV

# ランダムに20パターンの組み合わせだけを探索する例
random_search = RandomizedSearchCV(
    estimator=rf_model, 
    param_distributions=param_grid, 
    n_iter=20, # ここで探索する回数を制限できる
    cv=5, 
    random_state=42
)
random_search.fit(X_train, y_train)

GridSearchCVほどの網羅性はありませんが、はるかに短い時間で「そこそこ良いパラメータ」を見つけることができるため、非常に実用的な手法です。

まとめ:GridSearchCVを使いこなしてモデルの限界を引き出そう

この記事では、Scikit-learnのGridSearchCVについて、その仕組みから実践的な使い方まで詳しく解説しました。

最後に、記事の要点をまとめます。

  1. 目的: 人間が設定すべきハイパーパラメータの最適な組み合わせを自動で探し出し、モデルの精度を最大化する。
  2. 仕組み: 総当たり戦(グリッドサーチ)と交差検証(CV)を同時に行い、過学習を防ぎながら客観的に評価する。
  3. 使い方: estimator(モデル)、param_grid(パラメータ候補)、cv(分割数)を指定してfitするだけ。
  4. 結果の確認: best_params_best_estimator_ を使って最適なモデルの情報を引き出す。
  5. 注意点: 組み合わせが多すぎると計算が終わらなくなるため、大雑把な探索から始めるか、RandomizedSearchCVと併用する。

機械学習の精度向上において、ハイパーパラメータのチューニングは避けて通れない道です。最初は難しく感じるかもしれませんが、コードの書き方自体は決まったパターン(定型文)ですので、ぜひお手元のデータセットで何度も実行して使い方をマスターしてください。

さらに詳細な仕様や設定可能なパラメータについて知りたい場合は、ぜひScikit-learnの公式ドキュメントも併せてご確認ください。

コメント

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