[PYTHON] [Problème d'optimisation] Optuna vs Hyperopt

introduction

Les cadres d'optimisation incluent Optuna </ font> et Hyperopt </ font>. Je me demandais lequel était le meilleur, alors je vais le comparer en utilisant le problème d'optimisation des fonctions. Les deux cadres sont présentés dans un article séparé, veuillez donc vous y référer. Essayez l'optimisation des fonctions avec Optuna Essayez l'optimisation des fonctions avec Hyperopt

Expérience comparative

Cette fois

x^2+y^2+z^2

Nous optimiserons le problème de minimisation de. Les résultats seront différents pour chaque essai, je vais donc essayer trois fois.

code

Le code utilisé pour cette expérience est le suivant.

# -*- 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

#Définir la fonction d'objectif pour optuna(Cette fois x^2+y^2+z^2)
def objective_optuna(trial):
    #Définissez les paramètres pour optimiser
    param = {
        'x': trial.suggest_uniform('x', -100, 100),
        'y': trial.suggest_uniform('y', -100, 100),
        'z': trial.suggest_uniform('z', -100, 100)
    }
    #Renvoie la valeur d'évaluation(Il est conçu pour être minimisé par défaut)
    return param['x'] ** 2 + param['y'] ** 2 + param['z'] ** 2

#Optimisé avec optuna
def optuna_exe():
    #création d'objet d'étude
    study = optuna.create_study()
    #Exécution de l'optimisation
    study.optimize(objective_optuna, n_trials=500)
    #Meilleur affichage des paramètres
    print(study.best_params)
    #Afficher la meilleure valeur de fonction objective
    print(study.best_value)

    epoches = []    #Pour stocker le nombre d'essais
    values = []    #Pour stocker la meilleure valeur
    best = 100000
    #meilleure mise à jour
    for i in study.trials:
        if best > i.value:
            best = i.value
        epoches.append(i.number + 1)
        values.append(best)
    return epoches, values

#Définir la fonction objectif pour hyperopt
def objective_hyperopt(args):
    x, y, z = args
    return x ** 2 + y ** 2 + z ** 2

#Optimisé avec hyperopt
def hyperopt_exe():
    #Paramètres de l'espace de recherche
    space = [
        hp.uniform('x', -100, 100),
        hp.uniform('y', -100, 100),
        hp.uniform('z', -100, 100)
    ]
    #Un objet pour enregistrer l'état de la recherche
    trials = Trials()
    #Commencer l'exploration
    best = fmin(objective_hyperopt, space, algo=tpe.suggest, max_evals=500, trials=trials)
    #Sortir le résultat
    print(best)
    epoches = [] #Pour stocker le nombre d'essais
    values = [] #Pour stocker la meilleure valeur
    best = 100000
    #meilleure mise à jour
    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]

    #Dessiner un graphique
    fig, ax = plt.subplots()
    ax.set_xlabel("trial")
    ax.set_ylabel("value")
    ax.set_title("Optuna vs Hyperopt")
    ax.grid() #Insérer des lignes de quadrillage
    ax.plot(epoch_optuna, value_optuna, color="red", label="Optuna")
    ax.plot(epoch_hyperopt, value_hyperopt, color="blue", label="Hyperopt")
    ax.legend(loc=0) #Guide d'utilisation
    plt.show() #affichage graphique

if __name__ == '__main__':
    plot_graph()

Premier résultat expérimental

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

Optuna est excellent dans la meilleure valeur finale. Il semble qu'Optuna soit supérieur au graphique en termes de vitesse de convergence.

Deuxième résultat expérimental

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

Optuna est-il supérieur en termes de best_value finale et de vitesse de convergence dans la deuxième et la première fois?

Résultat expérimental 3e

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

Optuna était également supérieur dans la valeur finale best_value pour la troisième fois. Je pense que la vitesse de convergence ne change pas beaucoup.

Conclusion

Nous sommes arrivés à la conclusion qu'Optuna est supérieure en termes de meilleure valeur finale de la fonction objectif et de vitesse de convergence. Si le problème d'optimisation est rendu un peu plus difficile, cela fera-t-il une grande différence ...

Recommended Posts