3 views (last 30 days)
Show older comments
Jinglei on 2 Feb 2023
Edited: Walter Roberson on 6 Feb 2023
Accepted Answer: Walter Roberson
Open in MATLAB Online
x=[0 1 2 3 4 5 6 7 8 9 10]
x = 1×11
0 1 2 3 4 5 6 7 8 9 10
xs = 0:0.01:120;
y=[0 4 9 16 25 36 49 64 81 100 121]
y = 1×11
0 4 9 16 25 36 49 64 81 100 121
myfunc=@fitting;
rng('shuffle');
best_r = inf;
best_p = [-inf, -inf];
best_c = [-inf];
a=0.00001;
b=3;
d=2;
for iters = 1 : 100
p0 = a+(b-a).*rand(1,2);
c0 = a+(d-a).*rand(1,1);
ytotal0 = fitting(p0,c0,xs);
try
[p, c, r] =nlinfit(x,y,myfunc,p0,c0);
if any(p < 0), or (c < 0)
fprintf('rejected negative output on iteration %d\n', iters);
continue;
end
if any(norm(r)==best_r)
continue;
end
nr = norm(r);
if nr < best_r
fprintf('improved on iteration %d\n', iters);
best_r = nr;
best_p = p;
best_c = c;
end
catch ME
fprintf('failed iteration %d\n', iters);
end
end
failed iteration 1failed iteration 2failed iteration 3failed iteration 4failed iteration 5failed iteration 6failed iteration 7failed iteration 8failed iteration 9failed iteration 10failed iteration 11failed iteration 12failed iteration 13failed iteration 14failed iteration 15failed iteration 16failed iteration 17failed iteration 18failed iteration 19failed iteration 20failed iteration 21failed iteration 22failed iteration 23failed iteration 24failed iteration 25failed iteration 26failed iteration 27failed iteration 28failed iteration 29failed iteration 30failed iteration 31failed iteration 32failed iteration 33failed iteration 34failed iteration 35failed iteration 36failed iteration 37failed iteration 38failed iteration 39failed iteration 40failed iteration 41failed iteration 42failed iteration 43failed iteration 44failed iteration 45failed iteration 46failed iteration 47failed iteration 48failed iteration 49failed iteration 50failed iteration 51failed iteration 52failed iteration 53failed iteration 54failed iteration 55failed iteration 56failed iteration 57failed iteration 58failed iteration 59failed iteration 60failed iteration 61failed iteration 62failed iteration 63failed iteration 64failed iteration 65failed iteration 66failed iteration 67failed iteration 68failed iteration 69failed iteration 70failed iteration 71failed iteration 72failed iteration 73failed iteration 74failed iteration 75failed iteration 76failed iteration 77failed iteration 78failed iteration 79failed iteration 80failed iteration 81failed iteration 82failed iteration 83failed iteration 84failed iteration 85failed iteration 86failed iteration 87failed iteration 88failed iteration 89failed iteration 90failed iteration 91failed iteration 92failed iteration 93failed iteration 94failed iteration 95failed iteration 96failed iteration 97failed iteration 98failed iteration 99failed iteration 100
c = best_c
c = -Inf
p = best_p
p = 1×2
-Inf -Inf
%c = lsqcurvefit(myfunc,c0,x,y)
ytotal = fitting(p,c,x);
Warning: Failure at t=0.000000e+00. Unable to meet integration tolerances without reducing the step size below the smallest value allowed (7.905050e-323) at time t.
%for adding points
hold on
plot(x,y,'o', 'displayname', 'original')
hold off
xlim auto
ylim auto
legend show
%for adding points
hold on
xs = 0:0.1:150;
ytotal = fitting(p,c,xs);
Warning: Failure at t=0.000000e+00. Unable to meet integration tolerances without reducing the step size below the smallest value allowed (7.905050e-323) at time t.
plot(xs,ytotal)
hold off
R2=1-(sum((fitting(p,c,x)-y).^2)/sum((y-mean(y)).^2));
Warning: Failure at t=0.000000e+00. Unable to meet integration tolerances without reducing the step size below the smallest value allowed (7.905050e-323) at time t.
function ytotal = fitting(p,c,x)
xspan = x;
y0 = zeros(2,1);
[t,ye] = ode15s(@(x,y)eq2(x,y,p,c), xspan, y0);
%protect against failure of integration
if t(end) ~= xspan(end)
ytotal = inf(numel(xspan),1);
else
ytotal = ye(:,1)+ye(:,2)+c(1);
end
end
function dy=eq2(x,y,p,c)
%y(1)=CE,y(2)=LE
dy=zeros(2,1);
dy(1) = p(1) .* x;
dy(2) = p(2);
end
0 Comments Show -2 older commentsHide -2 older comments
Show -2 older commentsHide -2 older comments
Sign in to comment.
Sign in to answer this question.
Accepted Answer
Walter Roberson on 5 Feb 2023
Edited: Walter Roberson on 5 Feb 2023
Open in MATLAB Online
I had to fix every different things to get it to work.
The improvement to summarize failed iterations instead of listing each one was cosmetic, not strictly required. It took a while before the iterations started working properly and I was tired of the long stream of fail messages.
x=[0 1 2 3 4 5 6 7 8 9 10]
x = 1×11
0 1 2 3 4 5 6 7 8 9 10
xs = 0:0.01:120;
y=[0 4 9 16 25 36 49 64 81 100 121]
y = 1×11
0 4 9 16 25 36 49 64 81 100 121
rng('shuffle');
best_r = inf;
best_p = [-inf, -inf];
best_c = [-inf];
a=0.00001;
b=3;
d=2;
arefailing = false;
firstfail = -inf;
currentfail = -inf;
for iters = 1 : 100
p0 = a+(b-a).*rand(1,2);
c0 = a+(d-a).*rand(1,1);
ytotal0 = fitting(p0,c0,xs);
try
[pc, r] = nlinfit(x,y(:),@(pc,x)fitting(pc(1:2),pc(3),x),[p0,c0]);
%with the try/catch we never reach this statement if the nlfit
%succeeded, so the fact we got here means that an iteration worked
%(but might have returned values we do not want.)
if arefailing
fprintf('failed iterations %d to %d\n', firstfail, currentfail);
arefailing = false;
end
p = pc(1:2); c = pc(3);
if any(p < 0), or (c < 0)
fprintf('rejected negative output on iteration %d\n', iters);
continue;
else
end
if any(norm(r)==best_r)
continue;
end
nr = norm(r);
if nr < best_r
fprintf('improved on iteration %d\n', iters);
best_r = nr;
best_p = p;
best_c = c;
end
catch ME
if arefailing
currentfail = iters;
else
arefailing = true;
firstfail = iters;
currentfail = iters;
disp(ME)
if ~isempty(ME.cause); disp(ME.cause{1}); end
end
end
end
improved on iteration 1improved on iteration 4improved on iteration 19
if arefailing
fprintf('failed iterations %d to %d\n', firstfail, currentfail);
if firstfail == 1 %everything failed
fprintf('failed all iterations!!! Not doing any plotting\n');
else
arefailing = false; %we got at least one valid iteration
end
end
if ~arefailing
c = best_c
p = best_p
%c = lsqcurvefit(myfunc,c0,x,y)
ytotal = fitting(p,c,x);
%for adding points
hold on
plot(x,y,'o', 'displayname', 'original')
hold off
xlim auto
ylim auto
legend show
%for adding points
hold on
xs = 0:0.1:150;
ytotal = fitting(p,c,xs);
plot(xs,ytotal)
hold off
R2=1-(sum((fitting(p,c,x)-y).^2)/sum((y-mean(y)).^2));
end
c = 0.4196
p = 1×2
1.9650 2.2203
function ytotal = fitting(p,c,x)
xspan = x;
y0 = zeros(2,1);
[t,ye] = ode15s(@(x,y)eq2(x,y,p,c), xspan, y0);
%protect against failure of integration
if t(end) ~= xspan(end)
ytotal = inf(numel(xspan),1);
else
ytotal = ye(:,1)+ye(:,2)+c;
end
end
function dy=eq2(x,y,p,c)
%y(1)=CE,y(2)=LE
dy=zeros(2,1);
dy(1) = p(1) .* x;
dy(2) = p(2);
end
6 Comments Show 4 older commentsHide 4 older comments
Show 4 older commentsHide 4 older comments
Jinglei on 5 Feb 2023
Direct link to this comment
https://support.mathworks.com/matlabcentral/answers/1905446-i-am-confused-about-why-my-code-doesn-t-lead-to-a-fitting-result#comment_2600250
Thank you for your help but the fitting was still a failure with no fitting curve obtained.
Walter Roberson on 6 Feb 2023
Direct link to this comment
https://support.mathworks.com/matlabcentral/answers/1905446-i-am-confused-about-why-my-code-doesn-t-lead-to-a-fitting-result#comment_2600405
original x are 0 to 10. The plot for them is the blue lower left. The rest of the plot is extrapolation to 120, your xs
Jinglei on 6 Feb 2023
Direct link to this comment
https://support.mathworks.com/matlabcentral/answers/1905446-i-am-confused-about-why-my-code-doesn-t-lead-to-a-fitting-result#comment_2601340
Edited: Jinglei on 6 Feb 2023
That's right. And I tried changing the range of xs to (0,10), which, however, led to the same fitting result. In addition, when I tried the same code for more parameters (eight for p and two for c, that is, p=pc(1:8), c=pc(9:10), and of course, for a different model), it didn't come to any result again. In fact, it got stuck in the middle this time, running forever without stopping manually. Do you know what was wrong?Is it caused by to many parameters or any errors in the running process?
Walter Roberson on 6 Feb 2023
Direct link to this comment
https://support.mathworks.com/matlabcentral/answers/1905446-i-am-confused-about-why-my-code-doesn-t-lead-to-a-fitting-result#comment_2601450
You do not fit against xs, only against x. xs is used only to display the final plot.
Walter Roberson on 6 Feb 2023
Direct link to this comment
https://support.mathworks.com/matlabcentral/answers/1905446-i-am-confused-about-why-my-code-doesn-t-lead-to-a-fitting-result#comment_2601470
In fact, it got stuck in the middle this time, running forever without stopping manually. Do you know what was wrong?
No. I do not know what is wrong with code that I have not seen.
Jinglei on 6 Feb 2023
Direct link to this comment
https://support.mathworks.com/matlabcentral/answers/1905446-i-am-confused-about-why-my-code-doesn-t-lead-to-a-fitting-result#comment_2601695
Edited: Walter Roberson on 6 Feb 2023
Open in MATLAB Online
The code can be seen as below.
x = [0
5
10
15
20
25
30
35
40
45
50
55
60
65
70
80
90
100
110
120
];
xs = 0:0.01:120;
y = [0
1.415699757
1.044160175
1.342848859
1.357419038
1.138866343
1.386559398
1.452125206
1.430269937
1.153436523
1.26271287
1.408414667
1.357419038
1.430269937
1.095155804
1.488550656
1.503120835
1.386559398
1.401129577
1.532261195
];
rng('shuffle');
best_r = inf;
best_p = [-inf, -inf,-inf,-inf,-inf,-inf,-inf,-inf];
best_c = [-inf,-inf];
a=0.00001;
b=1;
d=2;
arefailing = false;
firstfail = -inf;
currentfail = -inf;
for iters = 1 : 100
p0 = a+(b-a).*rand(1,8);
c0 = a+(d-a).*rand(1,2);
ytotal0 = fitting(p0,c0,xs);
try
[pc, r] = nlinfit(x,y(:),@(pc,x)fitting(pc(1:8),pc(9:10),x),[p0,c0]);
%with the try/catch we never reach this statement if the nlfit
%succeeded, so the fact we got here means that an iteration worked
%(but might have returned values we do not want.)
if arefailing
fprintf('failed iterations %d to %d\n', firstfail, currentfail);
arefailing = false;
end
p = pc(1:8); c = pc(9:10);
if any(p < 0), or (c < 0)
fprintf('rejected negative output on iteration %d\n', iters);
continue;
else
end
if any(norm(r)==best_r)
continue;
end
nr = norm(r);
if nr < best_r
fprintf('improved on iteration %d\n', iters);
best_r = nr;
best_p = p;
best_c = c;
end
catch ME
if arefailing
currentfail = iters;
else
arefailing = true;
firstfail = iters;
currentfail = iters;
disp(ME)
if ~isempty(ME.cause); disp(ME.cause{1}); end
end
end
end
if arefailing
fprintf('failed iterations %d to %d\n', firstfail, currentfail);
if firstfail == 1 %everything failed
fprintf('failed all iterations!!! Not doing any plotting\n');
else
arefailing = false; %we got at least one valid iteration
end
end
if ~arefailing
c = best_c
p = best_p
%c = lsqcurvefit(myfunc,c0,x,y)
ytotal = fitting(p,c,x);
%for adding points
hold on
plot(x,y,'o', 'displayname', 'original')
hold off
xlim auto
ylim auto
legend show
%for adding points
hold on
xs = 0:0.1:150;
ytotal = fitting(p,c,xs);
plot(xs,ytotal)
hold off
R2=1-(sum((fitting(p,c,x)-y).^2)/sum((y-mean(y)).^2));
end
function ytotal = fitting(p,c,x)
xspan = x;
y0 = zeros(4,1);
[t,ye] = ode15s(@(x,y)eq2(x,y,p,c), xspan, y0);
%protect against failure of integration
if t(end) ~= xspan(end)
ytotal = inf(numel(xspan),1);
else
ytotal = ye(:,1)+ye(:,2)+ye(:,3)+ye(:,4);
end
end
function dy=eq2(x,y,p,c)
%y(1)=CE,y(2)=LE
dy=zeros(4,1);
dy(1) = p(1) .* (2.5 - y(1)-y(2)-y(3)-y(4)) .* (c(1)-y(1)-y(2)-y(4)) - p(2) .* y(1);
dy(2) = p(3) .* y(1)-p(4).*y(2);
dy(3) = p(5).*(2.5-y(1)-y(2)-y(3)-y(4)).*(c(2)-y(3)-y(4))-p(6).*y(3);
dy(4) = p(7).*y(3).*(c(2)-y(1)-y(2)-y(4))-p(8).*y(4);
end
Sign in to comment.
More Answers (1)
Bora Eryilmaz on 2 Feb 2023
Open in MATLAB Online
If you print out the exception inside the catch block, it will tell you what the error is.
catch ME
ME
fprintf('failed iteration %d\n', iters);
To start with, you are not passing the right number of arguments to the fitting() function: it would be passed two arguments from nlinfit, but your code expects three input arguments.
6 Comments Show 4 older commentsHide 4 older comments
Show 4 older commentsHide 4 older comments
Jinglei on 3 Feb 2023
Direct link to this comment
https://support.mathworks.com/matlabcentral/answers/1905446-i-am-confused-about-why-my-code-doesn-t-lead-to-a-fitting-result#comment_2597026
Thank you for your reply.
Firstly, I think those warnings were caused by the range of parameters I used, in which I gave the initial values as inf. I tried exact values instead and the warnings didn't appear. However, this doesn't help for the fitting. At the same time, I have found that the final values for all parameters are the same as the initially given ones (c_best, p_best, and r_best). In other words, those 'if' codes are not runned, which is the real problem.
In addition, as for the number of arguments you mentioned, I am not sure which three arguments you were talking about. If the third one is r, then I don't think it matters since it is not related to the fitting process but just the deviation to get the optimal simulation.
Bora Eryilmaz on 3 Feb 2023
Direct link to this comment
https://support.mathworks.com/matlabcentral/answers/1905446-i-am-confused-about-why-my-code-doesn-t-lead-to-a-fitting-result#comment_2597226
Edited: Bora Eryilmaz on 3 Feb 2023
You function fitting() takes three input arguments, p, c, and x. However, I think nlinfit will call that function with only two arguments.
Also, please read the documentation for nlinfit: https://www.mathworks.com/help/stats/nlinfit.html. Among other things, nlinfit does not return the estimated coefficients individually; it returns them together as a vector.
Finally, using Inf as initial guesses of parameters does not sound right; initial parameters are supposed to be at reasonable, ballpark values.
Jinglei on 3 Feb 2023
Direct link to this comment
https://support.mathworks.com/matlabcentral/answers/1905446-i-am-confused-about-why-my-code-doesn-t-lead-to-a-fitting-result#comment_2597855
Edited: Jinglei on 3 Feb 2023
Thank you for your reply.
Firstly, I think what you meant is that the nlinfit can only simulate two arguments including x, that is, only one parameter could be included, c or p. However, this doesn't work for my situation, even if I combined c and p together to be one, still, no fitting result could be achieved.
In addition, with the 'if' codes not running, c and p will be the initial values given instead of that obtained after the for codes. This means running nlinfit correctly or not would not matter since p and c will be assigned as p_best and c_best as intially given. Therefore, I would like to know what makes 'if' codes not working.
Further, it is strange that each run of the "for" code gave falure (100 falures as can be seen) in the runing process and I would like to know how to fix that.
Walter Roberson on 3 Feb 2023
Direct link to this comment
https://support.mathworks.com/matlabcentral/answers/1905446-i-am-confused-about-why-my-code-doesn-t-lead-to-a-fitting-result#comment_2597920
Open in MATLAB Online
For the case where you are passing in fixed values (for example a table of oxygen absorption) then see http://www.mathworks.com/help/matlab/math/parameterizing-functions.html for how to construct a function handle that the function would be happy with.
The objective function you pass to nlinfit must expect exactly two parameters: the vector of proposed coefficients, and the set of X values that the proposed parameters are to be applied to. If you have a model in which you are wanting more than one model variable to be altered, then put all of the model variables into a vector. For example if you have a model in parameters c and p and you want nlinfit to alter both of those, then create
function y = fitting(cp, x)
c = cp(1);
p = cp(2);
y = appropriate expression
end
Jinglei on 5 Feb 2023
Direct link to this comment
https://support.mathworks.com/matlabcentral/answers/1905446-i-am-confused-about-why-my-code-doesn-t-lead-to-a-fitting-result#comment_2600015
Thank you for your suggestion. However, in this case, c and p are taken as un-defined parameters by Matlab. And I am confused how to fix that. Could you show me that?
Jinglei on 6 Feb 2023
Direct link to this comment
https://support.mathworks.com/matlabcentral/answers/1905446-i-am-confused-about-why-my-code-doesn-t-lead-to-a-fitting-result#comment_2600370
Thank you for your help and it does work this time. The only problem is the obtained parameters to some extent away from the optimal ones, which may not be a big problem for my data. Thank you for your patience.
Sign in to comment.
Sign in to answer this question.
See Also
Categories
AI, Data Science, and StatisticsCurve Fitting ToolboxSmoothing
Find more on Smoothing in Help Center and File Exchange
Tags
- no curves were achieved.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!
An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- Deutsch
- English
- Français
- United Kingdom(English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)
Contact your local office