ランダムフォレストの力を最大化!ハイパーパラメーターの探し方と設定の勘所

AI

前回記事までで、データ標準化という必須の前処理を学習し、ランダムフォレストという高性能なAIモデルの搭載に成功しました。これにより、AI開発の基本的な土台は完璧に整っています。

しかし、AI開発のプロフェッショナルは、モデルをただ動かすだけでは満足しません。
次のステップは、搭載した高性能なエンジン(モデル)の出力を最大限に引き出すことを目指します。
その鍵を握るのが、AIモデルのハイパーパラメーター(詳細設定)です。

本記事では、AIの性能に劇的な影響を与えるハイパーパラメーターを調整し、AIの力を極限まで引き出すテクニックを実践します。

  1. ハイパーパラメーターの理解: AIの性能を左右する「設定値」とは何かを明確にします。
  2. 最適値の効率的な探索: グリッドサーチ(Grid Search)という手法を導入し、最適なハイパーパラメーターの組み合わせを自動かつ効率的に見つけ出します。
  3. 性能向上の体験: 意図的に性能を落とした状態からスタートし、パラメーター調整によってAIの正解率が実際に向上する過程を体験します。

第1章:ハイパーパラメーターの定義と環境準備

1.1. ハイパーパラメーターとは

AIが自動で学習した「花びらの長さの重要度」などの数値はパラメーターと呼ばれます。
これに対し、ハイパーパラメーターとは、開発者が訓練のに設定する、AIの学習方法や構造をコントロールするための「設計図」です。

項目パラメーター
(Weights)
ハイパーパラメーター
(Hyperparameters)
学習方法AIがデータから自動で計算人間がAIに指示する設定値
設定例各特徴量の重み、バイアスなど決定木の数、学習率、木の深さなど
役割予測を行うための具体的な知識AIの性能の限界を決める設定

ハイパーパラメーターを適切に調整するプロセスが「チューニング(調整)」と呼ばれ、AI開発の成否を分ける勘所となります。

1.2. 課題のステップアップ:回帰問題への挑戦と準備

前回まではアヤメの分類問題(どの品種か?)に挑戦しましたが、今回はより実用的な回帰問題(数値を予測する問題)にステップアップします。
題材は、カリフォルニア住宅価格の予測です。

新しい課題と新しいモデルに対応するため、プロジェクトフォルダに california_tune.py という新しいファイルを作成し、以下のコードを記述してください。
※ 今回は、ハイパーパラメーターを効率的に探すための強力なツールである GridSearchCV を導入します。

import pandas as pd
from sklearn.datasets import fetch_california_housing # カリフォルニアデータセット
from sklearn.model_selection import train_test_split, GridSearchCV 
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestRegressor # 回帰用モデル
from sklearn.metrics import mean_squared_error   # 誤差評価指標

# 全ての列を表示するための設定
pd.set_option('display.max_columns', None)
pd.set_option('display.width', 1000)

💡 解説

  • GridSearchCV: グリッドサーチを実行するためのクラスです。設定したいハイパーパラメーターの組み合わせをすべて試行し、最も性能が良かった組み合わせ(最適解)を自動で見つけ出してくれます。
  • fetch_california_housing: 今回扱う住宅価格データセットをロードします。
  • RandomForestRegressor: 予測対象が数値に変わるため、モデルを回帰(Regressor)用に切り替えます。
  • mean_squared_error: 評価指標も、正解率から誤差(Mean Squared Error)を測るものに変わります。

第2章:カリフォルニア住宅価格データセットの準備と初期評価

2.1. データセットのロードと準備

第1章で作成したファイル california_tune.py のインポート文の後に、データのロード、分割、そして標準化の処理を続けて記述します。

今回は予測対象が住宅価格(数値)となるため、前回の分類問題とは異なり、モデルの評価指標には「誤差」を使います。

# 1.2で作成したコードに続けて記述します。

# データのロードと準備

# 1. データセットのロード
# カリフォルニアデータセットは、データとターゲットが辞書型で提供される
california = fetch_california_housing()
X = california.data # 特徴量 
y = california.target # ターゲット (住宅価格中央値)

# 2. データを訓練用とテスト用 (80%:20%) に分割
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

# 3. StandardScalerの初期化と学習・変換
scaler = StandardScaler()
# 標準化後のデータを格納する変数
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

print("--- データ準備完了 ---")

💡 解説

  • 新しいデータセットの形式: カリフォルニアデータセットは、アヤメと同様に data(特徴量)と target(正解値)が分かれています。
  • データの標準化: 今回の回帰問題においても、特徴量のスケールを統一するため、StandardScaler を使った標準化を実行します。

