21 Sep 03:38 2010

## Sigmoid Curve Fitting

```Hi,

Does Scipy contain the ability to fit a sigmoid curve to a set of data points?

I found some Numpy code
(http://pingswept.org/2009/01/24/least-squares-polynomial-fitting-in-python/)
for fitting curves using the least squares method, but it only seems
to fit parabolas to my sigmoid data.

Regards,
Chris
```
21 Sep 05:54 2010

### Re: Sigmoid Curve Fitting

```  On 9/20/10 8:38 PM, Chris Spencer wrote:
> Hi,
>
> Does Scipy contain the ability to fit a sigmoid curve to a set of data points?
>
> I found some Numpy code
> (http://pingswept.org/2009/01/24/least-squares-polynomial-fitting-in-python/)
> for fitting curves using the least squares method, but it only seems
> to fit parabolas to my sigmoid data.
>

You can use curve_fit (scipy.optimize.curve_fit).

Which family of sigmoid functions do you want to use?
See http://en.wikipedia.org/wiki/Sigmoid_function for a few possibilities.

If, for example, you want to fit the following family to your data:

f(x) = 1/(1 + exp(-k*(x-x0)))

(which has two parameters, k and x0), you can do something like this:

-----
import numpy as np
import pylab
from scipy.optimize import curve_fit

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

21 Sep 15:13 2010

### Re: Sigmoid Curve Fitting

```Thank you. Since that feature only appears to be in the bleeding-edge
version, it took me a while to track-down and compile all the
libraries on Ubuntu 10.04, but it works perfectly.

Regards,
Chris

