3 views (last 30 days)

Show older comments

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

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

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))]

As a percentage of the total variance...

100*(1 - var(y - fun(x,coefs))/var(y))

So around 99% of the total variance in y has been explained by your model. So pretty good, but not perfect.

John D'Errico
on 15 Jan 2021

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))

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))

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

Start Hunting!