Recherche de site Web

Visualisation pour l'optimisation des fonctions en Python


L'optimisation des fonctions consiste à trouver l'entrée qui aboutit à la valeur optimale d'une fonction objectif.

Les algorithmes d'optimisation parcourent l'espace de recherche des variables d'entrée afin de localiser les optima, et la forme de la fonction objectif et le comportement de l'algorithme dans l'espace de recherche sont opaques sur les problèmes du monde réel.

En tant que tel, il est courant d’étudier des algorithmes d’optimisation utilisant des fonctions simples de faible dimension qui peuvent être facilement visualisées directement. De plus, les échantillons dans l'espace d'entrée de ces fonctions simples réalisés par un algorithme d'optimisation peuvent être visualisés avec leur contexte approprié.

La visualisation des fonctions de dimension inférieure et du comportement des algorithmes sur ces fonctions peut aider à développer des intuitions qui peuvent ensuite être répercutées sur des problèmes plus complexes d'optimisation de fonctions de dimension supérieure.

Dans ce didacticiel, vous découvrirez comment créer des visualisations pour l'optimisation des fonctions en Python.

Après avoir terminé ce tutoriel, vous saurez :

  • La visualisation est un outil important lors de l’étude des algorithmes d’optimisation des fonctions.
  • Comment visualiser des fonctions et des échantillons unidimensionnels à l'aide de tracés linéaires.
  • Comment visualiser des fonctions et des échantillons bidimensionnels à l'aide de tracés de contours et de surfaces.

Démarrez votre projet avec mon nouveau livre Optimization for Machine Learning, comprenant des tutoriels pas à pas et les fichiers code source Python pour tous exemples.

Présentation du didacticiel

Ce didacticiel est divisé en trois parties : ils sont:

  1. Visualisation pour l'optimisation des fonctions
  2. Visualisez l'optimisation des fonctions 1D

    1. Fonction de test
    2. Exemple de fonction de test
    3. Tracé linéaire de la fonction de test
    4. Nuage de points de la fonction de test
    5. Tracé linéaire avec Optima marqué
    6. Tracé linéaire avec échantillons
  3. Visualisez l'optimisation des fonctions 2D

    1. Fonction de test
    2. Exemple de fonction de test
    3. Tracé de contour de la fonction de test
    4. Tracé de contour rempli de la fonction de test
    5. Tracé de contour rempli de la fonction de test avec des échantillons
    6. Tracé de surface de la fonction de test

Visualisation pour l'optimisation des fonctions

L'optimisation des fonctions est un domaine mathématique qui consiste à trouver les entrées d'une fonction qui aboutissent à la sortie optimale pour la fonction, généralement une valeur minimale ou maximale.

L'optimisation peut être simple pour des fonctions différentielles simples où la solution peut être calculée analytiquement. Cependant, la plupart des fonctions que nous souhaitons résoudre dans le cadre de l’apprentissage automatique appliqué peuvent ou non se comporter correctement et peuvent être complexes, non linéaires, multivariées et non différenciables.

En tant que tel, il est important de comprendre un large éventail d’algorithmes différents qui peuvent être utilisés pour résoudre les problèmes d’optimisation des fonctions.

Un aspect important de l’étude de l’optimisation des fonctions consiste à comprendre la fonction objectif qui est optimisée et à comprendre le comportement d’un algorithme d’optimisation au fil du temps.

La visualisation joue un rôle important lors de la mise en route de l'optimisation des fonctions.

Nous pouvons sélectionner des fonctions de test simples et bien comprises pour étudier les algorithmes d'optimisation. Ces fonctions simples peuvent être tracées pour comprendre la relation entre l'entrée de la fonction objectif et la sortie de la fonction objectif et mettre en évidence les collines, les vallées et les optima.

De plus, les échantillons sélectionnés dans l'espace de recherche par un algorithme d'optimisation peuvent également être tracés au-dessus des tracés de la fonction objectif. Ces graphiques du comportement des algorithmes peuvent fournir un aperçu et une intuition du fonctionnement d’algorithmes d’optimisation spécifiques et naviguer dans un espace de recherche qui peut se généraliser à de nouveaux problèmes à l’avenir.

