Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fit sigmoid function ("S" shape curve) to data using Python

I'm trying to fit a sigmoid function to some data I have but I keep getting:ValueError: Unable to determine number of fit parameters.

My data looks like this:

enter image description here

My code is:

from scipy.optimize import curve_fit

def sigmoid(x):
    return (1/(1+np.exp(-x)))

popt, pcov = curve_fit(sigmoid, xdata, ydata, method='dogbox')

Then I get:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-5-78540a3a23df> in <module>
      2     return (1/(1+np.exp(-x)))
      3 
----> 4 popt, pcov = curve_fit(sigmoid, xdata, ydata, method='dogbox')

~\Anaconda3\lib\site-packages\scipy\optimize\minpack.py in curve_fit(f, xdata, ydata, p0, sigma, absolute_sigma, check_finite, bounds, method, jac, **kwargs)
    685         args, varargs, varkw, defaults = _getargspec(f)
    686         if len(args) < 2:
--> 687             raise ValueError("Unable to determine number of fit parameters.")
    688         n = len(args) - 1
    689     else:

ValueError: Unable to determine number of fit parameters.

I'm not sure why this does not work, it seems like a trivial action--> fit a curve to some point. The desired curve would look like this:

enter image description here

Sorry for the graphics.. I did it in PowerPoint...

How can I find the best sigmoid ("S" shape) curve?

UPDATE

Thanks to @Brenlla I've changed my code to:

def sigmoid(k,x,x0):
    return (1 / (1 + np.exp(-k*(x-x0))))

popt, pcov = curve_fit(sigmoid, xdata, ydata, method='dogbox')

Now I do not get an error, but the curve is not as desired:

x = np.linspace(0, 1600, 1000)
y = sigmoid(x, *popt)

plt.plot(xdata, ydata, 'o', label='data')
plt.plot(x,y, label='fit')
plt.ylim(0, 1.3)
plt.legend(loc='best')

and the result is:

enter image description here

How can I improve it so it will fit the data better?

UPDATE2

The code is now:

def sigmoid(x, L,x0, k, b):
    y = L / (1 + np.exp(-k*(x-x0)))+b

But the result is still...

enter image description here

like image 615
user88484 Avatar asked Apr 17 '19 10:04

user88484


People also ask

How do you fit a sigmoid curve in Matlab?

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

What is S curve in machine learning?

s-curves. S-curves are used to model growth or progress of many processes over time (e.g. project completion, population growth, pandemic spread, etc.). The shape of the curve looks very similar to the letter s , hence, the name, s-curve . There are many functions that may be used to generate a s-curve.


Video Answer


1 Answers

After great help from @Brenlla the code was modified to:

def sigmoid(x, L ,x0, k, b):
    y = L / (1 + np.exp(-k*(x-x0))) + b
    return (y)

p0 = [max(ydata), np.median(xdata),1,min(ydata)] # this is an mandatory initial guess

popt, pcov = curve_fit(sigmoid, xdata, ydata,p0, method='dogbox')

The parameters optimized are L, x0, k, b, who are initially assigned in p0, the point the optimization starts from.

  • L is responsible for scaling the output range from [0,1] to [0,L]
  • b adds bias to the output and changes its range from [0,L] to [b,L+b]
  • k is responsible for scaling the input, which remains in (-inf,inf)
  • x0 is the point in the middle of the Sigmoid, i.e. the point where Sigmoid should originally output the value 1/2 [since if x=x0, we get 1/(1+exp(0)) = 1/2].

And the result:

enter image description here

like image 176
user88484 Avatar answered Oct 19 '22 11:10

user88484