Curve is not fitting

51 views (last 30 days)
Simona Zalesakova
Simona Zalesakova on 17 Nov 2020
Commented: Alex Sha on 17 Nov 2020
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
Simona Zalesakova
Simona Zalesakova on 17 Nov 2020
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.


Mathieu NOE
Mathieu NOE on 17 Nov 2020
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
Mathieu NOE
Mathieu NOE on 17 Nov 2020
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 !
Alex Sha
Alex Sha on 17 Nov 2020
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.

Community Treasure Hunt

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

Start Hunting!