前回に続いて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でも探索できるので、真価が発揮されるのはもっと複雑な例の時だと思います。)