En règle générale, les fonctions unidimensionnelles ou bidimensionnelles sont choisies pour étudier les algorithmes d'optimisation car elles sont faciles à visualiser à l'aide de tracés standard, comme les tracés linéaires et les tracés de surface. Nous explorerons les deux dans ce tutoriel.

Tout d’abord, explorons comment nous pourrions visualiser une optimisation de fonction unidimensionnelle.

Visualisez l'optimisation des fonctions 1D

Une fonction unidimensionnelle prend une seule variable d'entrée et génère l'évaluation de cette variable d'entrée.

Les variables d'entrée sont généralement continues, représentées par une valeur réelle à virgule flottante. Souvent, le domaine d’entrée n’est pas contraint, même si pour les problèmes de test, nous imposons un domaine d’intérêt.

Fonction de test

Dans ce cas, nous explorerons la visualisation de fonctions avec une simple fonction objectif x^2 :

  • f(x)=x^2

Cela a une valeur optimale avec une entrée de x=0,0, qui est égale à 0,0.

L'exemple ci-dessous implémente cette fonction objectif et évalue une seule entrée.

# example of a 1d objective function

# objective function
def objective(x):
	return x**2.0

# evaluate inputs to the objective function
x = 4.0
result = objective(x)
print('f(%.3f) = %.3f' % (x, result))

L’exécution de l’exemple évalue la valeur 4,0 avec la fonction objectif, qui est égale à 16,0.

f(4.000) = 16.000

Échantillon de la fonction de test

La première chose que nous pourrions vouloir faire avec une nouvelle fonction est de définir une plage d’entrée d’intérêt et d’échantillonner le domaine d’intérêt à l’aide d’une grille uniforme.

Cet exemple servira de base à la génération ultérieure d'un tracé.

Dans ce cas, nous définirons un domaine d'intérêt autour des optima de x=0,0 de x=-5,0 à x=5,0 et échantillonnerons une grille de valeurs dans cette plage avec des incréments de 0,1, tels que -5,0, -4,9, -4,8. , etc.

...
# define range for input
r_min, r_max = -5.0, 5.0
# sample input range uniformly at 0.1 increments
inputs = arange(r_min, r_max, 0.1)
# summarize some of the input domain
print(inputs[:5])

Nous pouvons ensuite évaluer chacune des valeurs x de notre échantillon.

...
# compute targets
results = objective(inputs)
# summarize some of the results
print(results[:5])

Enfin, nous pouvons vérifier certaines des entrées et leurs sorties correspondantes.

...
# create a mapping of some inputs to some results
for i in range(5):
	print('f(%.3f) = %.3f' % (inputs[i], results[i]))

En reliant cela ensemble, l'exemple complet d'échantillonnage de l'espace d'entrée et d'évaluation de tous les points de l'échantillon est répertorié ci-dessous.

# sample 1d objective function
from numpy import arange

# objective function
def objective(x):
	return x**2.0

# define range for input
r_min, r_max = -5.0, 5.0
# sample input range uniformly at 0.1 increments
inputs = arange(r_min, r_max, 0.1)
# summarize some of the input domain
print(inputs[:5])
# compute targets
results = objective(inputs)
# summarize some of the results
print(results[:5])
# create a mapping of some inputs to some results
for i in range(5):
	print('f(%.3f) = %.3f' % (inputs[i], results[i]))

L’exécution de l’exemple génère d’abord un échantillon uniforme de points d’entrée comme prévu.

Les points d'entrée sont ensuite évalués à l'aide de la fonction objectif et enfin, nous pouvons voir un simple mappage des entrées aux sorties de la fonction objectif.

[-5.  -4.9 -4.8 -4.7 -4.6]
[25.   24.01 23.04 22.09 21.16]
f(-5.000) = 25.000
f(-4.900) = 24.010
f(-4.800) = 23.040
f(-4.700) = 22.090
f(-4.600) = 21.160

