4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ハイパーパラメータの調整

Posted at

パラメータはモデルの学習実行後に得られる値で、重みとも呼ばれます。
対してハイパーパラメータは各アルゴリズムに付随して、アルゴリズムの挙動を制御するための値です。
ハイパーパラメータを調整することで、っモデルの性能向上や過学習の抑制、効率の良い学習などが期待できます。

1. K-分割交差検証 (K-fold cross-validation)

与えられたデータセットを「学習用データセット」「テスト用データセット」に2分割することをホールドアウト法と呼びます。
ホールドアウト法では、ハイパーパラメータの調整に使うデータがありませんので、ハイパーパラメータを調整するためには「検証用データセット」を用意する必要があります。

しかし、3分割するほどデータ量がないこともあります。
その時に使うのが、**K-分割交差検証 (K-fold cross-validation)**です。

【手順】
1.データセットをK個に分割
2.分割したデータの1個を検証用データセットとし、残りK-1個を学習用データセットとして学習を実行
→ 1 回で学習を終わらせず、計K回の学習を行います。その際、既に検証用データセットに使ったデータを次は学習用データセットとして使用し、新たに検証用データセットを選択します。
3.各検証の結果を平均して最終的な検証結果とする

2. ハイパーパラメータの調整方法

ハイパーパラメータの調整するには、以下のような方法があります。
1.手動での調整
2.グリッドサーチ (Grid Search)
3.ランダムサーチ (Random Search)
4.ベイズ最適化 (Bayesian Optimization)

2-1. 手動での調整

DecisionTreeClassifierで決定木の実装を行う場合を考えます。

from sklearn.tree import DecisionTreeClassifier
# ハイパーパラメータ調整なし
dtree = DecisionTreeClassifier(random_state=0)
# ハイパーパラメータ調整あり
dtree2 = DecisionTreeClassifier(max_depth=10, min_samples_split=30, random_state=0)

このように、max_depthmin_samples_splitについて、自分で適当に値を入れて、数値を変えるたびに予測精度を確認するという方法が、手動での調整です。

2-2. グリッドサーチ (Grid Search)

グリッドサーチはまず、ハイパーパラメータを探索する範囲を決めます。
例えば上記のように決定木のmax_depthmin_samples_splitの値を調整したい場合、5、10、15、20、25 のように範囲をそれぞれ決めます(範囲の指定に特に決まりはありません)。
この場合のハイパーパラメータの組み合わせは 5x5=25 個になります。
この25個のハイパーパラメータの組み合わせ全てを使用して、学習・検証を行います。
そして、その結果から予測精度が最も高いハイパーパラメータを採用します。

グリッドサーチには以下の3つを準備する必要があります。

  • estimator : 学習に使用するモデル
  • param_grid : ハイパーパラメータを探索する範囲
  • cv : K-分割交差検証のKの値
# GridSearchCV クラスのインポート
from sklearn.model_selection import GridSearchCV

# 学習に使用するアルゴリズムの定義
estimator = DecisionTreeClassifier(random_state=0)

# 探索するハイパーパラメータと範囲の定義
param_grid = [{
    'max_depth': [3, 20, 50],
    'min_samples_split': [3, 20, 30]
}]

# データセット分割数を定義
cv = 5

# GridSearchCV クラスを用いたモデルの定義
tuned_model = GridSearchCV(estimator=estimator, 
                           param_grid=param_grid, 
                           cv=cv, return_train_score=False)

# モデルの学習&検証
tuned_model.fit(x_train_val, t_train_val)

# 検証結果の確認
pd.DataFrame(tuned_model.cv_results_).T

ここまで入力すると、それぞれのハイパーパラメータの値に対する予測精度などが表になって出力されます。
mean_test_scoreの値を見ると、モデルの予測精度がわかります。
その後、結果を参照して先ほどより狭い範囲でハイパーパラメータを調整します。
これを何度か繰り返すことで徐々に予測精度が高くなるハイパーパラメータへと近づけて行きます。

# 最も予測精度の高かったハイパーパラメータの確認
tuned_model.best_params_

# 最も予測精度の高かったモデルの引き継ぎ
best_model = tuned_model.best_estimator_

# モデルの検証
print(best_model.score(x_train_val, t_train_val))
print(best_model.score(x_test, t_test))

これで、最も予測精度が高かったハイパーパラメータのモデルで検証することができます。

2-3. ランダムサーチ (Random Search)

