Curve is not fitting

Hi all, I am trying to fit my curve with a sigmoid.
I have these values which make up the curve : x-coordinates: 12.5 17.5 22.5 27.5 32.5 34.5 36.5 37 37.5 38 38.5 39 39.5 40 40.5 41
y-coordinates: 6924389.58 7199598.07 7021016.88 7274575.20 7136362.29 7007205.28 6325328.04 6921281.59 7118442.65 6632108.61 7115114.23 6934792.13 6894812.36 6346667.73 5328042.11 2999529.33
I am trying to do it with the curve fitting tool, where I enter this equation y=a/(1+exp(b*(x-c))) as it should be my desired equation of the sigmoid, and also the values which I mentioned above.
I always end up with a fit like this (attached picture). Also, I put another point to my data which you can see in the picture, I thought it would help but it did not, so maybe ignore that one.
Can someone please tell me what I am doing wrong?
Thank you very much in advance :)

Answers (2)

John D'Errico
John D'Errico on 17 Nov 2020
Edited: John D'Errico on 17 Nov 2020
With only one or two points where the function is not essentially constant to within the noise of the system, a good fit will be highly problematic. However, if you do not provide starting values for a problem involving expeonentials, expect garbage in the fit.
What did you get? Oh, right! Garbage. What a surprise. So, first, LOOK AT YOUR DATA. THINK ABOUT WHAT YOU SEE.
x = [12.5 17.5 22.5 27.5 32.5 34.5 36.5 37 37.5 38 38.5 39 39.5 40 40.5 41];
y = [6924389.58 7199598.07 7021016.88 7274575.20 7136362.29 7007205.28 6325328.04 6921281.59 7118442.65 6632108.61 7115114.23 6934792.13 6894812.36 6346667.73 5328042.11 2999529.33];
plot(x,y,'o')
What is your model? A sigmoidal form.
ft = fittype('a/(1+exp(b*(x-c)))','indep','x');
What is c here? The midpoint of the sigmoidal transition. It should be just a little over 40 from the plot. I will guess 41 or 42.
What is b? A rate parameter. 0.1 seems a decent guess. As long as I get the sign right, this is what is important. I need to be in the right ball park on the value itself, but I hope .1 is good. Too small is far better than too big a value for this rate constant however.
The sigmoidal model you have posed will have an upper asymptote, so where x--> -inf, as a. That would suggest a good starting value for x would be 7e6, purely from the plot.
The lower asymptote, where x--> inf, will be zero. I don't know if that is the behavior you would be looking for. Regardless, it would be literally impossible to estimate an asymptote as x--> inf here anyway. You have no data out there.
Not using starting values in the fit here will absolutely produce garbage for a result, since fit uses random staritng values otherwise.
mdl = fit(x',y',ft,'start',[7e6,.1,41])
mdl =
General model:
mdl(x) = a/(1+exp(b*(x-c)))
Coefficients (with 95% confidence bounds):
a = 6.971e+06 (6.821e+06, 7.121e+06)
b = 2.796 (1.969, 3.623)
c = 40.9 (40.81, 41)
So I was dead on about the estimates of a and c. I was way off on b, and I should have been smarter there. Had I taken a few seconds more in looking at the plot, I would have chosen a value around 1 instead. Regardless...
How is the fit?
hold on
plot(mdl)
This seems as good as I could expect. If you choose not to provide starting values for exponential models, expect garbage for a result in general. That is especially true when so little information content is present in your data. That is definitely the case here, where only about 3 out of 16 data points offer any value to estimate the shape of your curve.

1 Comment

Thank you very much for your response.
To be honest, my knowledge of the sigmoidal functions wasn't that deep so I didn't know how to predict the initial values. I also wasn't aware of the fact that I need them. Now that makes sense all together. You explained that really nicely. I managed to do the fit correctly now.
Thank you once again :)

Sign in to comment.

hello Simona
I had to modify the model fit equation to get it to work
I used : = a.*(1-1./(1+exp(b.*(x-c))));
instead of y=a/(1+exp(b*(x-c)))
to give it the rapidely falling characteristics.
bellow the code that gives good results
% code is giving good results with modified
% template equation : % y = a.*(1-1./(1+exp(b.*(x-c))));
x = [ 12.5 17.5 22.5 27.5 32.5 34.5 36.5 37 37.5 38 38.5 39 39.5 40 40.5 41];
y = [6924389.58 7199598.07 7021016.88 7274575.20 7136362.29 7007205.28 6325328.04 6921281.59 7118442.65 6632108.61 7115114.23 6934792.13 6894812.36 6346667.73 5328042.11 2999529.33];
f = @(a,b,c,x) a.*(1-1./(1+exp(b.*(x-c))));
obj_fun = @(params) norm(f(params(1), params(2), params(3),x)-y);
sol = fminsearch(obj_fun, [y(1),-1,x(end)]);
a_sol = sol(1);
b_sol = sol(2);
c_sol = sol(3);
figure;
plot(x, y, '+', 'MarkerSize', 10, 'LineWidth', 2)
hold on
plot(x, f(a_sol, b_sol,c_sol, x), '-');grid

3 Comments

Thank you very much for your response.
It looks very cool. The idea of modifying the equation didn't even cross my mind.
Next time I will try to think more about it.
Thank you for showing me a different point of view!
No problem
you're welcome
John is right about a couple of crucial points : making sure that the fit model will have a chance to give the expected results , and good initial conditions, especially when highly non linear models are used.
i'll keep John "master class" example for my own use BTW !
Now the last thing you have to do is to accept one or the other answer !
Hi, all, in the aspect of curve fitting, MATLAB has still much room for improvement, for example, 1stOpt, another package, is no longer required to guess initial start-values by end-user, but with prefect results. Taking above fitting example, the code of 1stOpt looks like below:
Function y=a/(1+exp(b*(x-c)));
Data;
x = [12.5 17.5 22.5 27.5 32.5 34.5 36.5 37 37.5 38 38.5 39 39.5 40 40.5 41];
y = [6924389.58 7199598.07 7021016.88 7274575.20 7136362.29 7007205.28 6325328.04 6921281.59 7118442.65 6632108.61 7115114.23 6934792.13 6894812.36 6346667.73 5328042.11 2999529.33];
That is all! The results are:
Root of Mean Square Error (RMSE): 220076.767330568
Sum of Squared Residual: 774940536298.77
Correlation Coef. (R): 0.977076130054301
R-Square: 0.95467776392189
Parameter Best Estimate
---------- -------------
a 6970802.67818004
b 2.79576804361248
c 40.9038349616737
If the fitting function is: y=a*(1-1/(1+exp(b*(x-c))));
The code will be:
Function y=a*(1-1/(1+exp(b*(x-c))));
Data;
x = [12.5 17.5 22.5 27.5 32.5 34.5 36.5 37 37.5 38 38.5 39 39.5 40 40.5 41];
y = [6924389.58 7199598.07 7021016.88 7274575.20 7136362.29 7007205.28 6325328.04 6921281.59 7118442.65 6632108.61 7115114.23 6934792.13 6894812.36 6346667.73 5328042.11 2999529.33];
Result:
Root of Mean Square Error (RMSE): 220076.767330569
Sum of Squared Residual: 774940536298.773
Correlation Coef. (R): 0.977076130061656
R-Square: 0.954677763936262
Parameter Best Estimate
---------- -------------
a 6970802.67817935
b -2.79576804360291
c 40.9038349616752

Sign in to comment.

Categories

Asked:

on 17 Nov 2020

Commented:

on 17 Nov 2020

Community Treasure Hunt

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

Start Hunting!