基本情報
まずは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の時に最小値を取ります。
ここでは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_estimators
、max_depth
、min_samples_split
、min_samples_leaf
、max_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によるブラックボックス最適化
www.amazon.co.jp
オススメ書籍
・化学のためのPythonによるデータ解析・機械学習入門
データ分析に必要な最低限の知識を解説したうえで、化学プラントで得られるデータの扱い方が紹介されています。
脱ブタン塔や排煙脱硝装置を例に取り上げられておりイメージしやすくなっています。
-
化学のためのPythonによるデータ解析・機械学習入門
www.amazon.co.jp
・Pythonによる時系列分析: 予測モデル構築と企業事例
プロセス製造において時系列データの分析は欠かせません。
どのように時系列予測モデルを構築し、ビジネスへ活用していくかを詳細なPythonコードとともに解説してくれます。
-
Pythonによる時系列分析: 予測モデル構築と企業事例
www.amazon.co.jp
・PyCaretで学ぶ 機械学習入門
機械学習モデルを構築するのは想像以上に手間がかかります。
その一連の作業を自動化できるPyCaretというライブラリの使い方が分かりやすく解説されています。
-
PyCaretで学ぶ 機械学習入門
www.amazon.co.jp