📐 X(大文字)と y(小文字)の慣習

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

このコードを見て、「Xは大文字なのにyが小文字なのはタイプミスなのではないか」と思われた方もいるかもしれません。
しかし、これはPythonの機械学習ライブラリである scikit-learn を含むデータサイエンスコミュニティにおける標準的な慣習(コーディング規約)によるものです。

  • X(大文字): 特徴量(Features)
    • 機械学習モデルへの入力データ全体を示しています。慣習として、行列やテンソルといった複数次元のデータ構造を表す場合は大文字を使います。
  • y(小文字): ターゲット/正解ラベル(Target/Labels)
    • 機械学習モデルが予測すべき正解のデータを示しています。慣習として、単なるベクトルやスカラーといった1次元のデータ構造を表す場合は小文字を使います。

2.2. 弱体化モデルの作成と初期性能の評価

パラメーター調整による「性能の変化」を体験するため、モデルの決定木の深さと特徴量の数を極端に制限し、意図的に性能の低い状態からスタートします。

以下のコードを california_tune.py 追加して実行し、現在の誤差(エラー)を確認してください。

# 2.1で作成したコードに続けて記述します。

# 4. 弱体化モデルの初期化(極限まで性能を制限)
# max_depth=2, n_estimators=5, max_features=1 で極めて弱いモデルを設定
model_weak = RandomForestRegressor(random_state=42, max_depth=2, n_estimators=5, max_features=1) 

# 5. 訓練と予測
model_weak.fit(X_train_scaled, y_train)
y_pred_weak = model_weak.predict(X_test_scaled)

# 6. 誤差(MSE)を計算し、表示
# MSE (平均二乗誤差) は数値が小さいほど性能が良いことを意味します
mse_weak = mean_squared_error(y_test, y_pred_weak)

print("\n--- 弱体化モデルの初期評価(回帰) ---")
print(f"初期(極限弱体化)の平均二乗誤差 (MSE): {mse_weak:.4f}")

実行結果の確認

--- 弱体化モデルの初期評価(回帰) ---
初期(極限弱体化)の平均二乗誤差 (MSE): 1.0160

実行結果の 平均二乗誤差(MSE) は、\(0.5\) 以上の大きな数値になっているはずです。

このデータセットのターゲット(住宅価格)は \(10\) 万ドル単位に正規化されており、このスケールに対して \(0.5\) を超える MSE は、モデルの予測が大きく外れていることを示します。

この大きな誤差が改善前の「Before」の値であり、ここからグリッドサーチを使用して誤差の改善を目指します。

グリッドサーチの実践

グリッドサーチ(Grid Search)は、調整したいハイパーパラメーターの候補値を設定し、そのすべての組み合わせを試行錯誤することで、最も性能の良い設定を自動で発見する手法です。

この手法を用いることで、勘や経験に頼らず、機械的に最適なモデル設定を見つけることができます。

3.1. ランダムフォレストの主なハイパーパラメーター

グリッドサーチに進む前に、ランダムフォレスト (RandomForestRegressor) に存在する主要なハイパーパラメーターを知っておきましょう。

モデルの性能と過学習を防ぐ上で、特に重要なパラメーター (15種) を以下に一覧化します。

パラメーター名【意味】/調整の目的
n_estimators【決定木の数】
モデルの安定性と精度を向上させる。数が多すぎると計算時間が延びる。
max_depth【決定木の最大の深さ】
決定木の学習するルールの複雑さを制限する。過学習を防ぐ上で最も重要。
max_features【考慮する特徴量の最大数】
分割時にランダムに選択される特徴量の数。モデルの多様性を高め過学習を防ぐ。
min_samples_split【分割に必要な最小サンプル数】
ノードの分割を停止する基準。モデルの複雑さを制限する。
min_samples_leaf【葉ノードの最小サンプル数】
決定木の末端に存在するべき最小サンプル数。過学習を防ぐ。
min_weight_fraction_leaf【葉ノードの最小重み割合】
葉ノードに割り当てられるべき、全サンプルの重みの最小割合。
max_leaf_nodes【葉ノードの最大数】
決定木の葉ノードの最大数を制限する。深さ制限の代替手段。
min_impurity_decrease【不純度減少の最小値】
ノードが分割されるために必要な、不純度減少の最小値。
bootstrap【ブートストラップの有効化】
訓練データから復元抽出(サンプリング)を行うかどうか。ランダムフォレストの核。
oob_score【OOBスコアの計算】
訓練に使わなかったデータ(OOB: Out-of-Bag)で精度を評価するかどうか。
random_state【ランダムシードの固定】
結果の再現性を確保するために、ランダムな処理を固定する。
n_jobs【並列処理を行うCPUコア数】
訓練時の計算を高速化する。通常 -1 で全コアを使用。
warm_start【前回学習の再利用】
前回の訓練結果を再利用して、新しい決定木を追加できる。
ccp_alpha【複雑度パラメーター】
決定木の枝刈りを行うためのパラメーター。過学習を防ぐ。
max_samples【ブートストラップの最大サンプル数】
bootstrap=True の際、訓練に使用するサンプルの割合を制限する。
ランダムフォレスト (RandomForestRegressor) の主要なハイパーパラメーター15種

