2020.09.22 J'ai écrit un article qui suit cet article. Abandonner l'optimisation avec Early Stopper de scikit-Optimize
Étant donné que j'optimise parfois les paramètres au travail et que je reçois souvent des consultations sur des problèmes d'optimisation au travail, je vais résumer gp_minimize
de scikit-Optimize
, qui peut effectuer une optimisation bayésienne très facilement. Je le pense.
Installation facile avec pip
pip install scikit-optimize
Le texte intégral de ce code source. Ici, seuls les points clés, il y a en fait des codes de dessin.
import numpy as np
from skopt import gp_minimize
def func(param=None):
ret = np.cos(param[0] + 2.34) + np.cos(param[1] - 0.78)
return -ret
if __name__ == '__main__':
x1 = (-np.pi, np.pi)
x2 = (-np.pi, np.pi)
x = (x1, x2)
result = gp_minimize(func, x,
n_calls=30,
noise=0.0,
model_queue_size=1,
verbose=True)
import numpy as np
from skopt import gp_minimize
Seulement numpy et gp_minimize. S'il est détourné, changez-le si nécessaire.
def func(param=None):
ret = np.cos(param[0] + 0.34) + np.cos(param[1] - 0.78)
return -ret
Cette fois, le problème était de recevoir deux entrées et de trouver la valeur d'entrée qui maximise la somme de chaque valeur de fonction cosinus. Parce que c'est facile à comprendre. Cependant, comme c'était trop maladroit, j'ai ajouté un décalage (0,34, -0,78) à la valeur d'entrée. Si ce décalage est finalement décalé (-0,34, 0,78), on peut dire que l'optimisation est réussie.
Comme le nom gp_minimize
le suggère, il ne peut être minimisé **, donc la valeur de retour est définie sur une valeur négative en ajoutant-pour maximiser la minimisation.
x1 = (-np.pi, np.pi)
x2 = (-np.pi, np.pi)
x = (x1, x2)
Puisque nous savons que c'est une fonction cosinus cette fois, l'espace des deux variables d'entrée est le même, et la plage que (-π à π) peut prendre. Puisqu'il est nécessaire de spécifier le minimum et le maximum qui peuvent être pris pour chaque variable avec List ou Tuple, et enfin les passer ensemble à une List ou Tuple, ils sont combinés en un à la fin.
result = gp_minimize(func, x,
n_calls=30,
noise=0.0,
model_queue_size=1,
verbose=True)
Avec cela seul, l'échantillonnage commence. Pour l'instant, seuls les paramètres susceptibles d'être utilisés sont spécifiés cette fois.
Les premiers func
et x
spécifient la fonction d'optimisation et l'espace de recherche.
n_calls
est le nombre d'échantillons.
Si «noise» n'est pas spécifié, le bruit de la distribution gaussienne sera recherché, changez-le si nécessaire. Cette fois, il est évalué à 0,0 sans bruit.
model_queue_size
is gp_minimize
utilise GaussianProcessRegressor
of scikit-learn
pour prédire la valeur d'évaluation de l'espace et rechercher le prochain point d'échantillonnage, donc le nombre pour contenir une instance de GaussianProcessRegressor
à chaque fois. ..
Si vous ne le spécifiez pas, tout sera laissé, donc cela consommera de plus en plus de mémoire. Cette fois, j'ai spécifié 1 pour ne garder que la dernière version.
verbose
n'a qu'une sortie standard pendant l'échantillonnage. Si False est spécifié, rien ne sera généré.
Le résultat de cette optimisation est renvoyé dans "result".
Si vous faites référence au contenu avec la fonction dir, les membres suivants existent.
In [1]:dir(result)
Out[1]:
['fun',
'func_vals',
'models',
'random_state',
'space',
'specs',
'x',
'x_iters']
En général, l'interprétation suivante semble suffisante.
membre | valeur | Interprétation |
---|---|---|
fun | -1.9999999997437237 | Meilleure valeur d'évaluation lors de l'optimisation |
func_vals | array([ 0.72436992, -0.2934671 ,・ ・ ・ ・ ・ ・ ・-1.99988708, -1.99654543]) | Valeur de retour (valeur d'évaluation) de la fonction à chaque fois pendant l'optimisation |
models | list(GaussianProcessRegressor) | Conservé comme expliqué ci-dessusGaussianProcessRegressor Liste des instances de |
random_state | RandomState(MT19937) at 0x22023222268 | Graine aléatoire |
space | Space([ Real(low=-3.141592653589793, high=3.141592653589793, prior='uniform', transform='normalize'), Real(low=-3.141592653589793, high=3.141592653589793, prior='uniform', transform='normalize')]) |
Objets spatiaux d'exploration |
specs | (Omis car il y en a beaucoup) Contient un dictionnaire |
Il semble que les spécifications d'optimisation soient incluses ensemble |
x | [-2.3399919472084387, 0.7798573940377893] | Valeur de la variable d'entrée optimisée |
x_iters | (Omis car il y en a beaucoup) List |
Contient la valeur échantillonnée à chaque fois |
Enfin, collez celui tracé en utilisant la valeur contenue dans result
.
C'est un peu difficile à voir, mais la figure de gauche est la carte de chaleur réelle, l'axe vertical est x1
et l'axe horizontal est x2
, donc l'axe vertical est en bas et l'axe horizontal est légèrement à droite (valeur minimale ( Puisque le positif et le négatif sont inversés, il y a en fait la valeur maximale).
La figure de droite est le résultat de l'optimisation, mais la couleur de la carte thermique elle-même est également faite avec la valeur prédite de GaussianProcessRegressor
.
En échantillonnant 30 fois, il était possible de créer quelque chose qui était presque identique à l'espace réel, et la valeur optimale pouvait également être obtenue.
Le marqueur ○ est un point d'échantillonnage pour chaque temps, ce qui est difficile à comprendre, mais il semble que les bords sont échantillonnés et que la zone proche de la valeur minimale est focalisée après que l'espace puisse être prédit dans une certaine mesure.
La valeur optimale pour laquelle le marqueur ☆ a finalement été trouvé.
Bien qu'il existe peu d'articles sur l'utilisation de scikit-Optimize, j'ai écrit ceci cette fois parce que je n'ai trouvé aucun article japonais expliquant comment utiliser Callback. Donc, je vais écrire un article séparé sur la façon d'utiliser Callback et mettre un lien ici.
2020.09.22 Je l'ai écrit. Abandonner l'optimisation avec Early Stopper de scikit-Optimize
Recommended Posts