Maintenant que nous savons comment générer un échantillon d’entrées et les évaluer avec la fonction objectif, nous pouvons envisager de générer des tracés de la fonction.

Tracé linéaire de la fonction de test

Nous pourrions échantillonner l'espace d'entrée de manière aléatoire, mais l'avantage d'une ligne ou d'une grille de points uniforme est qu'elle peut être utilisée pour générer un tracé fluide.

C'est fluide car les points dans l'espace d'entrée sont classés du plus petit au plus grand. Cet ordre est important car nous nous attendons (espérons) que la sortie de la fonction objectif ait une relation similaire et fluide entre les valeurs, par ex. de petits changements dans l’entrée entraînent des changements localement cohérents (lisses) dans la sortie de la fonction.

Dans ce cas, nous pouvons utiliser les échantillons pour générer un tracé linéaire de la fonction objectif avec les points d'entrée (x) sur l'axe des x du tracé et la sortie de la fonction objectif (résultats) sur l'axe des y du tracé.

...
# create a line plot of input vs result
pyplot.plot(inputs, results)
# show the plot
pyplot.show()

En reliant cela ensemble, l’exemple complet est répertorié ci-dessous.

# line plot of input vs result for a 1d objective function
from numpy import arange
from matplotlib import pyplot

# objective function
def objective(x):
	return x**2.0

# define range for input
r_min, r_max = -5.0, 5.0
# sample input range uniformly at 0.1 increments
inputs = arange(r_min, r_max, 0.1)
# compute targets
results = objective(inputs)
# create a line plot of input vs result
pyplot.plot(inputs, results)
# show the plot
pyplot.show()

L’exécution de l’exemple crée un tracé linéaire de la fonction objectif.

Nous pouvons voir que la fonction a une grande forme de U, appelée parabole. Il s'agit d'une forme courante lors de l'étude des courbes, par ex. l'étude du calcul.

Nuage de points de la fonction de test

La ligne est une construction. Ce n'est pas vraiment la fonction, juste un résumé fluide de la fonction. Gardez toujours cela à l’esprit.

Rappelons que nous avons en fait généré un échantillon de points dans l'espace d'entrée et une évaluation correspondante de ces points.

En tant que tel, il serait plus précis de créer un nuage de points de points ; Par exemple:

# scatter plot of input vs result for a 1d objective function
from numpy import arange
from matplotlib import pyplot

# objective function
def objective(x):
	return x**2.0

# define range for input
r_min, r_max = -5.0, 5.0
# sample input range uniformly at 0.1 increments
inputs = arange(r_min, r_max, 0.1)
# compute targets
results = objective(inputs)
# create a scatter plot of input vs result
pyplot.scatter(inputs, results)
# show the plot
pyplot.show()

L’exécution de l’exemple crée un nuage de points de la fonction objectif.

Nous pouvons voir la forme familière de la fonction, mais nous ne gagnons rien à tracer directement les points.

La ligne et l'interpolation douce entre les points qu'elle fournit sont plus utiles car nous pouvons dessiner d'autres points au-dessus de la ligne, comme l'emplacement des optima ou les points échantillonnés par un algorithme d'optimisation.

Tracé linéaire avec Optima marqué

Ensuite, traçons à nouveau le tracé linéaire et cette fois, dessinons un point où se trouve l'optima connu de la fonction.

Cela peut être utile lors de l'étude d'un algorithme d'optimisation, car nous pourrions vouloir voir à quel point un algorithme d'optimisation peut se rapprocher de l'optima.

Tout d’abord, nous devons définir l’entrée pour les optima, puis évaluer ce point pour donner les valeurs des axes x et y pour le traçage.

...
# define the known function optima
optima_x = 0.0
optima_y = objective(optima_x)

Nous pouvons ensuite tracer ce point avec n’importe quelle forme ou couleur que nous aimons, dans ce cas, un carré rouge.