3.2. 探索するハイパーパラメーターの定義

数あるパラメーターの中から、特に性能に影響を与える n_estimatorsmax_depthmax_features の3種を厳選し、その候補値を定義します。

以下のコードを california_tune.py ファイルの末尾に追記してください。

# 2.2で作成したコードに続けて記述します。

# 7. 探索するハイパーパラメーターの候補値を定義
param_grid = {
    'n_estimators': [10, 50, 100],  # 決定木の数
    'max_depth': [3, 7, 15],        # 木の最大の深さ
    'max_features': [3, 6, 9]       # 考慮する特徴量の数
}

print("\n--- グリッドサーチ準備完了 ---")

3.3. グリッドサーチの実行

前項「3.2.」で定義したパラメーターの組み合わせ(param_grid)を使って、実際にモデルの最適化(チューニング)を実行します。
このプロセスでは、定義したすべての組み合わせ(\(3 \times 3 \times 3 = 27\) 通り)が自動で試行され、最も誤差(エラー)が小さくなる設定が選ばれます。

以下のコードを california_tune.py ファイルの末尾に追記してください。

# 3.2で作成したコードに続けて記述します。

# 8. モデルとグリッドサーチの初期化
# ベースモデルとしてRandomForestRegressorを使用
base_model = RandomForestRegressor(random_state=42)

# GridSearchCVの初期化
# estimator: ベースとなるモデル
# param_grid: 試すパラメーターの組み合わせ
# scoring: 評価指標 (誤差は小さいほど良いため、'neg_mean_squared_error'を使う)
# cv: 交差検証の分割数 (5分割で安定した評価を行う)
grid_search = GridSearchCV(
    estimator=base_model, 
    param_grid=param_grid, 
    scoring='neg_mean_squared_error',
    cv=5, 
    verbose=2, # 処理状況を表示
    n_jobs=-1 # すべてのCPUコアを使って並列処理
)

# 9. グリッドサーチの実行!(最適なパラメーターの探索)
print("グリッドサーチ開始。少々時間がかかります...")
grid_search.fit(X_train_scaled, y_train) 
print("グリッドサーチ完了!")

💡 解説

  • base_model: チューニングを行う対象として、性能の高い RandomForestRegressor を使用しています。
  • GridSearchCV の各種設定:
    • scoring='neg_mean_squared_error': GridSearchCV は値が大きいほど良いと判断するため、誤差(MSE)にマイナスをつけた指標を使用します。これにより、誤差の絶対値が小さい(性能が良い)設定を最適解として自動で選択できます。
    • cv=5: 交差検証(Cross Validation)と呼ばれる手法でデータを5分割し、評価の信頼性を高めます。
    • n_jobs=-1: PCのすべてのCPUコアを使って並列処理を行うことで、計算時間を大幅に短縮できます。

第4章:最適結果の確認と性能比較

4.1. 最適パラメーターとベストスコアの確認

以下のコードを california_tune.py の末尾に追記してください。

グリッドサーチが発見した最も優れたパラメーターの組み合わせと、その組み合わせで達成した最高のスコアを表示する処理です。

# 10. 最適なパラメーターとベストスコアの表示
print("\n--- グリッドサーチ結果 ---")
print(f"最適なパラメーターの組み合わせ: {grid_search.best_params_}")
print(f"ベストスコア (Negative MSE): {grid_search.best_score_:.4f}")

4.2. 最終的な性能の比較(Afterの評価)

最後に、この最適なパラメーターを適用したモデルが、テストデータでどれほどの性能(誤差)を出したかを評価し、第2章の「Before」の値と比較します。

以下のコードを california_tune.py ファイルの末尾に追記してください。

# 11. 最適モデルの取得とテストデータでの最終評価
best_model = grid_search.best_estimator_

