I am confused about why my code doesn't lead to a fitting result.
Show older comments
x=[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]
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
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));
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
Accepted Answer
More Answers (1)
Bora Eryilmaz
on 2 Feb 2023
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
Jinglei
on 3 Feb 2023
Bora Eryilmaz
on 3 Feb 2023
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.
Walter Roberson
on 3 Feb 2023
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
Jinglei
on 6 Feb 2023
Categories
Find more on Calendar in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!
