nonlinear curve , lsqcurvefit

I am using 'lsqcurvefit' to fit a nonlinear model ( Actualy a fourier series in which I know the frequencies. I want the amplitude of each sin/cosine term). So problem is like this,
suppose I have 'N' grid point and for each grid point I have time series data for which I know three dominant frequencies. Now the model which I want to fit on the time series for each grid is
H=A+B*t + C1*cos(2.pi.f2*t)+ C2*sin(2.pi.f1*t)+ C3*cos(2.pi.f2*t)+
C4*sin(2.pi.f2*t)+ C5*cos(2.pi.f3*t)+ C6*sin(2.pi.f3*t)
As I mentioned, I know the value of f1, f2, f3 for each grid and want to estimate A,B,C1,C2,... for each grid. Here 't' is independent variable.
I want to do this in loop for i=1:N and change the value of 'f' for each loop as I have these values for each grid.
Can you please help me out from this problem.
Here is what I was trying but its not working. Firstly I define a function with some function name say 'FUN' hence
@FUN((x0,Xdata,f) H=x0(1)+x0(2)*Xdata+x0(3)*cos(2*pi*f1.*Xdata)+x0(4)...
*sin(2*pi*f1.*Xdata)+x0(5)*cos(2*2*pi*f2.*Xdata)+...
x0(6)*sin(2*2*pi*f2.*Xdata)+x0(7)*cos(3*2*pi*f3.*Xdata)+...
x0(8)*sin(3*2*pi*f3.*Xdata);
and
f=[f1,f2,f3]
then using lsqcurvefitting
[P1,N1,R1,EF1,OP1,L1,J1]=lsqcurvefit(@EWHmodelFunc3,ones(8,1)*0.5,f0,t,EWH);
Please help me out

2 Comments

Matt J
Matt J on 15 Sep 2016
Edited: Matt J on 15 Sep 2016
Here is what I was trying but its not working.
What are the copy/pasted error messages?
Your objective function is linear in all of the parameters. Looks like you should really be using lsqlin(). If the lower bound EWH is non-critical, you could even be using mldivide().

Sign in to comment.

Answers (1)

Matt J
Matt J on 15 Sep 2016
Edited: Matt J on 15 Sep 2016
Just some guesses, but you really need to provide copy/pastes of error messages as requested here. Your definition of FUN has the wrong syntax. Looks like it should be
EWHmodelFunc3 = @FUN((x0,Xdata,f) x0(1)+x0(2)*Xdata+x0(3)*cos(2*pi*f1.*Xdata)+x0(4)...
*sin(2*pi*f1.*Xdata)+x0(5)*cos(2*2*pi*f2.*Xdata)+...
x0(6)*sin(2*2*pi*f2.*Xdata)+x0(7)*cos(3*2*pi*f3.*Xdata)+...
x0(8)*sin(3*2*pi*f3.*Xdata);
Also, the call to lsqcurvefit looks like it should be
[P1,N1,R1,EF1,OP1,L1,J1]=...
lsqcurvefit(@(x0,Xdata) EWHmodelFunc3(x0,Xdata,f),ones(8,1)*0.5,f0,t,EWH);

4 Comments

Dear Matt,
Thanks for your comment. Now quick response to your comments.
Mathematical form of the function which I defined is correct. I understand that you suggested me to add index 'n' in each term of sine/cosine but this will work when I will use single frequency (w) i.e. 1.2pi.w, 2.2pi.w,3.2pi.w and so on... but here frequency is different. Now when I used the code
H=@(x0,Xdata,f)x0(1)+x0(2)*Xdata+x0(3)*cos(2*pi*f(1).*Xdata)+x0(4)...
*sin(2*pi*f(1).*Xdata)+x0(5)*cos(2*pi*f(2).*Xdata)+...
x0(6)*sin(2*pi*f(2).*Xdata)+x0(7)*cos(2*pi*f(3).*Xdata)+...
x0(8)*sin(2*pi*f(3).*Xdata);
f=[0.0139;0.1736;0.0278];
t=1:144;
t=t';
and take random set as predicting variable as
W=rand(144,1);
[P1,N1,R1,EF1,OP1,L1,J1]=lsqcurvefit(H,ones(8,1)*0.5,f,t,W);
Then I get the following error
Hope this will help you to understand the problem.
Matt J
Matt J on 16 Sep 2016
Edited: Matt J on 16 Sep 2016
I understand that you suggested me to add index 'n' in each term of sine/cosine but this will work when I will use single frequency (w) i.e. 1.2pi.w, 2.2pi.w,3.2pi.w and so on...
Nope. I didn't suggest that. I copy/pasted the expression for H directly from your posted question, except that I fixed the syntax.
Then I get the following error
See again my original answer. You cannot pass H to lsqcurvefit because H expects 3 arguments. You must wrap H in an additional anonymous function as I demonstrated.
Dear Matt, Sorry to disturb you again. But alas, I am not able to solve.I have tried to modify the syntax as you suggested as follows where i have defined a function H with argument, (x0, Xdata and f)
H=@(x0,Xdata,f)x0(1)+x0(2)*Xdata+x0(3)*cos(2*pi*f(1).*Xdata)+x0(4)...
*sin(2*pi*f(1).*Xdata)+x0(5)*cos(2*pi*f(2).*Xdata)+...
x0(6)*sin(2*pi*f(2).*Xdata)+x0(7)*cos(2*pi*f(3).*Xdata)+...
x0(8)*sin(2*pi*f(3).*Xdata);
x0 is 8x1 column vector which initialize the parameter which i need to estimate, xData=1:144, EWH=rand(144,1) while f=[0.0139;0.1736;0.0278];
Now Please suggest me how can I wrap H in another fuction and then pass it to lsqcurvefit which you have suggested. i was doing like you suggested.
[P1,N1,R1,EF1,OP1,L1,J1]=lsqcurvefit(@(x0,Xdata)...
H(x0,Xdata,f),ones(8,1)*0.5,f,t,EWH);
Can you tell me where i am doing wrong. it would be nice if you solve by some random example.
Error Msg
Thanks in advance
Matt J
Matt J on 17 Sep 2016
Edited: Matt J on 18 Sep 2016
I get the feeling you're just putting the lsqcurvefit input arguments in the wrong places. Earlier you said 't' is the independent variable, but here you've called lsqcurvefit with t as the dependent variable. Also, you are now telling lsqcurvefit that 'f' is the independent variable, whereas earlier, you said it was just a set of 3 frequency parameters.
If you look at the documentation, you are calling lsqcurvefit with the 5-argument syntax,
x = lsqcurvefit(fun,x0,xdata,ydata,lb)
and so lsqcurvefit is making the associations,
fun= @(x0,Xdata) H(x0,Xdata,f); %model function
x0= ones(8,1)*0.5; %initial parameter guess
xdata = f; ydata = t; %data to be fit
lb=EWH; %lower bounds
lsqcurvefit is iteratively evaluating H(x0,Xdata,f) for different parameter choices and comparing the result element-wise to the 4th input argument, ydata=t. The error message is complaining that H(x0,Xdata,f) does not return an array the same size as ydata=t making the comparison impossible.
There is also a warning saying that the lower bound vector EWH is shorter in length than x0= ones(8,1)*0.5. In other words, you haven't specified a bound on all 8 of your unknown parameters. Therefore, lsqcurvefit is going to assume you want no bounds on all x0(i), i>length(EWH).

Sign in to comment.

Asked:

on 15 Sep 2016

Edited:

on 18 Sep 2016

Community Treasure Hunt

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

Start Hunting!