Résolvez les problèmes d'optimisation en Python. Si vous recherchez un bon échantillon, [Méthode Nelder Mead](https://ja.wikipedia.org/wiki/%E3%83%8D%E3%83%AB%E3%83%80%E3 % 83% BC% E2% 80% 93% E3% 83% 9F% E3% 83% BC% E3% 83% 89% E6% B3% 95) est implémenté [MATLAB function fminsearch](https: / /jp.mathworks.com/help/matlab/ref/fminsearch.html) semble bon.
MATLAB a une option payante appelée boîte à outils d'optimisation qui a des fonctions d'optimisation, mais vous pouvez utiliser cette fminsearch même si seul MATLAB lui-même est installé.
a = sqrt(2);
banana = @(x)100*(x(2)-x(1)^2)^2+(a-x(1))^2;
[x,fval] = fminsearch(banana, [-1.2, 1], optimset('TolX',1e-8));
C'est exactement l'exemple décrit sur la page fminsearch, mais le X qui minimise cette formule est Nelder-Mead. Requis par la loi.
Portez l'exemple de fonction banane ci-dessus vers Python. Pour résoudre ce problème d'optimisation en Python, nous nous appuyons sur Scipy. Scipy.optimize Dans Scipy.optimize, divers algorithmes d'optimisation sont implémentés, quand vous regardez le document Je comprends.
Un simple port ressemblerait à ceci:
from scipy.optimize import fmin
import math
banana = lambda X, a: 100*(X[1] - X[0]**2)**2 + (a - X[0])**2
a = math.sqrt(2)
arg = (a, )
fmin(banana, [-1, 1.2], args=arg)
Avec la valeur initiale de (x 1 </ sub>, x 2 </ sub>) = (-1, 1.2), l'optimisation a été effectuée pour minimiser la valeur de la formule ci-dessus. Cependant, il montre que le résultat (x 1 </ sub>, x 2 </ sub>) = (1.41420186, 1.99996718) a été obtenu.
La première chose importante ici est la définition de la fonction par lambda ''. Cela dit, c'est quelque chose qui revient chaque fois que vous faites un didacticiel Python, et ce n'est peut-être pas le point de s'inquiéter. Ici, il est important de "passer une liste appelée X et une variable appelée a comme arguments", et les variables ajustées par
`` fmin``` sont les deux variables passées dans la liste appelée X, et a est Cela signifie qu'il est passé comme une constante. Bien entendu, il peut être normalement défini comme suit.
def banana(X, a):
return 100*(X[1] - X[0]**2)**2 + (a - X[0])**2
Maintenant, l'argument de
fmin est la fonction objectif à minimiser, la variable à optimiser pour minimiser la valeur de la fonction, et l'optimisation par `` fmin
. C'est un tuple d'arguments à entrer dans la fonction, bien qu'il ne soit pas la cible.
Cette fois, des arguments à saisir dans la fonction objectif banane```, ```a``` à saisir comme constante est passé sous forme de taple à l'argument ```args``` de
fmin``` Par conséquent, «« »arg = (a,)« »est utilisé. Lors de la définition d'un taple avec 1 élément, il doit se terminer par "
,
`".
Diverses options peuvent être définies pour l'optimisation. Le gars de l'optimisation "ajuste les paramètres jusqu'à ce que la valeur de la fonction converge", mais il y a différentes conditions pour juger "convergé". Les conditions peuvent être définies. Pour plus de détails, voir Documentation.
Supposons maintenant que le nombre maximum d'évaluations de fonction soit de 400, le nombre maximum d'itérations de 400, la tolérance de valeur finale de la fonction de 1e-4 et la tolérance de X de 1e-4 (MATLAB fminsearch default value) Pour spécifier explicitement la semelle, appelez `` fmin '' comme indiqué ci-dessous.
fmin(banana, [-1, 1.2], args=arg, xtol=1e-4, ftol=1e-4, maxiter=400, maxfun=400)
À propos, si l'optimisation concerne la fonction banane, elle se terminera en un instant, mais il y a des moments où vous souhaitez visualiser le processus de ce calcul d'optimisation. Dans ce cas, spécifiez la fonction de rappel pour récupérer la valeur de chaque itération.
count = 0
def cbf(Xi):
global count
count += 1
print('%d, %f, %f, %f' % (count, Xi[0], Xi[1], banana(Xi, math.sqrt(2))))
Je ne sais pas si c'est la bonne façon de le faire, mais j'ai essayé de compter et d'afficher le nombre d'itérations comme une variable globale.
Au lieu de sortir le résultat du calcul sous forme de texte pour chaque itération, il peut être exprimé sous forme de graphique.
from scipy.optimize import fmin
import math
import matplotlib.pyplot as plt
count = 0
plt.axis([0, 100, 0, 6.5])
plt.ion()
def cbf(Xi):
global count
count += 1
f = banana(Xi, math.sqrt(2))
print('%d, %f, %f, %f' % (count, Xi[0], Xi[1], f))
plt.scatter(count, f)
banana = lambda X, a: 100*(X[1] - X[0]**2)**2 + (a - X[0])**2
a = math.sqrt(2)
arg = (a, )
fmin(banana, [-1, 1.2], args=arg, callback=cbf)
Vous pouvez maintenant voir les points tracés en temps réel sur le graphique avec
matplotlib```.
À la suite d'un calcul par fmin, comme décrit ci-dessus(x<sub>1</sub>, x<sub>2</sub>) = (1.41420186, 1.99996718)Les gens demandent souvent d'expliquer un peu plus en détail le processus par lequel le résultat a été obtenu. Non, mon patron aussi(Ce qui suit est omis)…。
Il y a des arguments `` `` retall``` et `` `` full_output``` comme options pour `` `` fmin``` à cette fin, et si vous définissez `` `` True``` sur ceci, vous pouvez définir `` `` fmin``. Vous pouvez obtenir différentes valeurs de retour de ``.
```python
[xopt, fopt, iter, funcalls, warnflag, allvecs] = fmin(banana, [-1, 1.2], args=arg, retall=True, full_output=True)
xopt
Est un paramètre optimisé,fopt
Est la valeur de retour de la fonction minimisée à ce moment.iter
Quandfuncallls
Combien de fois l'itération a été effectuée,warnflag
は「収束した」Quand判断した条件Est stocké.allvecs
には、各iterationで最適化の対象Quandなっている変数La valeur du(上述のbanana関数の例でいうQuandx1Quandx2La valeur du)Est stocké.
Donc, si vous avez besoin d'un historique des ajustements de variables pour chaque itération, vous pouvez le visualiser en le représentant graphiquement après optimisation avec `` fmin '' sans le traiter dans la fonction de rappel. ..
J'ai donc essayé de faire la même chose en Python, en citant l'exemple de la fonction fminsearch de MATLAB.
from scipy.optimize import fmin
import math
import matplotlib.pyplot as plt
def cbf(Xi):
global count
count += 1
f = banana(Xi, math.sqrt(2))
plt.scatter(count, f)
plt.pause(0.05)
def banana(X, a):
return 100*(X[1] - X[0]**2)**2 + (a - X[0])**2
def main():
a = math.sqrt(2)
arg = (a, )
[xopt, fopt, iter, funcalls, warnflag, allvecs] = fmin(
banana,
[-1, 1.2],
args=arg,
callback=cbf,
xtol=1e-4,
ftol=1e-4,
maxiter=400,
maxfun=400,
disp=True,
retall=True,
full_output=True)
for item in allvecs:
print('%f, %f' % (item[0], item[1]))
if __name__ == '__main__':
count = 1
plt.axis([0, 100, 0, 6.5])
main()
Recommended Posts