varantir
varantir

Reputation: 6854

Curve fit of scipy not working with sines?

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?

Failed Fit

Upvotes: 2

Views: 1057

Answers (2)

pseudocubic
pseudocubic

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): example figure

Upvotes: 4

dnalow
dnalow

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

Related Questions