ランダムサーチは指定した範囲のハイパーパラメータをランダムに抽出し、学習・検証を行います。
グリッドサーチに比べて、より広い範囲を探索することができるので、効率的と言われています。
しかし、全てのハイパーパラメータを探索するわけではないので、本当に最適か判断が難しいと言えます。
ランダムサーチで大体のあたりをつけてから、グリッドサーチで細かく見ていくやり方だと双方のメリットが活かせます。

# RandomizedSearchCV クラスのインポート
from sklearn.model_selection import RandomizedSearchCV
# 学習に使用するアルゴリズム
estimator = DecisionTreeClassifier(random_state=0)

# ハイパーパラメータを探索する範囲の指定 range(開始値, 終了値, ステップ)
# 例えば range(1, 10, 2) の場合、1から10までの値を2刻みで獲得できる。その値をlist()でリスト化。
param_distributions = {
    'max_depth': list(range(5, 100, 2)),
    'min_samples_split': list(range(2, 50, 1))
}

# 試行回数の指定
n_iter = 100

# Kの値を指定
cv = 5

# モデルの定義
tuned_model = RandomizedSearchCV(
    estimator=estimator, 
    param_distributions=param_distributions, 
    n_iter=n_iter, cv=cv, 
    random_state=0, return_train_score=False
)

# モデルの学習&検証
tuned_model.fit(x_train_val, t_train_val)

# 学習結果の確認(スコアの高い順に表示)
pd.DataFrame(tuned_model.cv_results_).sort_values('rank_test_score').T

ここまで入力すると、それぞれのハイパーパラメータの値に対する予測精度などが表になって出力されます。

# 最も予測精度の高かったハイパーパラメータの確認
tuned_model.best_params_

# 最も予測精度の高かったモデルの引き継ぎ
best_model = tuned_model.best_estimator_

# モデルの検証
print(best_model.score(x_train_val, t_train_val))
print(best_model.score(x_test, t_test))

2-4. ベイズ最適化 (Bayesian Optimization)

数学的背景の理解が難しいのですが、ベイズ最適化では探索(この辺かな〜?と適当に入力してみる)や活用(結果をもとに、さらにこの辺かな〜?と値を更新する)で得られた情報を元にハイパーパラメータを調整していくため、予測精度が高くなるハイパーパラメータを見つけやすいそうです。
日本の Prefferd Networks 社が開発している Optuna というフレームワークを使用するときの方法を記述します。

# optuna のインストール
!pip install optuna
import optuna

Optunaでは最初に関数objectiveを定義して内部に以下の要素を関数として順に定義します。

  • 1.ハイパーパラメータごとに探索範囲を指定
  • 2.学習に使用するアルゴリズムを指定
  • 3.学習の実行、検証結果の表示

探索範囲の指定にはデフォルトで準備されているtrialクラスを使用します。
3では学習・検証を繰り返してハイパーパラメータの調整を行うのですが、その際にreturnで取得した検証結果を最小化(最大化)するように調整が進みます。
また、3でK-分割交差検証を使用するにはcross_val_scoreが必要です。

from sklearn.model_selection import cross_val_score
def objective(trial, x, t, cv):
    # 1. ハイパーパラメータごとに探索範囲を指定
    max_depth = trial.suggest_int('max_depth', 2, 100)
    min_samples_split = trial.suggest_int('min_samples_split', 2, 100)

    # 2. 学習に使用するアルゴリズムを指定
    estimator = DecisionTreeClassifier(
      max_depth = max_depth,
      min_samples_split = min_samples_split
    )

    # 3. 学習の実行、検証結果の表示
    print('Current_params : ', trial.params)
    accuracy = cross_val_score(estimator, x, t, cv=cv).mean()
    return accuracy

正解率の最大化を目的とする場合には、direction='maximize' を指定します。

#  studyオブジェクトの作成(最大化)
study = optuna.create_study(direction='maximize')

# K分割交差検証の K
cv = 5

# 目的関数の最適化
study.optimize(lambda trial: objective(trial, x_train_val, t_train_val, cv), n_trials=10)

print(study.best_trial)

学習が終了したので、最も予測精度の高かったハイパーパラメータを確認するためにstudy.best_paramsを実行します。

# 最も予測精度の高かったハイパーパラメータの確認
study.best_params

# 最適なハイパーパラメータを設定したモデルの定義
best_model = DecisionTreeClassifier(**study.best_params)

# モデルの学習
best_model.fit(x_train_val, t_train_val)

# モデルの検証
print(best_model.score(x_train_val, t_train_val))
print(best_model.score(x_test, t_test))
4
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?