のんびりしているエンジニアの日記

ソフトウェアなどのエンジニア的な何かを書きます。

Hyperoptを使った、関数の最適化

Sponsored Links

皆さんこんにちは
お元気ですか。私は元気です。

本日はhyperoptと呼ばれるライブラリを紹介したいと思います。
KaggleのForamで時々あがっていたので、気になっていました。

Hyperoptについて

What is Hyperopt?

hyperoptはTree-structured Parzen Estimator Approach(TPE)やRandomSearchを使って、最適化を行うライブラリです。
しかし、掲載論文を読む時間がないので、最適化の方法はともかく、
このライブラリは最小化するパラメータの推定を行ってくれます。
(他のもできるかもしれませんが、今回は調べていません。)

Hyperoptについて、Scipy2013で発表をしているようです。興味が有る人は以下のビデオもどうぞ。

www.youtube.com

Install

sudo pip install hyperopt

何に使えるのか

機械学習のパラメータチューニングに使っている人は多いようです。
時々、Kaggleで見ることがあります。

サンプルを書いてみた

簡単なサンプルを参考にしながら書いてみました。
以下のコードの意味ですが、簡単に言いますと、function内部の
関数を最小にするように動作しています。

#coding:utf-8
from hyperopt import fmin, tpe, hp, rand

def function(args):
    x,y = args
    return x ** 2 + y ** 2

space = [hp.uniform('x',0,1), hp.normal('y', 0, 1)]

best = fmin(function,space,algo=rand.suggest,max_evals=100)
print best

best = fmin(function,space,algo=tpe.suggest,max_evals=100)
print best

第一引数に関数の最小化、パラメータ、TPEアルゴリズムで提案、反復回数となっています。
まだまだよくわからない箇所があるので、これを使って実際に
機械学習の最適化を行ってみたいと思います。

Scikit-learnで学ぶ機械学習のパラメータ最適化

機械学習でPythonといえば、scikit-learnが最も有名でしょう。
早速やってみた。

#coding:utf-8
from hyperopt import fmin, tpe, hp, rand
import numpy as np
from sklearn.metrics import accuracy_score
from sklearn import svm

parameter_space_svc = {
	'C':hp.loguniform("C", np.log(1), np.log(100)),
	'kernel':hp.choice('kernel',['rbf','poly']),
	'gamma': hp.loguniform("gamma", np.log(0.001), np.log(0.1)),
}

from sklearn import datasets
iris = datasets.load_digits()

train_data = iris.data[0:1300]
train_target = iris.target[0:1300]
test_data = iris.data[1300:-1]
test_target = iris.target[1300:-1]

count = 0

def function(args):
	print args
	clf = svm.SVC(**args)
	clf.fit(train_data,train_target)
	prediction = clf.predict(test_data)
	global count
	count = count + 1
	score = accuracy_score(test_target,prediction)
	print "%s回目の推測" % str(count),score
	return -accuracy_score(test_target,prediction)

best = fmin(function,parameter_space_svc,algo=tpe.suggest,max_evals=100)
print "best estimate parameters",best

clf = svm.SVC(**best)
print clf

ポイントは、2点
①辞書型にして渡るように辞書を構築し、中でhpを使い、パラメータの範囲や出方を決定していること。
②最大値への最適化はできないので、最小値への最適化に問題を変換(-をつける)
し、パラメータチューニングの問題を解いていること。
上記の式を応用すると、他の機械学習ライブラリに対しても
Hyperoptを適用することができます。

以下、ログです。パラメータを推定しながら、動いていることがわかります。
(長いログになったので省略しています。興味のある人はやってみてください。)

{'kernel': 'rbf', 'C': 7.193526575307785, 'gamma': 0.026663099972129244}
1回目の推測 0.197580645161
{'kernel': 'rbf', 'C': 95.55790927197563, 'gamma': 0.024863130263766336}
2回目の推測 0.219758064516
{'kernel': 'poly', 'C': 2.4628795490270203, 'gamma': 0.09203400263813753}
3回目の推測 0.959677419355
(略)
{'kernel': 'rbf', 'C': 10.928134685112381, 'gamma': 0.009527462400869574}
97回目の推測 0.711693548387
{'kernel': 'rbf', 'C': 15.893094144901005, 'gamma': 0.0017010025860481686}
98回目の推測 0.967741935484
{'kernel': 'poly', 'C': 1.1348590065991755, 'gamma': 0.08212341793223293}
99回目の推測 0.959677419355
{'kernel': 'rbf', 'C': 15.822412405153285, 'gamma': 0.005563271969641763}
100回目の推測 0.887096774194
best estimate parameters {'kernel': 0, 'C': 1.0905097294517248, 'gamma': 0.0010874401961848724}
SVC(C=1.09050972945, cache_size=200, class_weight=None, coef0=0.0, degree=3,
  gamma=0.00108744019618, kernel=0, max_iter=-1, probability=False,
  random_state=None, shrinking=True, tol=0.001, verbose=False)