Hyperoptを使って関数最適化をしてみる


はじめに

Hyperoptはハイパーパラメータの自動最適化フレームワークです。主に機械学習のハイパーパラメータチューニングのために使用されるようです。

準備

まずはライブラリをインストールしましょう。
pip install hyperoptでインストールできます。

実験

今回は

x^2+y^2+z^2

の最小化問題を最適化していきましょう。

目的関数の定義

はじめに目的関数を定義しましょう。

# 目的関数を設定
def objective_hyperopt(args):
    x, y, z = args
    return x ** 2 + y ** 2 + z ** 2

最適化実行

最初に最適化するパラメータの探索空間を設定しましょう。
そして、fmin()を使って探索を開始します。引数のmax_evalsで探索回数を設定しましょう。

# hyperoptで最適化実行
def hyperopt_exe():
    space = [
        hp.uniform('x', -100, 100),
        hp.uniform('y', -100, 100),
        hp.uniform('z', -100, 100)
    ]

    # 探索の様子を記録するためのオブジェクト
    trials = Trials()

    # 探索開始
    best = fmin(objective_hyperopt, space, algo=tpe.suggest, max_evals=500, trials=trials)

最終的に結果を知りたい場合は以下を追加しましょう。

    # 結果を出力する
    print(best)

探索中の情報はtrialsオブジェクトから取り出しましょう。以下を追加することで各試行でのパラメータや目的関数値を表示できます。

    # 探索過程を調べる
    for i, n in zip(trials.trials, range(500)):
        vals = i['misc']['vals']
        result = i['result']['loss']
        print('vals:', vals, 'result:', result)

コード

今回したコードは以下のようになります。

# -*- coding: utf-8 -*-
import hyperopt
from hyperopt import hp
from hyperopt import fmin
from hyperopt import tpe
from hyperopt import Trials
import matplotlib.pyplot as plt

# hyperopt用の目的関数を設定
def objective_hyperopt(args):
    x, y, z = args
    return x ** 2 + y ** 2 + z ** 2

# hyperoptで最適化実行
def hyperopt_exe():
    # 探索空間の設定
    space = [
        hp.uniform('x', -100, 100),
        hp.uniform('y', -100, 100),
        hp.uniform('z', -100, 100)
    ]

    # 探索の様子を記録するためのオブジェクト
    trials = Trials()

    # 探索開始
    best = fmin(objective_hyperopt, space, algo=tpe.suggest, max_evals=500, trials=trials)
    # 結果を出力する
    print(best)

    epoches = []
    values = []
    best = 100000
    # 探索過程を調べる
    for i, n in zip(trials.trials, range(500)):
        if best > i['result']['loss']:
            best = i['result']['loss']
        epoches.append(n+1)
        values.append(best)
        vals = i['misc']['vals']
        result = i['result']['loss']
        print('vals:', vals, 'result:', result)

    # グラフを描画
    plt.plot(epoches, values, color="red")
    plt.title("hyperopt")
    plt.xlabel("trial")
    plt.ylabel("value")
    plt.show()

if __name__ == '__main__':
    hyperopt_exe()

結果

今回の実験結果の図は以下のようになりました.
早い段階で収束してきていますね。

参考サイト

Hyperoptを使った、関数の最適化
Python: Hyperopt で機械学習モデルのハイパーパラメータを選ぶ