Optunaを使って自動でハイパーパラメータを探索する

2023年9月16日

広告を含みます





基本情報

まずはOptunaについて簡単に紹介します。

Optunaとは?

Optunaとは、 Preferred Networksが公開しているハイパーパラメータの最適化を自動化するためのフレームワークです。

ユーザーが最適化したい関数を定義するだけで、ハイパーパラメータの探索を開始できる分かりやすさも特徴的です。

Preferred NetworksはENEOSと共同でプラントのAI自動制御技術を開発するなど、AI開発企業の中でも馴染みがあります。

パラメータの探索方法

TPE(Tree-structured Parzen Estimator)という手法を用いることで、ハイパーパラメータ空間の探索を効率的に行います。

基本的にはランダムにパラメータを選択してスコアを算出する作業を繰り返します。

ただそれだけでは効率が悪いため、前回のパラメータのスコアを基に次のパラメータを微調整するような仕様になっています。

Optunaを使ってみる

簡単な例からOptunaの使用方法を解説します。

ライブラリの準備

利用にあたり、以下のコマンドでOptunaをインストールします。

pip install optuna

使用時は以下のコマンドでインポートします。

import optuna

最適化するための関数を準備する

今回は下に凸の2次関数を用います。

x=2の時に最小値を取ります。

題材となる2次関数

ここではobjective関数を新たに定義します。

def objective(trial):
    x = trial.suggest_float('x', -10, 10)
    return (x - 2) ** 2

trial.suggest_float('x', -10, 10)で"x"を-10~10の範囲で探索するよう指定しています。

return (x - 2) ** 2で最適化する関数を指定しています。

正確には、returnで返される値を最小化したり最大化したりしています。

そのため、必ずreturnに関数を記載する必要なく、以下のような関数でも問題ありません。

def objective(trial):
    x = trial.suggest_float('x', -10, 10)
    answer = (x - 2) ** 2
    return answer

関数を最適化する

まずoptuna.create_study()を実行し、studyオブジェクトを作ります。

study = optuna.create_study()

デフォルトは最小値ですが、optuna.create_study(direction="maximize")と指定することで最大値を求めるようになります。

次に、最初に定義したobjective関数を用いて、xの値を最適化します。

この例では試行を100回繰り返しています。

study.optimize(objective, n_trials=100)

最適化されたパラメータを確認する

最後に、最適化されたobjective関数の値と、その時のxの値を出力します。

print('Best value:', study.best_value)
print('Best parameters:', study.best_params)

以下のように出力されました。

Best value: 1.5305024591002886e-05
Best parameters: {'x': 2.0039121636712953}

一番最適な値である2に近い値となっています。

ちなみにstudy.optimize(objective, n_trials=10000)として10000回試行を行ってもx=2にはたどり着きません。

これは関数を指定する時にx = trial.suggest_float('x', -10, 10)suggest_floatメソッドを使っており、浮動小数点数で探索しているためです。

代わりにx = trial.suggest_int('x', -10, 10)のようにsuggest_intメソッドを使うことで整数のみで探索できます。

機械学習モデルで使う

機械学習モデルでOptunaを使用する例を紹介します。

ランダムフォレスト(Scikit-learn)

Scikit-learnで扱えるモデルに関するハイパーパラメータ探索を、ランダムフォレストを例に紹介します。

サンプルデータセットとしてirisデータセットを用いています。

import optuna
from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

data = load_iris()
X = data.data
y = data.target
X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.2, random_state=42)

次に関数を定義します。

始めにn_estimatorsmax_depthmin_samples_splitmin_samples_leafmax_featuresの5種類を最適化方法を指示します。

以降は一般的な機械学習モデルを構築するコードです。

classifierオブジェクトを作成し、fitメソッドでパラメータチューニング、predictメソッドで予測、accuracy_score関数で正解率を算出しています。

今回は正解率を最大化したいため、最後にreturn accuracyで正解率を返すようにしています。

def objective(trial):
    n_estimators = trial.suggest_int('n_estimators', 2, 150)
    max_depth = trial.suggest_int('max_depth', 1, 32, log=True)
    min_samples_split = trial.suggest_float('min_samples_split', 0.1, 1)
    min_samples_leaf = trial.suggest_float('min_samples_leaf', 0.1, 0.5)
    max_features = trial.suggest_categorical('max_features', ['auto', 'sqrt', 'log2'])

    classifier = RandomForestClassifier(
        n_estimators=n_estimators, 
        max_depth=max_depth, 
        min_samples_split=min_samples_split,
        min_samples_leaf=min_samples_leaf, 
        max_features=max_features,
        random_state=42
    )

    classifier.fit(X_train, y_train)
    y_pred = classifier.predict(X_valid)
    accuracy = accuracy_score(y_valid, y_pred)

    return accuracy

