Help us understand the problem. What is going on with this article?

[最適化問題]Optuna vs Hyperopt

はじめに

最適化フレームワークとして、OptunaHyperoptがあります。一体どちらが優れているのか気になったので、関数最適化問題を使って比較してみようと思います。
2つのフレームワークに関しては別記事で紹介しているので、そちらを参考にしてください。
Optunaを使って関数最適化をしてみる
Hyperoptを使って関数最適化をしてみる

比較実験

今回は

x^2+y^2+z^2

の最小化問題を最適化していきます。
試行ごとに結果が異なるため, 3回試行してみようと思います。

コード

今回、実験するために使用したコードは以下になります。

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

# optuna用の目的関数を設定(今回はx^2+y^2+z^2)
def objective_optuna(trial):
    # 最適化するパラメータを設定
    param = {
        'x': trial.suggest_uniform('x', -100, 100),
        'y': trial.suggest_uniform('y', -100, 100),
        'z': trial.suggest_uniform('z', -100, 100)
    }
    # 評価値を返す(デフォルトで最小化するようになっている)
    return param['x'] ** 2 + param['y'] ** 2 + param['z'] ** 2

# optunaで最適化実行
def optuna_exe():
    # studyオブジェクト生成
    study = optuna.create_study()
    # 最適化実行
    study.optimize(objective_optuna, n_trials=500)
    # ベストパラメータ表示
    print(study.best_params)
    # ベスト目的関数値を表示
    print(study.best_value)

    epoches = []    # 試行回数格納用
    values = []    # ベストvalue格納用
    best = 100000
    # best更新
    for i in study.trials:
        if best > i.value:
            best = i.value
        epoches.append(i.number + 1)
        values.append(best)
    return epoches, values

# 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 = [] # ベストvalue格納用
    best = 100000
    # best更新
    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)

    return epoches, values

def plot_graph():
    result_optuna = optuna_exe()
    result_hyperopt = hyperopt_exe()
    epoch_optuna = result_optuna[0]
    value_optuna = result_optuna[1]
    epoch_hyperopt = result_hyperopt[0]
    value_hyperopt = result_hyperopt[1]

    # グラフの描画
    fig, ax = plt.subplots()
    ax.set_xlabel("trial")
    ax.set_ylabel("value")
    ax.set_title("Optuna vs Hyperopt")
    ax.grid() # グリッド線を入れる
    ax.plot(epoch_optuna, value_optuna, color="red", label="Optuna")
    ax.plot(epoch_hyperopt, value_hyperopt, color="blue", label="Hyperopt")
    ax.legend(loc=0) # 凡例
    plt.show() # グラフ表示

if __name__ == '__main__':
    plot_graph()

実験結果1回目

Optuna:
'x': 0.2690396239515218,
'y': -1.75236444646743,
'z': 0.3724308175904496,
best_value:3.2818681863901693

Hyperopt:
'x': -2.9497423868903834,
'y': 0.13662455602710644,
'z': -3.844496541052724,
best_value:23.499800072493738
Figure_1.png

最終的なbest_valueはOptunaが優れていますね。
グラフより収束速度もOptunaが優れているかなといった感じですかね。

実験結果2回目

Optuna:
'x': 0.7811129871251672,
'y': 0.4130867942356189,
'z': 0.6953642534092288,
best_value:1.2643096431468364

Hyperopt:
'x': -3.7838067947126675,
'y': -2.595648793357423,
'z': -2.683504623035553,
best_value:28.255783580024783
Figure_2.png

2回目も1回目と同様、最終的なbest_valueと収束速度の面でOptunaが優れていますかね。

実験結果3回目

Optuna:
'x': -0.19339325990518663,
'y': -0.0030977352573082623,
'z': 0.4961595538587318,
best_value:0.2835848518257752

Hyperopt:
'x': 2.810074634010315,
'y': -1.2603362587820195,
'z': -0.7356174272489406,
best_value:10.026099933181214
Figure_3.png

3回目も最終的なbest_valueの値はOptunaが優れていました。収束速度はあまり変わらない気がしますね。

結論

最終的な最良目的関数値、収束速度の面でOptunaが優れている、との結論に至りました。
最適化問題をもう少し難しくしたら、差も大きく出るのだろうか...

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした