Optuna 入門 ハイパーパラメータを自動最適化してみよう!

Optuna とは

Optuna(オプチュナ)とは、 Preferred Networks社が開発しているハイパーパラメータの最適化を自動化するためのフレームワークです。チュートリアルページはこちらから確認できます。

Optunaのインストール

pipコマンドでインストールします。

pip install optuna

Jupyter NotebookもしくはGoogle Colabから実行する場合は、先頭に!を付けます。

!pip install optuna

K分割交差検証を実施する

先ずはOptunaを用いる前にK分割交差検証を実施してみましょう。

今回はロジスティック回帰を用いて、scikit-learnに付属の乳がんデータセットを用いて分類器を作ります。

from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score 
from sklearn.model_selection import train_test_split
import numpy as np
import optuna
from sklearn.model_selection import cross_validate

from sklearn import datasets
cancer = datasets.load_breast_cancer()

X = cancer.data
y = 1- cancer.target

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, shuffle=True, random_state=123)

# 解説
# solverは、最適化問題で使用するアルゴリズムです。
# 今回は、'lbfgs'を指定しています。他には 'newton-cg', 'lbfgs', 'liblinear', 'sag', 'saga'があります。デフォルトは'lbfgs'ですので、明示的に'lbfgs'を指定しています。
# 最大反復回数は max_iter で設定が可能です。デフォルトは100回ですが、デフォルトのままですと警告が出てしまうため、max_iterを10000に指定しています。
model = LogisticRegression(solver='lbfgs',max_iter=10000)

# 訓練
model.fit(X_train, y_train)

# 予測
pred = model.predict(X_test)

# 正解率を出力
accuracy = 100.0 * accuracy_score(y_test, pred)
print("正解率: {}".format(accuracy))

出力結果

正解率: 98.24561403508771

from sklearn.model_selection import cross_val_score

# 5分割交差検証による汎化性能の評価
scores = cross_val_score(model, X_train, y_train, cv=5)

# 評価結果の出力
print("5分割交差検証による汎化性能の評価: {}".format(100 * scores.mean()))

出力結果

5分割交差検証による汎化性能の評価: 94.94505494505493

Optunaでハイパーパラメータを最適化する

Optunaでハイパーパラメータを最適化していきます。

Optunaの基本的な使い方として、

optuna.create_study()を実行し、optuna.studyインスタンスを作ります。

引数にdirectionには、’maximize’や’minimize’を渡せます。

その後、study.optimize()に、関数を渡して最適化します。

今回はObjectiveクラスを作成し、objectiveでインスタンス化しているため、objectiveを引数に渡しています。

from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score 
from sklearn.model_selection import train_test_split
from sklearn.model_selection import cross_validate

import numpy as np
import optuna

class Objective:
    def __init__(self, X, y):
        # 変数X,yの初期化
        self.X = X
        self.y = y

    def __call__(self, trial):
        # ハイパーパラメータの設定
        params = {
            # 最適化アルゴリズムを指定
            'solver' : trial.suggest_categorical('solver', ['newton-cg', 'lbfgs', 'liblinear', 'sag', 'saga']),
            # 正則化の強さを指定(0.0001から10まで)
            'C': trial.suggest_loguniform('C', 0.0001, 10),
            # 最大反復回数(*ソルバーが収束するまで)
            'max_iter': trial.suggest_int('max_iter', 100, 100000)
            }

        model = LogisticRegression(**params)

        # 評価指標として正解率の最大化を目指す
        scores = cross_validate(model,
                                X=self.X, 
                                y=self.y,
                                scoring='accuracy', # 正解率を指定(https://scikit-learn.org/stable/modules/model_evaluation.html#scoring-parameter)
                                n_jobs=-1) # 並行して実行するジョブの数(-1は全てのプロセッサを使用)
        return scores['test_score'].mean()

# ハイパーパラメータの探索
objective = Objective(X_train, y_train)
study = optuna.create_study(direction='maximize') # 最大化
study.optimize(objective, timeout=60)

# ベストパラメータを出力
print('params:', study.best_params)

実行後、ハイパーパラメータの探索が終わり、ベストパラメータを出力しています。

ベストパラメータを出力していることは、best_params を出力することで、ベストなパラメータを確認できます。

study.best_params

出力結果

{'C': 8.688219513706178, 'max_iter': 34661, 'solver': 'liblinear'}

上記は辞書型のため、keyを指定して出力することもできます。

print(study.best_params['solver'])
print(study.best_params['max_iter'])
print(study.best_params['C'])

出力結果

liblinear
34661
8.688219513706178

ちなみに、一番良かったスコアは下記で算出できます。

print(study.best_value)

出力結果

0.953846153846154

ハイパーパラメター探索で特定した値を設定する

from sklearn.metrics import confusion_matrix, accuracy_score
from sklearn.metrics import precision_score, recall_score

model = LogisticRegression(
    # ハイパーパラメータ探索で特定した値を設定
    solver = study.best_params['solver'],
    C = study.best_params['C'],
    max_iter = study.best_params['max_iter']
)

model.fit(X_train, y_train)
pred = model.predict(X_test)
# 正解率の出力
print("Accuracy: {:.5f}".format(100 * accuracy_score(y_test, pred)))

# 混同行列の出力
print(confusion_matrix(y_test, pred))

# 適合率
print("Precision: {:.5f}".format(100 * precision_score(y_test, pred)))
# 再現率
print("Recall: {:.5f}".format(100 * recall_score(y_test, pred)))

出力結果

Accuracy: 98.24561
[[73  0]
 [ 2 39]]
Precision: 100.00000
Recall: 95.12195

機械学習や統計を効率よく学ぶには?

機械学習や統計を効率よく学ぶには、普段から機械学習や統計学を用いて業務をしている現役のデータサイエンティストに質問できる環境で学ぶことです。
質問し放題かつ、体系的に学べる動画コンテンツでデータ分析技術を学びたい方は、オンラインで好きな時間に勉強できるAI Academy Bootcampがオススメです。受講料も業界最安値の35,000円(6ヶ月間質問し放題+オリジナルの動画コンテンツ、テキストコンテンツの利用可能)なので、是非ご活用ください。

1 COMMENT

現在コメントは受け付けておりません。