scikit-learnのモデルをOptunaでCV(クロスバリデーション)を実施する方法は2種類あります。
- 良し悪しを判断するメトリクスにscikit-learnのCVを指定する方法
- OptunaのCV関数(OptunaSearchCV)を使う方法
前回の乳がんの例では、実は「良し悪しを判断するメトリクスにscikit-learnのCVを指定する方法」で実施していました。
Python のハイパーパラメータ自動最適化ライブラリー Optuna その2 – Optunaを使うとき最低限覚えておきたい探索範囲の指定方法 –
最初に前回のコードを振り返り、その後にOptunaのCV関数(OptunaSearchCV)を使う方法を紹介します。
先ずは手順の復習です。
Optuna の手順の復習
Optunaは、目的関数(objective function)を設定し最適化を目指すことでより良いハイパーパラメータの組み合わせを探索します。
以下、ざっくり手順です。
- ステップ1:目的関数を設定する
- 各モデルのハイパーパラメータの集合を定義する
- 良し悪しを判断するメトリクスを定義する
- ステップ2:目的関数の最適化を実行する
- ステップ3:最適解を利用する
ステップ4で試行回数(n_trials)を設定し実行します。試行回数が多いほど時間が掛かりますが、より良い解になる可能性が高くなります。
分類問題(乳がんデータ)
前回説明した分類問題(乳がんデータ)の例です。
良し悪しを判断するメトリクスを、どのように設定したのかを見てみます。Step 4のところです(色を変えています)。scikit-learnのCV(クロスバリデーション)のcross_val_score関数を使っています。
以下、前回のコードです。
# 目的関数の設定(ステップ1) def objective(trial): #ハイパーパラメータの集合を定義する ##推定器の集合 classifier_name = trial.suggest_categorical("classifier", ["LogReg", "SVC", "RandomForest" ] ) ##推定器ごとのハイパーパラメータの集合 ###ロジ回(LogReg) if classifier_name == 'LogReg': logreg_c = trial.suggest_float("logreg_c", 1e-10, 1e10, log=True ) classifier_obj = linear_model.LogisticRegression(C=logreg_c) ###サポートベクターマシン(SVC) elif classifier_name == "SVC": svc_c = trial.suggest_float("svc_c", 1e-10, 1e10, log=True ) classifier_obj = sklearn.svm.SVC(C=svc_c, gamma="auto" ) ###ランダムフォレスト(RandomForest) else: rf_n_estimators = trial.suggest_int("rf_n_estimators", 10, 1000 ) rf_max_depth = trial.suggest_int("rf_max_depth", 2, 50, log=True ) classifier_obj = ensemble.RandomForestClassifier( max_depth=rf_max_depth, n_estimators=rf_n_estimators ) #良し悪しを判断するメトリクスを定義する ##CVの実施 score = model_selection.cross_val_score(classifier_obj, X, y, n_jobs=-1, cv=10 ) ##CVの結果の平均値 accuracy = score.mean() return accuracy # 目的関数の最適化を実行する(ステップ2) study = optuna.create_study(direction="maximize") study.optimize(objective, n_trials=100) # 最適解の出力 print(f"The best value is : \n {study.best_value}") print(f"The best parameters are : \n {study.best_params}")
以下、実行結果です。
最良なモデルはランダムフォレストです。
次に、このランダムフォレストに対し、OptunaのCV関数(OptunaSearchCV)を使い、CV(クロスバリデーション)を実施してみたいと思いますが……
……ただ、先程の例ではロジスティック回帰、SVM、ランダムフォレストの3つのアルゴリズム(数理モデル)を対象にしているため、OptunaのCV関数(OptunaSearchCV)を使った例と見比べるとき、やや面倒です。
そのため、ランダムフォレストのみに対し、scikit-learnのCVの関数(model_selection.cross_val_score)を指定するコード例を示します。
以下、コードです。
# ライブラリーの読み込み import optuna import pandas as pd import sklearn.svm from sklearn import linear_model from sklearn import ensemble from sklearn import datasets from sklearn import model_selection # サンプルデータの読み込み(乳がんデータ) X,y = datasets.load_breast_cancer(return_X_y=True, as_frame=True) # 目的関数の設定(ステップ1) def objective(trial): #ハイパーパラメータの集合を定義する model = ensemble.RandomForestClassifier() params = {"n_estimators":trial.suggest_int("n_estimators", 10,1000 ), "max_depth":trial.suggest_int("max_depth", 2, 50, log=True ) } classifier_obj = model.set_params(**params) #良し悪しを判断するメトリクスを定義する score = model_selection.cross_val_score(classifier_obj, X, y, n_jobs=-1, cv=10 ) accuracy = score.mean() return accuracy # 目的関数の最適化を実行する(ステップ2) study = optuna.create_study(direction="maximize") study.optimize(objective, n_trials=100) # 最適解の出力 print(f"The best value is : \n {study.best_value}") print(f"The best parameters are : \n {study.best_params}")
以下、実行結果です。
OptunaのCV関数(OptunaSearchCV)を使う方法
Optunaで、scikit-learnのモデルをCV(クロスバリデーション)を実施するとき、OptunaSearchCVを使っても実施できます。
今回は、ランダムフォレストで実施してみます。
簡単な流れは以下です。
- モデル設定
- ハイパーパラメータ探索の設定
- CV(クロスバリデーション)の設定
- ハイパーパラメータの探索の実施
- 最適解の出力
先ず、モデルの設定です。ランダムフォレストです。
以下、コードです。
# ライブラリーの読み込み import optuna import pandas as pd from sklearn import ensemble from sklearn import datasets # サンプルデータの読み込み(乳がんデータ) X,y = datasets.load_breast_cancer(return_X_y=True, as_frame=True) # モデル設定 model = ensemble.RandomForestClassifier()
次に、ハイパーパラメータ探索の設定です。
OptunaSearchCVでは、param_distributions
引数を使用してハイパーパラメータの探索空間を定義します。
通常の設定時(前回)とは異なる関数を使って行いますが、やっていることはほぼ同じす。
-
optuna.distributions.FloatDistribution:実数値の範囲を指定するための分布。一様分布や対数一様分布などを選択可能。
- optuna.distributions.IntDistribution:整数値の範囲を指定するための分布。
- optuna.distributions.CategoricalDistribution:カテゴリ変数のサンプリング。
以下、コードです。
# ハイパーパラメータの探索の設定 params = { "n_estimators":optuna.distributions.IntDistribution(10,1000), "max_depth":optuna.distributions.IntDistribution(2,50,log=True) }
CV(クロスバリデーション)の設定をします。
以下、コードです。
# CV(クロスバリデーション)の設定 optuna_search = optuna.integration.OptunaSearchCV(model, params, cv=10, n_jobs=-1, n_trials=100, scoring='accuracy' )
では、CVで評価しながらハイパーパラメータの探索を実施します。
以下、コードです。
# ハイパーパラメータの探索の実施 optuna_search.fit(X, y)
結果を見てみます。
以下、コードです。
# 最適解の出力 print(f"The best value is : \n {optuna_search.best_score_}") print(f"The best parameters are : \n {optuna_search.best_params_}")
以下、実行結果です。
まとめ
scikit-learnのモデルをOptunaでCV(クロスバリデーション)を実施する方法は2種類あります。
- 良し悪しを判断するメトリクスにscikit-learnのCVを指定する方法
- OptunaのCV関数(OptunaSearchCV)を使う方法
今回は、前回の乳がんの例の分類問題に対し、OptunaのCV関数(OptunaSearchCV)を使う方法を紹介しました。
非常に手軽にできますので、興味ある方は一度チャレンジしてみてください。
Python のハイパーパラメータ自動最適化ライブラリー Optuna その4 – 時系列Facebook ProphetモデルをOptunaで自動最適化 –