Function fitting on a set of data points

20 visualizaciones (últimos 30 días)
Alessandro Ruda
Alessandro Ruda el 14 de En. de 2021
Comentada: John D'Errico el 15 de En. de 2021
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

Respuesta aceptada

John D'Errico
John D'Errico el 14 de En. de 2021
Editada: John D'Errico el 14 de En. de 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 comentarios
Alessandro Ruda
Alessandro Ruda el 15 de En. de 2021
Thank you guys for your time! I didn't consider this way of solving it
John D'Errico
John D'Errico el 15 de En. de 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.

Iniciar sesión para comentar.

Más respuestas (1)

Jon
Jon el 14 de En. de 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 comentario
Jon
Jon el 14 de En. de 2021
Editada: Jon el 14 de En. de 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))

Iniciar sesión para comentar.

Etiquetas

Productos

Community Treasure Hunt

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

Start Hunting!

Translated by