How to constrain the lower and upper bounds in lsqcurvefit?

8 次查看(过去 30 天)
Hi,
For a data set (x, y), I am trying to fit a function f(m, x) using lsqcurvefit. I write as follow:
x=xdata;
y=ydata;
fun=f(m,x);
m0=[m01; m02; m03]; %these are real numbers
lb=[0; 0; 0];
ub=[ub1; ub2; ub3]; %these are real numbers
m=lsqcurvefit(fun, m0, xdata, ydata, lb, ub);
However, sometimes it obeys the bounds and sometimes it does not while fitting. Could anyone please help me if there is any way of constraining the bounds?
Thank you very much in advance!
Kind regards,
Arun
  7 个评论
Arun Kumar Bar
Arun Kumar Bar 2019-1-2
编辑:Matt J 2019-1-2
Hi Matt,
Glad to see that you would like to chek yourself. I did not provide initially in details as the equation is a complex one. Anyway, I am providing here a small set of data, particularly where I face problem.
The rlprt is a 24x2 double, see the attached file, same is the imprt.
In the equation (see below), there are three independent parameters m1, m2 and m3.
Notably, all m(i) must be > 0;
When I fit individually (i.e. using xdata=rlprt(:, 1) and ydata=imprt(:, 1)), it results out all m(i) > 0. But when I run in loop, see bellow for the code I use, m(2) come out as negative values.
Thanks and regards,
Arun
-
--------
figure()
for i=1:2
xdata=rlprt(:, i);
ydata=imprt(:, i);
fun=@(m,xdata) ((((m(2)-m(1)).*tan(pi.*m(3)/2))/2)+((sqrt((((m(2)-m(1)).*tan(pi.*m(3)/2)).^2)-(4.*((xdata.*xdata)-(xdata.*(m(1)+m(2)))+(((m(1)+m(2)).^2)/4)-(((m(2)-m(1)).^2)/(4.*((sin(pi.*(m(3)-1)/2)).^2)))+(((m(2)-m(1)).^2).*((tan(pi.*m(3)/2)).^2)/4)))))/2));
m0=[0.45; 0.1815; 0.0735];
lb=[0; 0; 0];
ub=[2, 0.75, 0.25];
m=lsqcurvefit(fun, m0, xdata, ydata, lb, ub);
plot(xdata, ydata, 'o', 'linewidth', 1.5); hold on;
plot(xdata, fun(m, xdata), '-', 'linewidth', 1.5);
output(i, 1:3)=m(1:3, 1);
end
hold off;
--------
Matt J
Matt J 2019-1-2
编辑:Matt J 2019-1-2
I don't get negative values when I run this code. I get complex ones,
output =
0.3528 + 0.0001i -3.5428 - 1.5825i 0.2693 + 0.0047i
0.3698 + 0.0000i -0.0523 - 0.0029i 0.2063 + 0.0017i
Your function is not real-valued at certain m in the search space.

请先登录,再进行评论。

采纳的回答

Matt J
Matt J 2019-1-2
编辑:Matt J 2019-1-2
This seems to work okay,
for i=1:2
[xdata,is]=sort(realpart(:, i));
ydata=imaginarypart(is, i);
fun=@(m,xdata) ((((m(2)-m(1)).*tan(pi.*m(3)/2))/2)+((sqrt((((m(2)-m(1)).*tan(pi.*m(3)/2)).^2)-(4.*((xdata.*xdata)-(xdata.*(m(1)+m(2)))+(((m(1)+m(2)).^2)/4)-(((m(2)-m(1)).^2)/(4.*((sin(pi.*(m(3)-1)/2)).^2)))+(((m(2)-m(1)).^2).*((tan(pi.*m(3)/2)).^2)/4)))))/2));
m0=[0.45; 0.1815; 0.0735];
lb=[0; 0; 0];
ub=[2, 0.75, 0.25];
[m,resnorm,residual,exitflag,stats]=lsqcurvefit(@(m,xd) abs(fun(m,xd)), m0, xdata, ydata, lb, ub);
plot(xdata, ydata, 'o', 'linewidth', 1.5); hold on;
plot(xdata, fun(m, xdata), '-', 'linewidth', 1.5);
output(i, 1:3)=m(1:3, 1);
end
output =
0.3522 0.0000 0.1771
0.3676 0.0239 0.1444
untitled.png
  2 个评论
Arun Kumar Bar
Arun Kumar Bar 2019-1-2
Hi Matt,
Thank you very much for your efforts to reply so promptly!
Yes, these codes do work for this data set. Notably, It appears quite surprising to me now. For the data sets where I used to get -ve values of the real parts of the output m(i) using the codes I provided in my previous comment, now I get better fittings and more reliable outputs through the way you suggested. However, the data sets which give better fitting and more reliable outputs through the way I used to use, now result out very poor fitting and unrliable outputs through the way you suggested. It appears strange to me, at least at the moment. Let me see if I can figure out where it's going wrong.
Thanks a lot once again!
Kind regards,
Arun.

请先登录,再进行评论。

更多回答(0 个)

类别

Help CenterFile Exchange 中查找有关 Get Started with Curve Fitting Toolbox 的更多信息

产品


版本

R2018b

Community Treasure Hunt

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

Start Hunting!

Translated by