Rami2314
Rami2314

Reputation: 113

Curvefit() not fitting my data correctly. How to give a good fit?

I am currently trying to fit by data using the curvefit() function in python. The shape should be a upside down 'hump' like shape. However this is giving me a parabola looking shape. Here is the code and a picture. Any help would be much appreciated![1]: https://i.sstatic.net/fmRBn.png

def model(x, a, p,q):
    return a*np.exp(p*x+q*x**2)

# Input data
x = np.array([11, 11, 11,15,15,15,20,20,20,25,25,25,29,29,29])
y = np.array([2.048, 1.56, 1.18, 2.6116,2.35,2.1036,2.97, 2.97, 2.97, 2.463,2.05,1.6679,1.825,1.0939,0.534])
[enter image description here][1]
# Fit
popt, pcov = curve_fit(model, x, y)

# prepare some data for a plot
xx = np.linspace(-20, 60)
yy = model(xx, *popt)

plt.plot(x, y, 'o', xx, yy)
plt.title('Exponential Fit')
plt.ylim(0,5)
plt.xlim(-5,30)
plt.grid()
plt.show()
print(popt)

Upvotes: 1

Views: 871

Answers (2)

Warren Weckesser
Warren Weckesser

Reputation: 114811

curve_fit (like many iterative fitting and optimization methods) performs best when it is given a reasonable starting point. The default initial guess for curve_fit is all 1s, which is a very bad guess for your problem--warnings are generated, overflow occurs, and the returned pcov is an array of all inf values (did you check it?).

With a little trial-and-error, I was able to get what looks like a reasonable fit by using p0=[0.1, 0.1, -0.001]:

In [123]: popt, pcov = curve_fit(model, x, y, p0=[0.1, 0.1, -0.001])

In [124]: popt
Out[124]: array([ 0.0847053 ,  0.36886652, -0.00961928])

In [125]: pcov
Out[125]: 
array([[ 2.96403174e-03, -3.64981635e-03,  8.97783126e-05],
       [-3.64981635e-03,  4.61677436e-03, -1.15963105e-04],
       [ 8.97783126e-05, -1.15963105e-04,  2.96960195e-06]])

Here's the plot of your data and the fitted curve:

plot

Upvotes: 0

Looking at your data, I would suggest to drop the exponencial model and just keep the paraobolic function

def simple_model(x, a, p,q):
    return p*x + q*x**2 + a

For complicated non-linear functions curve-fit can't do magic, keep it simple, and then you might add more stuff to the model.

Anyway, if you rather stick to your model, you can set the seed of the initial values of a, p and q that curve_fit will try to optimize:

popt, pcov = curve_fit(model, x, y, p0=[a_seed, p_seed, q_seed])

Playing with reasonable initial guesses of a_seed, p_seed, q_seed may be helpful. Good luck!

Upvotes: 1

Related Questions