そして最後にパラメータの最適化を行い出力します。

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

print('Best trial:')
trial = study.best_trial
print('  Accuracy: {}'.format(trial.value))
print('  Params: ')
for key, value in trial.params.items():
    print('    {}: {}'.format(key, value))

以下のような出力が得られます。

Best trial:
 Accuracy: 1.0
 Params:
  n_estimators: 75
  max_depth: 25
  min_samples_split: 0.33120922897773897
  min_samples_leaf: 0.1820783492221814
  max_features: log2

LightGBM

ランダムフォレストに似ていますが、LightGBMのコード例も紹介します。

パラメータが増えていますが、実施している内容は同じです。

import numpy as np
import optuna

import lightgbm as lgb
import sklearn.datasets
import sklearn.metrics
from sklearn.model_selection import train_test_split

data, target = sklearn.datasets.load_breast_cancer(return_X_y=True)
train_x, valid_x, train_y, valid_y = train_test_split(data, target, test_size=0.25)

def objective(trial):
    
    dtrain = lgb.Dataset(train_x, label=train_y)

    param = {
        "objective": "binary",
        "metric": "binary_logloss",
        "verbosity": -1,
        "boosting_type": "gbdt",
        "lambda_l1": trial.suggest_float("lambda_l1", 1e-8, 10.0, log=True),
        "lambda_l2": trial.suggest_float("lambda_l2", 1e-8, 10.0, log=True),
        "num_leaves": trial.suggest_int("num_leaves", 2, 256),
        "feature_fraction": trial.suggest_float("feature_fraction", 0.4, 1.0),
        "bagging_fraction": trial.suggest_float("bagging_fraction", 0.4, 1.0),
        "bagging_freq": trial.suggest_int("bagging_freq", 1, 7),
        "min_child_samples": trial.suggest_int("min_child_samples", 5, 100),
    }

    gbm = lgb.train(param, dtrain)
    preds = gbm.predict(valid_x)
    pred_labels = np.rint(preds)
    accuracy = sklearn.metrics.accuracy_score(valid_y, pred_labels)

    return accuracy

study = optuna.create_study(direction="maximize")
study.optimize(objective, n_trials=100)

print("Number of finished trials: {}".format(len(study.trials)))

print("Best trial:")
trial = study.best_trial

print("  Value: {}".format(trial.value))

print("  Params: ")
for key, value in trial.params.items():
    print("    {}: {}".format(key, value))

参考資料

Optuna 公式ドキュメント

・Optunaによるブラックボックス最適化

基本的な使い方から最適化まで、Optunaを学ぶならこの書籍がオススメです。

Optunaによるブラックボックス最適化
Optunaによるブラックボックス最適化

www.amazon.co.jp

オススメ書籍

・化学のためのPythonによるデータ解析・機械学習入門

データ分析に必要な最低限の知識を解説したうえで、化学プラントで得られるデータの扱い方が紹介されています。
脱ブタン塔や排煙脱硝装置を例に取り上げられておりイメージしやすくなっています。

化学のためのPythonによるデータ解析・機械学習入門
化学のためのPythonによるデータ解析・機械学習入門

www.amazon.co.jp

・Pythonによる時系列分析: 予測モデル構築と企業事例

プロセス製造において時系列データの分析は欠かせません。
どのように時系列予測モデルを構築し、ビジネスへ活用していくかを詳細なPythonコードとともに解説してくれます。

Pythonによる時系列分析: 予測モデル構築と企業事例
Pythonによる時系列分析: 予測モデル構築と企業事例

www.amazon.co.jp

・PyCaretで学ぶ 機械学習入門

機械学習モデルを構築するのは想像以上に手間がかかります。
その一連の作業を自動化できるPyCaretというライブラリの使い方が分かりやすく解説されています。

PyCaretで学ぶ 機械学習入門
PyCaretで学ぶ 機械学習入門

www.amazon.co.jp







記事への問い合わせはこちら

-データサイエンス
-