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