MATLAB Answers

Function fitting on a set of data points

36 views (last 30 days)
Hello,
I am trying to fit a function on a set of data point using some parameters to be optimized and the function lsqcurvefit.
The function is essentially:
y = a+b*cos(x)+c*cos(2*x)+d*sin(x)-e*sin(2*x);
So I first defined the parameters in terms on one variable, as following:
x(1) = a
x(2) = b
x(3) = c
x(4) = d
x(5) = e
And here goes the code:
DATA = load('data_f.txt');
t = DATA(:,1);
y = DATA(:,2);
plot(t,y,'ro')
F = @(x,xdata) +x(1) - x(2)*cos(xdata*(pi/180)) + x(3)*cos(2*xdata*(pi/180)) - x(4)*sin(xdata*(pi/180)) - x(5)*sin(2*xdata*(pi/180));
x0 = [1 1 1 1 1];
[x,resnorm,~,exitflag,output] = lsqcurvefit(F,x0,t,y)
hold on
plot(t,F(t,y))
hold off
Problem is that the curve looks horrible but the parameters look fine compared to the fitting done in other programs. Is there something I am not seeing?
Thank you very much in advance!
Stay safe,
Alex

  0 Comments

Sign in to comment.

Accepted Answer

John D'Errico
John D'Errico on 14 Jan 2021
Edited: John D'Errico on 14 Jan 2021
What did you do wrong? It looks like Jon may be correct, in that you did not use the newly estimated set of parameters from the fit.
xy = [0.0 6.08
15 5.3
30 4.28
45 2.89
60 1.31
75 -0.16
90 -0.47
105 0.23
120 1.68
135 3.55
150 5.32
165 6.51
180 6.86
195 6.29
210 4.92
225 3.04
240 1.19
255 0
270 -0.09
285 0.75
300 2.21
315 3.89
330 5.29
345 6.09
360 6.08];
x = xy(:,1);
y = xy(:,2);
FIRST, PLOT YOUR DATA. LOOK AT IT. Does this simple trig model make sense?
plot(x,y,'ro')
And, yes, the result does seem to be a very simple sinusoidally varying curve.
However, there is no need to use lsqcurvefit to fit this, since it is a linear model in the parameters. Using a nonlinear estimation tool to fit a linear model is like using a Mack truck to carry a pea to Boston. A bit of over kill. But, yes, you could use lsqcurvefit. I won't bother to do so here.
A = [ones(size(x)),sind(x),sind(2*x),cosd(x),cosd(2*x)];
coefs = A\y
coefs = 5×1
3.1957 -0.1826 -0.4175 -0.2026 3.3489
plot(x,y,'ro')
hold on
fun = @(u,coefs) coefs(1) + coefs(2)*sind(u) + coefs(3)*sind(2*u) + coefs(4)*cosd(u) + coefs(5)*cosd(2*u);
plot(x,fun(x,coefs),'b-')
hold off
While there is a little lack of fit, it is not terrible. Look at the residual errors.
plot(x,y - fun(x,coefs),'o-')
Lack of fit is usually seen as patterning in the residuals. Here we see exactly that. So your model is probably not the correct model for this data, merely a good approximation to that data. By way of comparison, how much of the information in your original signal has been explained by the model?
[var(y),var(y - fun(x,coefs))]
ans = 1×2
6.1724 0.0445
As a percentage of the total variance...
100*(1 - var(y - fun(x,coefs))/var(y))
ans = 99.2797
So around 99% of the total variance in y has been explained by your model. So pretty good, but not perfect.

  3 Comments

Jon
Jon on 14 Jan 2021
I didn't look that closely at the overall problem the OP was trying to solve, just at the specific error. Great point that this can be solved as a linear regression problem, as it is linear in the parameters, even though the function that is fit is not a linear equation. I think this is often overlooked.
Alessandro Ruda
Alessandro Ruda on 15 Jan 2021
Thank you guys for your time! I didn't consider this way of solving it
John D'Errico
John D'Errico on 15 Jan 2021
Yes. I think that too often people overlook that point, that a "linear" regression refers to the parameters. If the model is linear in the parameters, then it is a linear regression problem. Instead, people look at what they see as a NONLINEAR model, and accept that this must be a nonlinear regression. Not the end of the world, but this is, as I am known to say, is like using a Mack truck to carry a pea to Boston. (Don't ask where I learned the phrase.) You don't want to use a nonlinear estimation tool to solve a linear problem if you can avoid it, as that carries its own set of issues.

Sign in to comment.

More Answers (1)

Jon
Jon on 14 Jan 2021
It seems like you are not using the parameters you just solved for when evaluating your function to plot it.
Maybe you meant
plot(t,F(x,t))

  1 Comment

Jon
Jon on 14 Jan 2021
or if you want to compare the data points to the fitted curve
numFit = 1000; % for example
tfit = linspace(t(1),t(end),numFit)
plot(t,y,'o',tfit,F(x,tfit))

Sign in to comment.

Products

Community Treasure Hunt

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

Start Hunting!