Scipy-Optimierung für untergebundenes System
-
27-10-2019 - |
Frage
Ich muss oft nichtlineare Probleme lösen, bei denen die Anzahl der Variablen die Anzahl der Einschränkungen (oder manchmal umgekehrt) überschreitet. Normalerweise sind einige der Einschränkungen oder Variablen kompliziert überflüssig. Gibt es eine Möglichkeit, solche Probleme zu lösen?
Die meisten scipy -Solvers scheinen davon auszugehen, dass die Anzahl der Einschränkungen der Anzahl der Variablen entspricht und dass der Jakobier nicht singulär ist. leastsq
Funktioniert manchmal, aber es versucht nicht einmal, wenn die Einschränkungen weniger als die Anzahl der Variablen sind. Mir ist klar, dass ich einfach rennen könnte fmin
an linalg.norm(F)
, Aber dies ist viel weniger effizient als jede Methode, die den Jakobier nutzt.
Hier ist ein Beispiel für ein Problem, das zeigt, wovon ich spreche. Es hat offensichtlich eine Lösung, aber leastsq
gibt einen Fehler. Natürlich ist dieses Beispiel von Hand leicht zu lösen. Ich habe es einfach hierher gesetzt, um das Problem zu demonstrieren.
import numpy as np
import scipy.optimize
mat = np.random.randn(5, 7)
def F(x):
y = np.dot(mat, x)
return np.array([ y[0]**2 + y[1]**3 + 12, y[2] + 17 ])
x0 = np.random.randn(7)
scipy.optimize.leastsq(F, x0)
Die Fehlermeldung, die ich erhalte, lautet:
Traceback (most recent call last):
File "question.py", line 13, in <module>
scipy.optimize.leastsq(F, x0)
File "/home/dstahlke/apps/scipy/lib64/python2.7/site-packages/scipy/optimize/minpack.py", line 278, in leastsq
raise TypeError('Improper input: N=%s must not exceed M=%s' % (n,m))
TypeError: Improper input: N=7 must not exceed M=2
Ich habe das Netz nach einer Antwort gesucht und sogar auf der Scipy -Mailingliste gefragt und keine Antwort erhalten. Im Moment habe ich die Scipy -Quelle so gehackt, dass die newton_krylov
Löser verwendet pinv()
, aber ich denke nicht, dass dies eine optimale Lösung ist.
Lösung
Wie wäre es mit der Größe der Größe des Rückkehrarrays von f () zur Anzahl der Variablen:
import numpy as np
import scipy.optimize
mat = np.random.randn(5, 7)
def F(x):
y = np.dot(mat, x)
return np.resize(np.array([ y[0]**2 + y[1]**3 + 12, y[2] + 17]), 7)
while True:
x0 = np.random.randn(7)
r = scipy.optimize.leastsq(F, x0)
err = F(r[0])
norm = np.dot(err, err)
if norm < 1e-6:
break
print err