Reputation: 6854
I do not understand what's wrong with this data fitting:
from scipy.optimize import curve_fit
def sin_fit(x, *p):
a,b,c,d= p
return a + b*np.sin(c*x+ d)
# p0 is the initial guess for the fitting coefficients
p0 = [0.1, 1., 1., 0.1]
coeff, var_matrix = curve_fit(sin_fit, t, data, p0=p0)
I guess either there is something obvious wrong, which I am missing at the moment, or I cannot use the curve fit from scipy for this problem. Any ideas?
Upvotes: 2
Views: 1057
Reputation: 1039
It seems like this is a problem with your initial guess, in particular the frequency you chose is too far off. At your current initial guess p0
, curve_fit
will not converge fast enough on a good answer, so you need to choose a better p0
. Here's an example of what I mean:
t = np.linspace(0,50,1000)
data = 0.275 * (np.random.rand(len(t)) * 0.2 + 1.) * np.sin(2. * np.pi / 15. * t - 7.5)
p0 = [0.2, 0.5, 1.5 * np.pi / 14, 0.]
coeff, var_matrix = curve_fit(sin_fit, t, data, p0=p0)
plt.plot(t, data, 'bo')
plt.plot(t, sin_fit(t, *p0), 'g-')
plt.plot(t, sin_fit(t, *coeff), 'r-')
Below you can see that with a closer initial guess (green curve) curve_fit
will perform the fit better (red curve):
Upvotes: 4
Reputation: 984
Everything works and the algorithm found a local minimum, as it is supposed to do. Your initial guess of the frequency is just far of from reality.
Good fitting does not only rely on the right model, but also on good starting values. Expecially for periodic curves, higher harmonics can form a local minimum.
Thats why fitting is never a blackbox like data in -> result out mechanism. User interference is almost always needed. If that is not favorable, and you have such kind of data, rather use fourier analysis to get the information aimed for.
Upvotes: 3