この記事はMachine Learning Advent Calendar 2016の17日目の記事です。
今回はブラックボックス関数を最小化するパラメータを推定することが可能なscikit-optimizeというライブラリについて紹介したいと思います。
- scikit-optimize公式ページ(https://scikit-optimize.github.io/)
- githubページ(https://github.com/scikit-optimize/scikit-optimize)
Installation
今回実験した環境は次の通り。
- 実行環境: MacOS Siera
- Python 3.5.2
インストールはpipから簡単にできる。
pip install scikit-optimize
Example
githubのREADME.mdにあるGetting Startedではある関数にノイズを加えたものである。関数が分かれば良いのですが、実際は関数が未知となっていることがあります。そのような場合にあるデータ点xを関数はわからないが評価は出来る場合にBayesian Optimizationという方法使って最小化するxを求めることができる。
import numpy as np
from skopt import gp_minimize
def f(x):
return (np.sin(5 * x[0]) * (1 - np.tanh(x[0] ** 2)) * np.random.randn() * 0.1)
res = gp_minimize(f, [(-2.0, 2.0)])
このresは次のような変数を持っている。
- fun: f(x)の最小値
- func_vals: 各試行で得られたf(x)の値
fun = min(func_vals)
- models: 各試行で利用したモデル
- random_state: seed
- space: 探索した範囲(Space)
- specs: パラメータの一覧
- x: 最小値を得られたxの値
- x_iters: 各試行で評価されたxの値
For Machine Learning
機械学習(特に, 教師あり学習)といえばデータ集合からモデルを構築し, 未知のデータに対する予測性能を向上させるのが目的になります。その際, 機械学習では交差検定と様々な評価指標を用いてモデルを評価します。更に, より高性能なモデルを構築したい場合にはハイパーパラメータのチューニングが不可欠になります。
今回はこのハイパーパラメータのチューニングをskoptを使ってやってみます。
準備
データと機械学習のモデルを決めます。
こちらのページにも例が載っていますが, せっかくなので少し違うモデルでやってみます。
- データ: breast_cancer
- モデル: GradientBoostedTreeClassifier (scikit-learn)
- 評価: AUC
手順
- データとモデルを準備します。
from sklearn.datasets import load_breast_cancer
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.model_selection import cross_val_score
data = load_breast_cancer()
X, y = data.data, data.target
n_features = len(X)
model = GradientBoostingClassifier
- ブラックボックス関数を定義します。
def objective(params):
max_depth, lr, max_features, min_samples_split, min_samples_leaf = params
model.set_params(max_depth=max_depth,
max_features=max_features,
learning_rate=lr,
min_samples_split=min_samples_split,
min_samples_leaf=min_samples_leaf)
# gp_minimizeは最小化しか出来ないので高いほど性能が高いと示すような指標は負の値を使う必要がある
return -np.mean(cross_val_score(model, X, y, cv=5, scoring='roc_auc'))
- パラメータの探索範囲(Space)を決めます。
space = [(1, 5), (10**-5, 10**-1, "log-uniform"), (1, n_features), (2, 30), (1, 30)]
- 探索の初期値を決めます。
x0 = [3, 0.01, 6, 2, 1]
- gp_minimizeを使って最小化するハイパーパラメータを推定します。
res = gp_minimize(objective, space, x0=x0, n_calls=50)
print(res.fun) # -0.993707074488
print(res.x) # [5, 0.096319962593215167, 1, 30, 22]
このようにして最適なハイパーパラメータを求めることが出来ました。
ちなみにこのデータセットだとgp_minimizeにかかる時間は17[s]でした。
Others
公式サイトには, 上記に説明したもの以外にもいくつかサンプルが載っています。
- Bayesian optimization
- Hyperparameter optimization
- Store and load results
- Strategy comparison
- Visualizing results