Lösen Sie Optimierungsprobleme in Python. Wenn Sie nach einem guten Beispiel suchen, wählen Sie Nelder Mead-Methode % 83% BC% E2% 80% 93% E3% 83% 9F% E3% 83% BC% E3% 83% 89% E6% B3% 95) [MATLAB-Funktion fminsearch](https: / /jp.mathworks.com/help/matlab/ref/fminsearch.html) sieht gut aus.
MATLAB verfügt über eine kostenpflichtige Option namens Optimierungs-Toolbox, die Funktionen zur Optimierung bietet. Sie können diese fminsearch jedoch auch dann verwenden, wenn nur MATLAB selbst installiert ist.
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));
Dies ist genau das Beispiel, das auf der Seite fminsearch beschrieben ist, aber das X, das diese Formel minimiert, ist Nelder-Mead. Gesetzlich vorgeschrieben.
Portieren Sie das obige Beispiel für eine Bananenfunktion nach Python. Um dieses Optimierungsproblem in Python zu lösen, verlassen wir uns auf Scipy. Scipy.optimize In Scipy.optimize werden verschiedene Optimierungsalgorithmen implementiert, wenn Sie sich das Dokument ansehen Ich verstehe.
Ein einfacher Port würde so aussehen:
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)
Mit dem Anfangswert von (x1 </ sub>, x2 </ sub>) = (-1, 1,2) wurde eine Optimierung durchgeführt, um den Wert der obigen Formel zu minimieren. Es zeigt jedoch, dass das Ergebnis (x1, x2) = (1.41420186, 1.99996718) erhalten wurde.
Das erste wichtige hier ist die Definition der Funktion durch "Lambda". Das heißt, es ist etwas, das jedes Mal auftaucht, wenn Sie ein Python-Tutorial machen, und es ist möglicherweise nicht der Grund, sich Sorgen zu machen. Hier ist es wichtig, "eine Liste mit dem Namen X und eine Variable mit dem Namen a als Argumente zu übergeben", und die durch `` `fmin``` angepassten Variablen sind die beiden Variablen, die in der Liste mit dem Namen X übergeben werden, und a ist Dies bedeutet, dass es als Konstante übergeben wird. Natürlich kann es normalerweise wie folgt definiert werden.
def banana(X, a):
return 100*(X[1] - X[0]**2)**2 + (a - X[0])**2
Das Argument von "fmin" ist nun die zu minimierende Zielfunktion, die zu optimierende Variable, um den Funktionswert zu minimieren, und die Optimierung durch "fmin". Es ist ein Tupel von Argumenten, die in die Funktion eingegeben werden sollen, obwohl es nicht das Ziel von ist.
Dieses Mal wird von den in die Zielfunktion "Banane" eingegebenen Argumenten das als Konstante eingegebene "a" als Taple an das Argument "args" des "fmin" übergeben. Daher wird `arg = (a,)`
gesetzt. Wenn Sie einen Taple mit 1 Element definieren, muss er mit "
,
" enden.
Für die Optimierung können verschiedene Optionen eingestellt werden. Der Optimierungs-Typ "optimiert die Parameter, bis der Wert der Funktion konvergiert", aber es gibt verschiedene Bedingungen für die Beurteilung von "konvergiert". Die Bedingungen können eingestellt werden. Weitere Informationen finden Sie unter Dokumentation.
Angenommen, die maximale Anzahl von Funktionsauswertungen beträgt 400, die maximale Anzahl von Iterationen beträgt 400, die Toleranz für den Funktionsendwert beträgt 1e-4 und die X-Toleranz beträgt 1e-4 (Standardwert für MATLAB fminsearch) und um die Sohle explizit anzugeben, rufen Sie `` `fmin``` wie folgt auf.
fmin(banana, [-1, 1.2], args=arg, xtol=1e-4, ftol=1e-4, maxiter=400, maxfun=400)
Wenn es bei der Optimierung um die Bananenfunktion geht, endet sie übrigens sofort, aber manchmal möchten Sie den Prozess dieser Optimierungsberechnung visualisieren. Geben Sie in diesem Fall die Rückruffunktion an, um den Wert für jede Iteration abzurufen.
count = 0
def cbf(Xi):
global count
count += 1
print('%d, %f, %f, %f' % (count, Xi[0], Xi[1], banana(Xi, math.sqrt(2))))
Ich bin mir nicht sicher, ob dies der richtige Weg ist, aber ich habe versucht, die Anzahl der Iterationen als globale Variable zu zählen und anzuzeigen.
Anstatt das Berechnungsergebnis als Text für jede Iteration auszugeben, kann es in einem Diagramm ausgedrückt werden.
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)
Jetzt können Sie die Punkte in Echtzeit in der Grafik mit `` `matplotlib``` zeichnen.
Als Ergebnis der Berechnung mit fmin, wie oben beschrieben(x<sub>1</sub>, x<sub>2</sub>) = (1.41420186, 1.99996718)Die Leute bitten oft darum, den Prozess, mit dem das Ergebnis erzielt wurde, etwas detaillierter zu erklären. Nein, mein Chef auch(Folgendes wird weggelassen)…。
Zu diesem Zweck gibt es die Argumente `` `retall``` und` `` full_output``` als Optionen für `` `fmin```, und wenn Sie` `` True``` auf diesen Wert setzen, `` `fmin Sie können verschiedene Rückgabewerte von `` `erhalten.
```python
[xopt, fopt, iter, funcalls, warnflag, allvecs] = fmin(banana, [-1, 1.2], args=arg, retall=True, full_output=True)
xopt
Ist ein optimierter Parameter,fopt
Ist der Rückgabewert der minimierten Funktion zu diesem Zeitpunkt.iter
Wannfuncallls
Wie oft wurde die Iteration durchgeführt?warnflag
は「収束した」Wann判断した条件Wird gelagert.allvecs
には、各iterationで最適化の対象Wannなっている変数Der Wert der(上述のbanana関数の例でいうWannx1Wannx2Der Wert der)Wird gelagert.
Wenn Sie also für jede Iteration eine Historie von Variablenanpassungen benötigen, können Sie diese visualisieren, indem Sie sie nach der Optimierung mit `` `fmin``` grafisch darstellen, ohne sie in der Rückruffunktion zu verarbeiten. ..
Also habe ich versucht, dasselbe in Python zu tun, indem ich das Beispiel der fminsearch-Funktion von MATLAB angeführt habe.
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