I have some data points and would like to find a fitting function, I guess a cumulative Gaussian sigmoid function would fit, but I don't really know how to realize that.
This is what I have right now:
import numpy as np
import pylab
from scipy.optimize import curve_fit
def sigmoid(x, a, b):
y = 1 / (1 + np.exp(-b*(x-a)))
return y
xdata = np.array([400, 600, 800, 1000, 1200, 1400, 1600])
ydata = np.array([0, 0, 0.13, 0.35, 0.75, 0.89, 0.91])
popt, pcov = curve_fit(sigmoid, xdata, ydata)
print(popt)
x = np.linspace(-1, 2000, 50)
y = sigmoid(x, *popt)
pylab.plot(xdata, ydata, 'o', label='data')
pylab.plot(x,y, label='fit')
pylab.ylim(0, 1.05)
pylab.legend(loc='best')
pylab.show()
But I get the following warning:
.../scipy/optimize/minpack.py:779: OptimizeWarning: Covariance of the parameters could not be estimated category=OptimizeWarning)
Can anyone help? I'm also open for any other possibilities to do it! I just need a curve fit in any way to this data.
One great thing that you can do is to use the "Curve fitting" App in Matlab. you can find it in APPS, in "Math, statistics and optimization" section. over there you can choose your x and y data and the function that you want to fit over them (you can enter custom equations such as sigmoid).
Returns poptarray. Optimal values for the parameters so that the sum of the squared residuals of f(xdata, *popt) - ydata is minimized. pcov2-D array. The estimated covariance of popt. The diagonals provide the variance of the parameter estimate.
1. What does popt and pcov mean? popt- An array of optimal values for the parameters which minimizes the sum of squares of residuals. pcov-2d array which contains the estimated covariance of popt. The diagonals provide the variance of the parameter estimate.
You could set some reasonable bounds for parameters, for example, doing
def fsigmoid(x, a, b):
return 1.0 / (1.0 + np.exp(-a*(x-b)))
popt, pcov = curve_fit(fsigmoid, xdata, ydata, method='dogbox', bounds=([0., 600.],[0.01, 1200.]))
I've got output
[7.27380294e-03 1.07431197e+03]
and curve looks like
First point at (400,0) was removed as useless. You could add it, though result won't change much...
UPDATE
Note, that bounds are set as ([low_a,low_b],[high_a,high_b]), so I asked for scale to be within [0...0.01] and location to be within [600...1200]
You may have noticed the resulting fit is completely incorrect.
Try passing some decent initial parameters to curve_fit
, with the p0
argument:
popt, pcov = curve_fit(sigmoid, xdata, ydata, p0=[1000, 0.001])
should give a much better fit, and probably no warning either.
(The default starting parameters are [1, 1]; that is too far from the actual parameters to obtain a good fit.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With