Ich habe ein paar Probleme mit der Anpassung einer Kurve an einige Daten, aber kann nicht herausfinden, wo ich falsch liege.Exponentielle Abklingkurve, die in numpy und scipy passt
In der Vergangenheit habe ich diese für Exponentialfunktionen mit numpy.linalg.lstsq getan und scipy.optimize.curve_fit für Sigmoidfunktionen. Dieses Mal wollte ich ein Skript erstellen, mit dem ich verschiedene Funktionen spezifizieren, Parameter bestimmen und ihre Anpassung an die Daten testen kann. Dabei habe ich festgestellt, dass Scipy leastsq
und Numpy lstsq
unterschiedliche Antworten für den gleichen Datensatz und die gleiche Funktion zu liefern scheinen. Die Funktion ist einfach y = e^(l*x)
und ist so eingeschränkt, dass y=1
bei x=0
.
Excel-Trendlinie stimmt mit dem Numpy lstsq
Ergebnis überein, aber wie Scipy leastsq
ist in der Lage, jede Funktion zu übernehmen, wäre es gut zu erarbeiten, was das Problem ist.
import scipy.optimize as optimize
import numpy as np
import matplotlib.pyplot as plt
## Sampled data
x = np.array([0, 14, 37, 975, 2013, 2095, 2147])
y = np.array([1.0, 0.764317544, 0.647136491, 0.070803763, 0.003630962, 0.001485394, 0.000495131])
# function
fp = lambda p, x: np.exp(p*x)
# error function
e = lambda p, x, y: (fp(p, x) - y)
# using scipy least squares
l1, s = optimize.leastsq(e, -0.004, args=(x,y))
print l1
# [-0.0132281]
# using numpy least squares
l2 = np.linalg.lstsq(np.vstack([x, np.zeros(len(x))]).T,np.log(y))[0][0]
print l2
# -0.00313461628963 (same answer as Excel trend line)
# smooth x for plotting
x_ = np.arange(0, x[-1], 0.2)
plt.figure()
plt.plot(x, y, 'rx', x_, fp(l1, x_), 'b-', x_, fp(l2, x_), 'g-')
plt.show()
Bearbeiten - zusätzliche Informationen
Die MWE über eine kleine Probe des Datensatzes enthält. Bei der Anpassung der tatsächlichen Daten zeigt die scipy.optimize.curve_fit Kurve ein R^2 von 0,82, während die numpy.linalg.lstsq Kurve, die die gleiche ist wie die von Excel berechnet, eine R^2 von 0,41 aufweist .
Dank @Jaime - große Antwort!Leider ist mein Mathematikwissen nicht so toll; ist ein write oder wrong [siehe auch edit oben], oder sind sie einfach grundverschieden ...? Was sind die Auswirkungen auf andere Funktionen, wenn ich beispielsweise die Anpassung einer Sigmoid- oder Gompertz-Kurve an dieselben Daten testen möchte? – StacyR
@StacyR Ich habe nicht das Wissen, um Ihre Frage richtig zu beantworten, aber ich bin mir ziemlich sicher, dass die Anpassung eines Exponentials, wie Sie es mit 'np.linalg.lstsq' gemacht haben, nur ein Quick'n'Dirty-Trick ist, der nicht berechnet Fehler richtig. Es gibt eine Diskussion (schwer für mich zu folgen) hier: http://mathworld.wolfram.com/LeastSquaresFittingExponential.html Wenn Sie nicht tief in diese Sachen tauchen wollen, würde ich mit scipy's Methode für alles gehen: es sollte bessere Passungen ergeben, und Ihre Ergebnisse werden für alle Funktionen konsistent sein. – Jaime
danke nochmal! Ich habe darüber mehr geforscht und festgestellt, dass die 'np.linalg.lstsq'-Methode y-Fehler bei niedrigen x-Werten übergewichtet. Die Verbindung, die Sie teilten, und einige andere Ressourcen, die ich fand, erlaubten mir, eine andere analytische Methode abzuleiten (die Sache, die es schwierig macht, ist die Einschränkung --- alle Bücher beschreiben die Methode für y = a * e^b * x eher als y = e^b * x), erzeugt dies jedoch auch eine schlechtere Anpassungskurve als die iterative "scipy.optimize.leastsq". – StacyR