Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scipy sigmoid curve fitting

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.

like image 759
Johanna Köllner Avatar asked Jun 10 '18 17:06

Johanna Köllner


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 does SciPy optimize curve_fit return?

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.

What is POPT and PCOV?

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.


Video Answer


2 Answers

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

enter image description here

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]

like image 75
Severin Pappadeux Avatar answered Nov 28 '22 05:11

Severin Pappadeux


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

like image 43
9769953 Avatar answered Nov 28 '22 06:11

9769953