...
# draw the function optima as a red square
pyplot.plot([optima_x], [optima_y], 's', color='r')

En reliant cela ensemble, l'exemple complet de création d'un tracé linéaire de la fonction avec les optima mis en évidence par un point est répertorié ci-dessous.

# line plot of input vs result for a 1d objective function and show optima
from numpy import arange
from matplotlib import pyplot

# objective function
def objective(x):
	return x**2.0

# define range for input
r_min, r_max = -5.0, 5.0
# sample input range uniformly at 0.1 increments
inputs = arange(r_min, r_max, 0.1)
# compute targets
results = objective(inputs)
# create a line plot of input vs result
pyplot.plot(inputs, results)
# define the known function optima
optima_x = 0.0
optima_y = objective(optima_x)
# draw the function optima as a red square
pyplot.plot([optima_x], [optima_y], 's', color='r')
# show the plot
pyplot.show()

L'exécution de l'exemple crée le tracé linéaire familier de la fonction, et cette fois, les optima de la fonction, par ex. l'entrée qui aboutit à la sortie minimale de la fonction est marquée d'un carré rouge.

C'est une fonction très simple et le carré rouge de l'optima est facile à voir.

Parfois, la fonction peut être plus complexe, avec de nombreuses collines et vallées, et nous pouvons vouloir rendre les optima plus visibles.

Dans ce cas, nous pouvons tracer une ligne verticale sur toute la parcelle.

...
# draw a vertical line at the optimal input
pyplot.axvline(x=optima_x, ls='--', color='red')

En reliant cela ensemble, l’exemple complet est répertorié ci-dessous.

# line plot of input vs result for a 1d objective function and show optima as line
from numpy import arange
from matplotlib import pyplot

# objective function
def objective(x):
	return x**2.0

# define range for input
r_min, r_max = -5.0, 5.0
# sample input range uniformly at 0.1 increments
inputs = arange(r_min, r_max, 0.1)
# compute targets
results = objective(inputs)
# create a line plot of input vs result
pyplot.plot(inputs, results)
# define the known function optima
optima_x = 0.0
# draw a vertical line at the optimal input
pyplot.axvline(x=optima_x, ls='--', color='red')
# show the plot
pyplot.show()

L'exécution de l'exemple crée le même tracé et trace cette fois une ligne rouge marquant clairement le point dans l'espace d'entrée qui marque l'optima.

Tracé linéaire avec échantillons

Enfin, nous pourrions vouloir tirer les échantillons de l’espace d’entrée sélectionnés par un algorithme d’optimisation.

Nous simulerons ces échantillons avec des points aléatoires tirés du domaine d'entrée.

...
# simulate a sample made by an optimization algorithm
seed(1)
sample = r_min + rand(10) * (r_max - r_min)
# evaluate the sample
sample_eval = objective(sample)

On peut ensuite tracer cet échantillon, dans ce cas à l'aide de petits cercles noirs.

...
# plot the sample as black circles
pyplot.plot(sample, sample_eval, 'o', color='black')

L'exemple complet de création d'un tracé linéaire d'une fonction avec les optima marqués par une ligne rouge et un échantillon d'algorithme dessiné avec de petits points noirs est répertorié ci-dessous.

# line plot of domain for a 1d function with optima and algorithm sample
from numpy import arange
from numpy.random import seed
from numpy.random import rand
from matplotlib import pyplot

# objective function
def objective(x):
	return x**2.0

# define range for input
r_min, r_max = -5.0, 5.0
# sample input range uniformly at 0.1 increments
inputs = arange(r_min, r_max, 0.1)
# compute targets
results = objective(inputs)
# simulate a sample made by an optimization algorithm
seed(1)
sample = r_min + rand(10) * (r_max - r_min)
# evaluate the sample
sample_eval = objective(sample)
# create a line plot of input vs result
pyplot.plot(inputs, results)
# define the known function optima
optima_x = 0.0
# draw a vertical line at the optimal input
pyplot.axvline(x=optima_x, ls='--', color='red')
# plot the sample as black circles
pyplot.plot(sample, sample_eval, 'o', color='black')
# show the plot
pyplot.show()

