Ich versuche gerade Daten zu fitten, welche generell der Form y = A*x^B folgen.
Ich habe bisher drei Varianten getestet:
Variante 1: Linearisieren und mit nump.polyfit fitten.
Variante 2: stumpf scipy.curve_fit anwenden (Startwerte geschätzt, ich gebe ja die analytische form oben im code vor) <- erscheint mir am elegantesten.
Variante 3: Adaption des Beispiels von hier http://scipy-cookbook.readthedocs.io/it ... gData.html (ganz unten).
Code: Alles auswählen
import numpy as np
import matplotlib.pyplot as plt
from scipy import optimize
powerlaw = lambda x, amp, index: amp * (x**index)
num_points = 20
xdata = np.linspace(1.1, 10.1, num_points)
ydata = powerlaw(xdata, 10.0, -2.0) # simulated perfect data
yerr = 0.1 * ydata # simulated errors (10%)
ydata += np.random.randn(num_points) * yerr#
########### Variante 1: ###########
A = np.polyfit(np.log10(xdata), np.log10(ydata), 1)
amp1 = 10**A[1]
yn1=amp1*xdata**A[0]
plt.plot(xdata,ydata,'ro')
plt.plot(xdata,yn1,'g-')
########### Variante 2: ###########
B = optimize.curve_fit(lambda t,a,b: a*t**b, xdata, ydata, p0=(9, -1))
yn2=B[0][0]*xdata**B[0][1]
plt.plot(xdata,yn2,'b--')
########### Variante 3: ###########
logx = np.log10(xdata)
logy = np.log10(ydata)
logyerr = yerr / ydata
# define our (line) fitting function
fitfunc = lambda p, x: p[0] + p[1] * x
errfunc = lambda p, x, y, err: (y - fitfunc(p, x)) / err
pinit = [1.0, -1.0]
out = optimize.leastsq(errfunc, pinit,
args=(logx, logy, logyerr), full_output=1)
pfinal = out[0]
index = pfinal[1]
amp = 10.0**pfinal[0]
plt.plot(xdata, powerlaw(xdata, amp, index),'r-')
plt.show()
Daher habe ich ein paar Fragen:
1. Weshalb liefert mir curve_fit einen subjektiv schlechteren fit? (Bei echten Daten sieht man es deutlicher als in diesem Testfall)
2. Weshalb steigt Variante 3 aus, sobald der yerr = 0 ist?
3. Was wäre denn der ideale Weg des fittings?
Danke!