# テストデータで予測を実行
y_pred_final = best_model.predict(X_test_scaled)

# 最終誤差(MSE)を計算し、表示
mse_final = mean_squared_error(y_test, y_pred_final)

print("\n--- 性能改善結果 ---")
print(f"改善前 (Before) の平均二乗誤差 (MSE): {mse_weak:.4f}")
print(f"改善後 (After) の平均二乗誤差 (MSE): {mse_final:.4f}")

プログラムを再度実行するため、グリッドサーチに少し時間がかかりますが、完了した後に結果を確認してください。

--- グリッドサーチ結果 ---
最適なパラメーターの組み合わせ: {'max_depth': 15, 'max_features': 3, 'n_estimators': 100}
ベストスコア (Negative MSE): -0.2513

--- 性能改善結果 ---
改善前 (Before) の平均二乗誤差 (MSE): 1.0160
改善後 (After) の平均二乗誤差 (MSE): 0.2534

💡 実行結果の確認ポイント

  • grid_search.best_params_: 3つのパラメーター(n_estimators, max_depth, max_features)の最適な値が表示されます。
  • 改善の確認: mse_final の値が、mse_weak の値よりも大幅に小さくなっていれば、ハイパーパラメーター調整による性能改善が成功したことになります。

第5章:結果の考察とハイパーパラメーターの勘所

5.1. チューニングの成果と劇的な改善

私の環境での実行結果 (再掲) は、ハイパーパラメーター調整(チューニング)の力が非常に大きいことを明確に示しています。

--- グリッドサーチ結果 ---
最適なパラメーターの組み合わせ: {'max_depth': 15, 'max_features': 3, 'n_estimators': 100}
ベストスコア (Negative MSE): -0.2513

--- 性能改善結果 ---
改善前 (Before) の平均二乗誤差 (MSE): 1.0160
改善後 (After) の平均二乗誤差 (MSE): 0.2534
  • 改善の意義: 誤差が \(1.0160\) から \(0.2534\) へと約 \(75\%\) 減少しました。これは、AIモデルの予測精度が劇的に向上し、予測のブレが非常に小さくなったことを意味します。
  • 学習目標の達成: 意図的に性能を落とした状態 (\(1.0160\)) からスタートし、パラメーター調整によって性能が改善する過程を明確に体験できました。

5.2. 最適なハイパーパラメーターの考察

実行結果によると、グリッドサーチが発見した最適な組み合わせは以下の通りです。

\(\text{‘max_depth’: 15},\)
\(\text{‘max_features’: 3},\)
\(\text{‘n_estimators’: 100}\)

この結果から見えてくる設定の勘所は、以下のとおりです。

  1. n_estimators: 決定木の数
    • 最適値: \(100\) (最大値)
    • ランダムフォレストは、多くの決定木(\(100\) 本)の多数決によって予測を安定させ、精度を向上させることが分かりました。この問題では、木の数が多いほど良いという、ランダムフォレストの基本的な特性が確認されました。
  2. max_depth: 決定木の深さ
    • 最適値: \(15\) (最大値)
    • \(15\) という比較的深い値が選ばれました。これは、カリフォルニアの住宅価格データが、ある程度複雑なルール(「犯罪率が低い」かつ「部屋数が8以上」など)を学習しなければ正確に予測できない、複雑な構造を持っていることを示唆しています。
  3. max_features: 考慮する特徴量の数
    • 最適値: \(3\) (最小値)
    • カリフォルニアデータセットには 8 つの特徴量がありますが、最適な値は 3 でした。これは、ノードを分割する際に少数の特徴量(3つ)しか使わせないことで、個々の決定木に多様性が生まれ、結果としてフォレスト全体の過学習を防ぎ、性能が安定したことを意味します。

まとめ

今回の実践を通じて、高性能なAIモデルの力を最大限に引き出すためのハイパーパラメーター調整の原則を明確化できたかと思います。

  1. 影響の大きなパラメーターを選ぶ: n_estimators, max_depth, max_features など、モデルの安定性や複雑さに直接関わる主要なパラメーターに絞る。
  2. 探索範囲を決める: 候補値(グリッド)を広すぎず、狭すぎない範囲で設定する。
  3. 自動で探索させる: GridSearchCV を利用して、機械的に最適な組み合わせを自動で発見させる。
  4. 結果を考察する: チューニング後の結果から、データセットの特性を読み取る。

これで、AI開発の「土台作り」から「性能の向上」という専門的な領域へとステップアップしました。

このレベルで満足することなく、次回はさらなる性能向上への挑戦を続けていきます。

コメント

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