L'exécution de l'exemple crée le tracé linéaire du domaine et marque les optima avec une ligne rouge comme auparavant.

Cette fois, l'échantillon du domaine sélectionné par un algorithme (en réalité un échantillon aléatoire de points) est dessiné avec des points noirs.

Nous pouvons imaginer qu'un véritable algorithme d'optimisation affichera les points se resserrant sur le domaine lors de sa recherche en descente à partir d'un point de départ.

Voyons ensuite comment nous pourrions réaliser des visualisations similaires pour l’optimisation d’une fonction bidimensionnelle.

Visualisez l'optimisation des fonctions 2D

Une fonction bidimensionnelle est une fonction qui prend deux variables d'entrée, par ex. x et y.

Fonction de test

Nous pouvons utiliser la même fonction x^2 et la mettre à l'échelle pour devenir une fonction bidimensionnelle ; Par exemple:

  • f(x, y)=x^2 + y^2

Celui-ci a une valeur optimale avec une entrée de [x=0,0, y=0,0], qui est égale à 0,0.

L'exemple ci-dessous implémente cette fonction objectif et évalue une seule entrée.

# example of a 2d objective function

# objective function
def objective(x, y):
	return x**2.0 + y**2.0

# evaluate inputs to the objective function
x = 4.0
y = 4.0
result = objective(x, y)
print('f(%.3f, %.3f) = %.3f' % (x, y, result))

L'exécution de l'exemple évalue le point [x=4, y=4], qui est égal à 32.

f(4.000, 4.000) = 32.000

Ensuite, nous avons besoin d’un moyen d’échantillonner le domaine afin de pouvoir, à notre tour, échantillonner la fonction objectif.

Exemple de fonction de test

Une manière courante d'échantillonner une fonction bidimensionnelle consiste à générer d'abord un échantillon uniforme le long de chaque variable, x et y, puis à utiliser ces deux échantillons uniformes pour créer une grille de échantillons, appelés grilles maillées.

Il ne s'agit pas d'un tableau bidimensionnel dans l'espace d'entrée ; il s'agit plutôt de deux tableaux bidimensionnels qui, lorsqu'ils sont utilisés ensemble, définissent une grille couvrant les deux variables d'entrée.

Ceci est obtenu en dupliquant l'intégralité du tableau d'échantillons x pour chaque point d'échantillonnage y et en dupliquant de la même manière l'intégralité du tableau d'échantillons y pour chaque x point d'échantillonnage.

Ceci peut être réalisé en utilisant la fonction NumPy meshgrid() ; Par exemple:

...
# define range for input
r_min, r_max = -5.0, 5.0
# sample input range uniformly at 0.1 increments
xaxis = arange(r_min, r_max, 0.1)
yaxis = arange(r_min, r_max, 0.1)
# create a mesh from the axis
x, y = meshgrid(xaxis, yaxis)
# summarize some of the input domain
print(x[:5, :5])

Nous pouvons ensuite évaluer chaque paire de points à l’aide de notre fonction objectif.

...
# compute targets
results = objective(x, y)
# summarize some of the results
print(results[:5, :5])

Enfin, nous pouvons revoir le mappage de certaines des entrées avec leurs valeurs de sortie correspondantes.

...
# create a mapping of some inputs to some results
for i in range(5):
	print('f(%.3f, %.3f) = %.3f' % (x[i,0], y[i,0], results[i,0]))

L'exemple ci-dessous montre comment nous pouvons créer une grille d'échantillonnage uniforme dans l'espace d'entrée bidimensionnel et la fonction objectif.

# sample 2d objective function
from numpy import arange
from numpy import meshgrid

# objective function
def objective(x, y):
	return x**2.0 + y**2.0