On Mon, Sep 20, 2010 at 11:54 PM, Warren Weckesser
<warren.weckesser <at> enthought.com> wrote:
>  On 9/20/10 8:38 PM, Chris Spencer wrote:
>>
>> Hi,
>>
>> Does Scipy contain the ability to fit a sigmoid curve to a set of data
>> points?
>>
>> I found some Numpy code
>>
>> (http://pingswept.org/2009/01/24/least-squares-polynomial-fitting-in-python/)
>> for fitting curves using the least squares method, but it only seems
>> to fit parabolas to my sigmoid data.
>>
>
> You can use curve_fit (scipy.optimize.curve_fit).
>
> Which family of sigmoid functions do you want to use?
> See http://en.wikipedia.org/wiki/Sigmoid_function for a few possibilities.
>
> If, for example, you want to fit the following family to your data:
>
```

21 Sep 17:24 2010

### Re: Sigmoid Curve Fitting

```Is it possible to get it to determine the asymptotes as well? It seems
to assume the curve will be bounded between y=0 and 1, whereas my data
can have arbitrary limits. I tried changing sigmoid() to:

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

but that only results in a curve of f(x)=0.5.

Regards,
Chris

On Mon, Sep 20, 2010 at 11:54 PM, Warren Weckesser
<warren.weckesser <at> enthought.com> wrote:
>  On 9/20/10 8:38 PM, Chris Spencer wrote:
>>
>> Hi,
>>
>> Does Scipy contain the ability to fit a sigmoid curve to a set of data
>> points?
>>
>> I found some Numpy code
>>
>> (http://pingswept.org/2009/01/24/least-squares-polynomial-fitting-in-python/)
>> for fitting curves using the least squares method, but it only seems
>> to fit parabolas to my sigmoid data.
>>
>
> You can use curve_fit (scipy.optimize.curve_fit).
```

21 Sep 18:16 2010

### Re: Sigmoid Curve Fitting

```  On 9/21/10 10:24 AM, Chris Spencer wrote:
> Is it possible to get it to determine the asymptotes as well? It seems
> to assume the curve will be bounded between y=0 and 1, whereas my data
> can have arbitrary limits. I tried changing sigmoid() to:
>
> def sigmoid(x, x0, k, a):
>     y = a * 1 / (1 + np.exp(-k*(x-x0)))
>     return y
>
> but that only results in a curve of f(x)=0.5.
>

The following is a variation that includes more parameters in the family
of sigmoid functions.  But bear in mind, I chose this family of
functions just as a demonstration of curve_fit.  I don't know if it
makes sense to use this family for your data.  The appropriate family to
use depends on the nature of the data.

-----
import numpy as np
import pylab
from scipy.optimize import curve_fit

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

xdata = np.array([0.0,   1.0,  3.0,  4.3,  7.0,   8.0,   8.5, 10.0,
12.0, 14.0])
ydata = np.array([0.11, 0.12, 0.14, 0.21, 0.83,  1.45,   1.78,  1.9,
```

21 Sep 19:02 2010

### Re: Sigmoid Curve Fitting

```On Tue, Sep 21, 2010 at 12:16 PM, Warren Weckesser
<warren.weckesser <at> enthought.com> wrote:
> The following is a variation that includes more parameters in the family
> of sigmoid functions.  But bear in mind, I chose this family of
> functions just as a demonstration of curve_fit.  I don't know if it
> makes sense to use this family for your data.  The appropriate family to
> use depends on the nature of the data.

I see what you mean. That modification only fits a low-to-high
sigmoid, but that's close enough for me to adapt by reversing my data
set. Thank you for the excellent example.

Regards,
Chris
```
21 Sep 20:04 2010

### Re: Sigmoid Curve Fitting

```I found this modification allows for the inversion of the estimated
sigmoid curve:

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

Regards,
Chris

On Tue, Sep 21, 2010 at 1:02 PM, Chris Spencer <chrisspen <at> gmail.com> wrote:
> On Tue, Sep 21, 2010 at 12:16 PM, Warren Weckesser
> <warren.weckesser <at> enthought.com> wrote:
>> The following is a variation that includes more parameters in the family
>> of sigmoid functions.  But bear in mind, I chose this family of
>> functions just as a demonstration of curve_fit.  I don't know if it
>> makes sense to use this family for your data.  The appropriate family to
>> use depends on the nature of the data.
>
> I see what you mean. That modification only fits a low-to-high
> sigmoid, but that's close enough for me to adapt by reversing my data
> set. Thank you for the excellent example.
>
> Regards,
> Chris
>
```
21 Sep 20:21 2010

### Re: Sigmoid Curve Fitting

```
On 9/21/10 1:04 PM, Chris Spencer wrote:
> I found this modification allows for the inversion of the estimated
> sigmoid curve:
>
> def sigmoid(x, x0, k, a, c, d):
>      y = 1 / (1 + np.exp(-k*(x-x0)))
>      y = (1 - y)*(1 - d) + y*d
>      y = a * y + c
>      return y
>

A negative value of k "reverses" the sigmoid shape, so you shouldn't
have to define a new function.  If you prefer to have k be positive, you
could use

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

(I changed "-k" to "k".)

Warren

> Regards,
> Chris
>
> On Tue, Sep 21, 2010 at 1:02 PM, Chris Spencer<chrisspen <at> gmail.com>  wrote:
>> On Tue, Sep 21, 2010 at 12:16 PM, Warren Weckesser
>> <warren.weckesser <at> enthought.com>  wrote:
```

21 Sep 20:30 2010

### Re: Sigmoid Curve Fitting

```Right, I noticed that negating k should theoretically have the same
effect. However, when I reversed your sample data (i.e. ydata =
ydata[::-1]), I was surprised to find that curve_fit gives me
to work around this problem.

Regards,
Chris

On Tue, Sep 21, 2010 at 2:21 PM, Warren Weckesser
<warren.weckesser <at> enthought.com> wrote:
>
> On 9/21/10 1:04 PM, Chris Spencer wrote:
>> I found this modification allows for the inversion of the estimated
>> sigmoid curve:
>>
>> def sigmoid(x, x0, k, a, c, d):
>>      y = 1 / (1 + np.exp(-k*(x-x0)))
>>      y = (1 - y)*(1 - d) + y*d
>>      y = a * y + c
>>      return y
>>
>
>
> A negative value of k "reverses" the sigmoid shape, so you shouldn't
> have to define a new function.  If you prefer to have k be positive, you
> could use
>
> def sigmoid(x, x0, k, a, c):
>     y = a / (1 + np.exp(k*(x-x0))) + c
```

21 Sep 20:36 2010

### Re: Sigmoid Curve Fitting

```  On 9/21/10 1:30 PM, Chris Spencer wrote:
> Right, I noticed that negating k should theoretically have the same
> effect. However, when I reversed your sample data (i.e. ydata =
> ydata[::-1]), I was surprised to find that curve_fit gives me
> f(x)=0.92 instead of a proper sigmoid curve.

Ah, in that case, it can help to give curve_fit a better initial guess
for the parameters.  For example, if I use

popt, pcov = curve_fit(sigmoid, xdata, ydata, p0=(1.0, -1.0, 1.0, 0.0))

with the original function, it works as expected.

Warren

> to work around this problem.
>
> Regards,
> Chris
>
> On Tue, Sep 21, 2010 at 2:21 PM, Warren Weckesser
> <warren.weckesser <at> enthought.com>  wrote:
>> On 9/21/10 1:04 PM, Chris Spencer wrote:
>>> I found this modification allows for the inversion of the estimated
>>> sigmoid curve:
>>>
>>> def sigmoid(x, x0, k, a, c, d):
>>>       y = 1 / (1 + np.exp(-k*(x-x0)))
>>>       y = (1 - y)*(1 - d) + y*d
```

21 Sep 21:29 2010

### Re: Sigmoid Curve Fitting

```> Hi,
>
> Does Scipy contain the ability to fit a sigmoid curve to a set of data
> points?
>
> I found some Numpy code
> (http://pingswept.org/2009/01/24/least-squares-polynomial-fitting-in-python/)
> for fitting curves using the least squares method, but it only seems
> to fit parabolas to my sigmoid data.

scipy.optimize.leastsq can fit any non-linear regression curve using
Levenberg-Marquardt. You will have to supply a function that computes the
residuals, and optionally a function that returns their Jacobian unless
you want it estimated.

Sturla
```
21 Sep 22:31 2010

### Re: Sigmoid Curve Fitting

On Tue, Sep 21, 2010 at 2:29 PM, Sturla Molden wrote:
scipy.optimize.leastsq can fit any non-linear regression curve using
Levenberg-Marquardt. You will have to supply a function that computes the
residuals, and optionally a function that returns their Jacobian unless
you want it estimated.

curve_fit is just a specific version of leastsq, right? From their documentation I see that they both employ the same nonlinear regression algorithm.

--
Gökhan
```_______________________________________________
SciPy-User mailing list
SciPy-User <at> scipy.org
http://mail.scipy.org/mailman/listinfo/scipy-user
```
22 Sep 03:18 2010

### Re: Sigmoid Curve Fitting

```On Tue, Sep 21, 2010 at 2:29 PM, Sturla Molden <sturla <at> molden.no> wrote:
>> Hi,
>>
>> Does Scipy contain the ability to fit a sigmoid curve to a set of data
>> points?
>>
>> I found some Numpy code
>> (http://pingswept.org/2009/01/24/least-squares-polynomial-fitting-in-python/)
>> for fitting curves using the least squares method, but it only seems
>> to fit parabolas to my sigmoid data.
>
> scipy.optimize.leastsq can fit any non-linear regression curve using
> Levenberg-Marquardt. You will have to supply a function that computes the
> residuals, and optionally a function that returns their Jacobian unless
> you want it estimated.
>
> Sturla
>
Ignoring that you data is the opposite,  there are a lot of 'growth
curves'  such as Richard's (growth) curve or generalized logistic
function.
http://en.wikipedia.org/wiki/Generalised_logistic_function

Also, you can fit a linear model if your model can be linearized. The
downside is that the errors are multiplicative rather than additive.
For nonlinear models, it usually helps to standardize your data.

Bruce
```

Gmane