# Fitting a sigmoid curve using curve fitting tool box

474 views (last 30 days)

Show older comments

Hari krishnan
on 17 Feb 2020

Edited: Srilatha Raghavan
on 31 Jul 2020

Hi, I am trying to fit a sigmoid function to the underlying data with the goodness of fit. I was using the curve fitting tool box. Unfortunately, i am not getting an idea to how to go forward with this. I tried to write custom function to fit the data, unfortunately, i am not able to get the required fit. Any help to solve this will be appreciated. X and Y data is shown below.

y= [0.70,1.09,0.96,0.37,0.27,0.35,0.16,0.18,0.18,0.02,0.37,0.67,1.26,1.70,1.85,1.73,1.92,1.72,1.47,1.50,1.46,1.43,2.12,1.6,1.8]

x = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]

##### 0 Comments

### Accepted Answer

Alex Sha
on 18 Feb 2020

Hi, Hair, the quailty of your data seems to be bad for sigmoid type of function. If take the function like:

y = y0+a/(1+exp(-(x-x0)/b))^c

Then the fitting result looks like:

### More Answers (1)

John D'Errico
on 18 Feb 2020

Edited: John D'Errico
on 18 Feb 2020

The problem is, there are many functional forms that people think of and call with the generic name "sigmoid". We can find a few of them listed here:

Perhaps the most common one is of the specific form:

f(x) = 1/(1 + exp(-x))

But many people will want to use thing like a transformed cumulative normal, which can be gotten from the erf function. Or possibly an arc tangent curve, or many others. Again, a few of them are shown on the wiki page. The thing is, each of those has a different fundamental shape.

y = [0.70,1.09,0.96,0.37,0.27,0.35,0.16,0.18,0.18,0.02,0.37,0.67,1.26,1.70,1.85,1.73,1.92,1.72,1.47,1.50,1.46,1.43,2.12,1.6,1.8]

x = 1:length(y);

plot(x,y,'o')

Your first problem is that your data is REALLY noisy. The first three points almost look like they are not even from the same curve.

Regardless, lets try to fit a simple sigmoidal model to your data. I'll start with the one I show above, adding some parameters, but keeping the same general form.

ft = fittype('L + (U-L)/(1 + exp(-4*log(3)*(x-xmid)/xscale80))','indep','x')

ft =

General model:

ft(L,U,xmid,xscale80,x) = L + (U-L)/(1 + exp(-4*log(3)*(x-xmid)/xscale80))

mdl = fit(x',y',ft,'start',[.5 ,3, 15,3])

mdl =

General model:

mdl(x) = L + (U-L)/(1 + exp(-4*log(3)*(x-xmid)/xscale80))

Coefficients (with 95% confidence bounds):

L = 0.4242 (0.2428, 0.6057)

U = 1.694 (1.519, 1.869)

xmid = 12.69 (11.91, 13.47)

xscale80 = 1.763 (-1.042, 4.567)

Here, I've named the parameters to be indicative of what they represent in the model. As it turns out, each of the paramters can be simply interpreted here.

That is, L is the lower asymptote, the limit of f(x), as x --> inf. U is the upper asymptote. xmid is the point where the curve goes through 50% of the transition. So xmid is the 50% point.

xscale80 is a little more difficult, but we can express it in the form of the width of the transition. If my arithmetic is correct, we can say the difference between the 10% and the 90% points on the curve will be xscale80. So 80% of the transition occurs between the 10% nd 90% points on that curve. Thus, when xscale80 is a large number, the transition is a slow one. If xscale is small, then the transition approaches a sharp step function.

plot(mdl)

grid on

hold on

plot(x,y,'bo')

xline(mdl.xmid);

xline(mdl.xmid + mdl.xscale80/2);

xline(mdl.xmid - mdl.xscale80/2);

I've drawn vertical lines at the 10% 50% and 90% points on the curve as it goes through the transition.

As you can see, the model does fit quasi-reasonably, although the lower asymptote is a bit off in my eyes. I did say your data was pure crapola, I think? At least those first three data points are dragging the estimate of L off from where it seems it should be. A weighted fit, or a robust regression would help.

mdl = fit(x',y',ft,'Robust','LAR','start',[.5 ,3, 15,3])

Fitting stopped because the number of iterations or function evaluations exceeded the specified maximum.

mdl =

General model:

mdl(x) = L + (U-L)/(1 + exp(-4*log(3)*(x-xmid)/xscale80))

Coefficients (with 95% confidence bounds):

L = 0.2993 (0.1037, 0.4948)

U = 1.72 (1.532, 1.908)

xmid = 12.59 (11.74, 13.44)

xscale80 = 2.374 (-0.7873, 5.536)

plot(mdl)

hold on

grid on

plot(x,y,'bo')

xline(mdl.xmid - mdl.xscale80/2);

xline(mdl.xmid);

xline(mdl.xmid + mdl.xscale80/2);

This fit looks more reasonable. Your data is still pure crapola though. This is hinted at by the width of the confidence intervals on the parameters. As you can see, those bounds on the parameters are all scarily wide.

##### 7 Comments

Srilatha Raghavan
on 31 Jul 2020

Edited: Srilatha Raghavan
on 31 Jul 2020

### See Also

### Categories

### Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!