# define range for input
r_min, r_max = -5.0, 5.0
# sample input range uniformly at 0.1 increments
xaxis = arange(r_min, r_max, 0.1)
yaxis = arange(r_min, r_max, 0.1)
# create a mesh from the axis
x, y = meshgrid(xaxis, yaxis)
# summarize some of the input domain
print(x[:5, :5])
# compute targets
results = objective(x, y)
# summarize some of the results
print(results[:5, :5])
# create a mapping of some inputs to some results
for i in range(5):
	print('f(%.3f, %.3f) = %.3f' % (x[i,0], y[i,0], results[i,0]))

L'exécution de l'exemple résume d'abord certains points de la grille de maillage, puis l'évaluation de la fonction objectif pour certains points.

Enfin, nous énumérons les coordonnées dans l’espace d’entrée bidimensionnel et leur évaluation de fonction correspondante.

[[-5.  -4.9 -4.8 -4.7 -4.6]
 [-5.  -4.9 -4.8 -4.7 -4.6]
 [-5.  -4.9 -4.8 -4.7 -4.6]
 [-5.  -4.9 -4.8 -4.7 -4.6]
 [-5.  -4.9 -4.8 -4.7 -4.6]]
[[50.   49.01 48.04 47.09 46.16]
 [49.01 48.02 47.05 46.1  45.17]
 [48.04 47.05 46.08 45.13 44.2 ]
 [47.09 46.1  45.13 44.18 43.25]
 [46.16 45.17 44.2  43.25 42.32]]
f(-5.000, -5.000) = 50.000
f(-5.000, -4.900) = 49.010
f(-5.000, -4.800) = 48.040
f(-5.000, -4.700) = 47.090
f(-5.000, -4.600) = 46.160

Maintenant que nous savons comment échantillonner l’espace d’entrée et évaluer les points, voyons comment tracer la fonction.

Tracé de contour de la fonction de test

Un tracé populaire pour les fonctions bidimensionnelles est un tracé de contour.

Ce tracé crée une représentation plate des sorties de la fonction objectif pour chaque coordonnée x et y où la couleur et les lignes de contour indiquent la valeur relative ou la hauteur de la sortie de la fonction objectif.

C'est comme une carte de contour d'un paysage où les montagnes peuvent être distinguées des vallées.

Ceci peut être réalisé en utilisant la fonction contour() Matplotlib qui prend directement la grille de maillage et l'évaluation de la grille de maillage en entrée.

On peut alors préciser le nombre de niveaux à dessiner sur le contour et la palette de couleurs à utiliser. Dans ce cas, nous utiliserons 50 niveaux et une palette de couleurs populaire « jet » où les niveaux bas utilisent une palette de couleurs froides (bleu) et les niveaux élevés utilisent une palette de couleurs chaudes (rouge).

...
# create a contour plot with 50 levels and jet color scheme
pyplot.contour(x, y, results, 50, alpha=1.0, cmap='jet')
# show the plot
pyplot.show()

En reliant cela ensemble, l'exemple complet de création d'un tracé de contour de la fonction objectif bidimensionnelle est répertorié ci-dessous.

# create a contour plot with 50 levels and jet color scheme
pyplot.contour(x, y, results, 50, alpha=1.0, cmap='jet')
# show the plot
pyplot.show()

Tying this together, the complete example of creating a contour plot of the two-dimensional objective function is listed below.

# contour plot for 2d objective function
from numpy import arange
from numpy import meshgrid
from matplotlib import pyplot

# objective function
def objective(x, y):
	return x**2.0 + y**2.0

# define range for input
r_min, r_max = -5.0, 5.0
# sample input range uniformly at 0.1 increments
xaxis = arange(r_min, r_max, 0.1)
yaxis = arange(r_min, r_max, 0.1)
# create a mesh from the axis
x, y = meshgrid(xaxis, yaxis)
# compute targets
results = objective(x, y)
# create a contour plot with 50 levels and jet color scheme
pyplot.contour(x, y, results, 50, alpha=1.0, cmap='jet')
# show the plot
pyplot.show()

