MATLAB Answers

0

LSQCURVEFIT Error When Trying To Optimize Parameters

Asked by Kelly McGuire on 1 Feb 2019
Latest activity Answered by Kelly McGuire on 2 Feb 2019
I am trying to optimize 5 parameters using lsqcurvefite. I keep getting "Array indices must be positive integers or logical values". "Error in @(c,xdata) c(0)+c(1)..." line. I know my two vectors/data (VarName1 and VarName2 attached) are not positive integers, but that is my data for which I am trying obtain c0, c1, c2, c3, and c4 so that I can then fit my data with the best curve. How can I do nonlinear least squares fitting when most data will not be integers and not necessarily positive?
xdata = VarName1;
ydata = VarName2;
predicted = @(c,xdata) c(0) + c(1)*cos(xdata) + c(2)*cos(xdata) + c(3)*cos(xdata) + c(4)*cos(xdata);
c0 = [-276.8401; -0.01386; 0.007231; 0.011035; 0.001128];
[ahat,resnorm,residual,exitflag,output,lambda,jacobian] = ...
lsqcurvefit(predicted,c0,xdata,ydata);

  1 Comment

Here is the working code. However, I am NOT getting values that fit the data close to a good fit. Any suggestions?
theta = VarName1(:,1);
y = VarName2(:,1);
plot(theta,y,'bo')
xdata = VarName1;
ydata = VarName2;
lb = [-276.9; -1; -1; -1; -1];
ub = [-276.8; 1; 1; 1; 1];
predicted = @(c,xdata) c(1) + c(2)*cos(xdata) + c(3)*(cos(xdata)).^2 + c(4)*(cos(xdata)).^3 + c(5)*(cos(xdata)).^4;
c0 = [-276.838; -0.00656; 0.005231; 0.016035; 0.001128];
[c,resnorm,residual,exitflag,output,lambda,jacobian] = ...
lsqcurvefit(predicted,c0,xdata,ydata,lb,ub);
hold on
plot(xdata,predicted(c,xdata),'r-','markersize',20)
hold off

Sign in to comment.

2 Answers

Answer by Kelly McGuire on 2 Feb 2019
 Accepted Answer

Ok, here is the working code. Apparently, I needed to convert degrees to radians for this least squares computation on the cosines to work properly.
Angles = -180:20:180;
Angles = Angles';
Radians = (pi/180).*Angles;
theta = Radians(:,1);
y = VarName2(:,1);
plot(theta,y,'bo')
xdata = VarName1.*(pi/180);
ydata = VarName2;
lb = [-277; -100; -100; -100; -100];
ub = [-276.83; 100; 100; 100; 100];
predicted = @(c,xdata) c(1) + c(2)*cos(xdata) + c(3)*(cos(xdata)).^2 + c(4)*(cos(xdata)).^3 + c(5)*(cos(xdata)).^4;
c0 = [-276; -5; 5; 2; 1];
[c,resnorm,residual,exitflag,output] = ...
lsqcurvefit(predicted,c0,xdata,ydata,lb,ub);
hold on
plot(xdata,predicted(c,xdata),'r-','markersize',20)
hold off

  0 Comments

Sign in to comment.


Answer by Alan Weiss
on 1 Feb 2019

I think that you probably made a gross modeling error, because your predicted function is the same as
predicted = @(c,xdata) c(1) + (c(2) + c(3) + c(4) + c(5))*cos(xdata);
which makes it clear that you are really fitting to
predicted = @(c,xdata) c(1) + c(2)*cos(xdata);
In other words, you are trying to fit four parameters that are indistinguishable from one parameter.
I would guess (but don't know) that you meant
predicted = @(c,xdata) c(0) + cos(c(1)*xdata) + cos(c(2)*xdata) + cos(c(3)*xdata) + cos(c(4)*xdata);
or maybe
predicted = @(c,xdata) c(0) + c(5)*cos(c(1)*xdata) + c(6)*cos(c(2)*xdata) + c(7)*cos(c(3)*xdata) + c(8)*cos(c(4)*xdata);
One more thing: the problem as your wrote it is linear in the c variables, and if you keep it linear in those variables, then you should use a linear solver (backslash or lsqlin) instead of a nonlinear solver.
Alan Weiss
MATLAB mathematical toolbox documentation

  1 Comment

I am trying to use this function: with n=4. I don't know what happened during copy and paste, but that wasn't the correct equation. Also, I tried lsqlin, but I get "too many ouput arguments" error. I typed c in the command window, and it gave values for c, but plugging them into the equation still doesn't give a good fit. This is what my code above should have had (it's corrected above):
predicted = @(c,xdata) c(1) + c(2)*cos(xdata) + c(3)*(cos(xdata)).^2 + c(4)*(cos(xdata)).^3 + c(5)*(cos(xdata)).^4;

Sign in to comment.