Optunaでscikit-learnのパラーメーター最適化

前回に続いてOptunaの記事です。
今回はscikit-learnのモデルをチューニングしてみましょう。

ドキュメントのうち、最初に読むのはこちら。
Advanced Configurations
少々分かりにくいですが、これでカテゴリカルナ値や、一様分布、対数一様分布からのサンプリング方法が分かります。
ただ、全然具体的で無いので、githubの方にあるexamplesもみましょう。
https://github.com/pfnet/optuna/tree/master/examples

今回のコードはその中にある、 sklearn_simple.py を参考にして書きました。
(自分の理解のため、少々アレンジしていますが、元々のより良いものにはなって無いです)

データは定番のirisを使い、SVMとランダムフォレストの二つのモデルで、それぞれ1種類ずつパラメーターを最適化し、
最も良いものを探索しています。


import optuna
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
iris = load_iris()
X = iris.data
y = iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)


def objective(trial):

    classifier_name = trial.suggest_categorical(
                        'classifier',
                        ['SVC', 'RandomForest']
                    )
    if classifier_name == 'SVC':
        svc_c = trial.suggest_loguniform('svc_c', 1e-10, 1e10)
        classifier_obj = SVC(C=svc_c, gamma='auto')
    else:
        rf_max_depth = int(trial.suggest_int('rf_max_depth', 2, 32))
        classifier_obj = RandomForestClassifier(
                max_depth=rf_max_depth,
                n_estimators=10
        )
    classifier_obj.fit(X_train, y_train)
    return classifier_obj.score(X_test, y_test)


study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=100)
print(study.best_trial)

# 出力結果
"""
FrozenTrial(number=15, state=,
 value=1.0, datetime_start=datetime.datetime(2019, 10, 8, 0, 43, 30, 243112),
 datetime_complete=datetime.datetime(2019, 10, 8, 0, 43, 30, 310756),
 params={'classifier': 'RandomForest', 'rf_max_depth': 10},
 distributions={'classifier': CategoricalDistribution(choices=('SVC', 'RandomForest')),
 'rf_max_depth': IntUniformDistribution(low=2, high=32)},
 user_attrs={}, system_attrs={'_number': 15},
 intermediate_values={}, trial_id=15)
"""

今回は RandomForest で、 rf_max_depth を 10とするのが最適だったようです。
(実行するたびに結果が変わります。)

これはこれで非常に単純な例なのですが、それでも、最初のカテゴリカル変数によって以降の変数たちを
if文で場合分けしてかけるなど、hyperoptに比べて柔軟な探索ができる、ってのは少しわかったような気がします。
(もっとも、このくらいならhpyeroptでも探索できるので、真価が発揮されるのはもっと複雑な例の時だと思います。)

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です