L'exécution de l'exemple crée le tracé de contour.

Nous pouvons voir que les parties les plus incurvées de la surface autour des bords ont plus de contours pour montrer les détails, et que les parties les moins incurvées de la surface au milieu ont moins de contours.

Nous pouvons voir que la partie la plus basse du domaine est le milieu, comme prévu.

Tracé de contour rempli de la fonction de test

Il est également utile de colorer le tracé entre les contours pour afficher une surface plus complète.

Encore une fois, les couleurs ne sont qu'une simple interpolation linéaire, pas une véritable évaluation de fonction. Il faut garder cela à l'esprit pour les fonctions plus complexes où les détails les plus fins ne seront pas affichés.

Nous pouvons remplir le tracé de contour en utilisant la version contourf() de la fonction qui prend les mêmes arguments.

...
# create a filled contour plot with 50 levels and jet color scheme
pyplot.contourf(x, y, results, levels=50, cmap='jet')

Nous pouvons également afficher les optima sur le tracé, dans ce cas sous la forme d'une étoile blanche qui se détachera sur la couleur de fond bleu de la partie la plus basse du tracé.

...
# define the known function optima
optima_x = [0.0, 0.0]
# draw the function optima as a white star
pyplot.plot([optima_x[0]], [optima_x[1]], '*', color='white')

En reliant cela ensemble, l'exemple complet d'un tracé de contour rempli avec les optima marqués est répertorié ci-dessous.

# filled contour plot for 2d objective function and show the optima
from numpy import arange
from numpy import meshgrid
from matplotlib import pyplot

# objective function
def objective(x, y):
	return x**2.0 + y**2.0

# define range for input
r_min, r_max = -5.0, 5.0
# sample input range uniformly at 0.1 increments
xaxis = arange(r_min, r_max, 0.1)
yaxis = arange(r_min, r_max, 0.1)
# create a mesh from the axis
x, y = meshgrid(xaxis, yaxis)
# compute targets
results = objective(x, y)
# create a filled contour plot with 50 levels and jet color scheme
pyplot.contourf(x, y, results, levels=50, cmap='jet')
# define the known function optima
optima_x = [0.0, 0.0]
# draw the function optima as a white star
pyplot.plot([optima_x[0]], [optima_x[1]], '*', color='white')
# show the plot
pyplot.show()

L'exécution de l'exemple crée le tracé de contour rempli qui donne une meilleure idée de la forme de la fonction objectif.

Les optima à [x=0, y=0] sont alors clairement marqués d'une étoile blanche.

Tracé de contour rempli de la fonction de test avec des échantillons

Nous pouvons vouloir montrer la progression d'un algorithme d'optimisation pour avoir une idée de son comportement dans le contexte de la forme de la fonction objectif.

Dans ce cas, on peut simuler les points choisis par un algorithme d'optimisation avec des coordonnées aléatoires dans l'espace d'entrée.

...
# simulate a sample made by an optimization algorithm
seed(1)
sample_x = r_min + rand(10) * (r_max - r_min)
sample_y = r_min + rand(10) * (r_max - r_min)

Ces points peuvent ensuite être tracés directement sous forme de cercles noirs et leur couleur contextuelle peut donner une idée de leur qualité relative.

...
# plot the sample as black circles
pyplot.plot(sample_x, sample_y, 'o', color='black')

En reliant cela ensemble, l'exemple complet d'un tracé de contour rempli avec un échantillon optimal et d'entrée tracé est répertorié ci-dessous.

# filled contour plot for 2d objective function and show the optima and sample
from numpy import arange
from numpy import meshgrid
from numpy.random import seed
from numpy.random import rand
from matplotlib import pyplot

# objective function
def objective(x, y):
	return x**2.0 + y**2.0

# define range for input
r_min, r_max = -5.0, 5.0
# sample input range uniformly at 0.1 increments
xaxis = arange(r_min, r_max, 0.1)
yaxis = arange(r_min, r_max, 0.1)
# create a mesh from the axis
x, y = meshgrid(xaxis, yaxis)
# compute targets
results = objective(x, y)
# simulate a sample made by an optimization algorithm
seed(1)
sample_x = r_min + rand(10) * (r_max - r_min)
sample_y = r_min + rand(10) * (r_max - r_min)
# create a filled contour plot with 50 levels and jet color scheme
pyplot.contourf(x, y, results, levels=50, cmap='jet')
# define the known function optima
optima_x = [0.0, 0.0]
# draw the function optima as a white star
pyplot.plot([optima_x[0]], [optima_x[1]], '*', color='white')
# plot the sample as black circles
pyplot.plot(sample_x, sample_y, 'o', color='black')
# show the plot
pyplot.show()

En exécutant l'exemple, nous pouvons voir le tracé de contour rempli comme avant avec les optima marqués.

Nous pouvons maintenant voir l'échantillon dessiné sous forme de points noirs et leur couleur environnante et leur distance relative par rapport aux optima donnent une idée de la mesure dans laquelle l'algorithme (des points aléatoires dans ce cas) s'est rapproché de la résolution du problème.

Tracé de surface de la fonction de test

Enfin, nous souhaiterons peut-être créer un tracé tridimensionnel de la fonction objectif pour avoir une idée plus complète de la courbure de la fonction.

Ceci peut être réalisé en utilisant la fonction plot_surface() Matplotlib, qui, comme le tracé de contour, prend directement la grille de maillage et l'évaluation de la fonction.

...
# create a surface plot with the jet color scheme
figure = pyplot.figure()
axis = figure.gca(projection='3d')
axis.plot_surface(x, y, results, cmap='jet')

L'exemple complet de création d'un tracé de surface est répertorié ci-dessous.

# surface plot for 2d objective function
from numpy import arange
from numpy import meshgrid
from matplotlib import pyplot
from mpl_toolkits.mplot3d import Axes3D

# objective function
def objective(x, y):
	return x**2.0 + y**2.0

# define range for input
r_min, r_max = -5.0, 5.0
# sample input range uniformly at 0.1 increments
xaxis = arange(r_min, r_max, 0.1)
yaxis = arange(r_min, r_max, 0.1)
# create a mesh from the axis
x, y = meshgrid(xaxis, yaxis)
# compute targets
results = objective(x, y)
# create a surface plot with the jet color scheme
figure = pyplot.figure()
axis = figure.gca(projection='3d')
axis.plot_surface(x, y, results, cmap='jet')
# show the plot
pyplot.show()

L’exécution de l’exemple crée un tracé de surface tridimensionnel de la fonction objectif.

De plus, le tracé est interactif, ce qui signifie que vous pouvez utiliser la souris pour faire glisser la perspective sur la surface et la visualiser sous différents angles.

Lectures complémentaires

Cette section fournit plus de ressources sur le sujet si vous souhaitez approfondir.

Apis

  • Optimisation et recherche de racine (scipy.optimize)
  • Optimisation (scipy.optimize)
  • API numpy.meshgrid.
  • API matplotlib.pyplot.contour.
  • API matplotlib.pyplot.contourf.
  • API mpl_toolkits.mplot3d.Axes3D.plot_surface.

Articles

  • Optimisation mathématique, Wikipédia.
  • Parabole, Wikipédia.

Résumé

Dans ce didacticiel, vous avez découvert comment créer des visualisations pour l'optimisation des fonctions en Python.

Concrètement, vous avez appris :

  • La visualisation est un outil important lors de l’étude des algorithmes d’optimisation des fonctions.
  • Comment visualiser des fonctions et des échantillons unidimensionnels à l'aide de tracés linéaires.
  • Comment visualiser des fonctions et des échantillons bidimensionnels à l'aide de tracés de contours et de surfaces.

Avez-vous des questions ?
Posez vos questions dans les commentaires ci-dessous et je ferai de mon mieux pour y répondre.

Articles connexes