optimization data fitting error

I want find a model fit for a set of data. I'm just adapting the example code for my model, and there is just one line (my model equation) which is causing an error. Please could somebody tell me what about this line needs adjusting?
The error message:
"Error using lsqcurvefit (line 251)
Function value and YDATA sizes are not equal.
Error in curvefittingpractice2 (line 39)
[x,resnorm,~,exitflag,output] = lsqcurvefit(F,x0,t,y)"
Code:
Data = ...
[0.0000 5.8955
0.1000 3.5639
0.2000 2.5173
0.3000 1.9790
0.4000 1.8990
0.5000 1.3938
0.6000 1.1359
0.7000 1.0096
0.8000 1.0343
0.9000 0.8435
1.0000 0.6856
1.1000 0.6100
1.2000 0.5392
1.3000 0.3946
1.4000 0.3903
1.5000 0.5474
1.6000 0.3459
1.7000 0.1370
1.8000 0.2211
1.9000 0.1704
2.0000 0.2636];
plot(t,y,'ro')
title('Data points')
%F = @(x,xdata)x(1)*exp(-x(2)*xdata); --for this I get no error, for the
%following line I get an error message
F = @(x,xdata)x(1)*exp(x(2)/xdata).^x(3);
x0 = [1 1 1 0];
[x,resnorm,~,exitflag,output] = lsqcurvefit(F,x0,t,y)
hold on
plot(t,F(x,t))
hold off

3 Comments

Hi, Em, in your function: F = @(x,xdata)x(1)*exp(x(2)/xdata).^x(3);
note the part: x(2)/xdata, the first data value for xdata is 0, so this will cause a math logical error (divided by zero)
... as I wrote two hours earlier.
Thanks to you both for your help! Unfortunately, I'm still getting error messages - just posted on the comment below.

Sign in to comment.

 Accepted Answer

For the second ‘F’, as written, returns a row vector rather than a column vector. The solution is to use element-wise division:
F = @(x,xdata)x(1)*exp(x(2)./xdata).^x(3);
(The first ‘F’ returns a column vector as written, so no problem.)
However the other problem is that the second ‘F’ produces an infinite result with the first value of ‘t’, since it is 0. One possible way to address that is to eliminate the first row of ‘Data’, however the fit is inferior to the first ‘F’ with the full data set.
I would go with the first ‘F’ and be done with it.

12 Comments

Thanks for your answer! I've just replaced the line in my code with your line - and then also deleted the first data point. In both instances I am now getting the following error message:
Error using snls (line 47)
Objective function is returning undefined values at initial point. lsqcurvefit cannot continue.
Error in lsqncommon (line 166)
snls(funfcn,xC,lb,ub,flags.verbosity,options,defaultopt,initVals.F,initVals.J,caller, ...
Error in lsqcurvefit (line 257)
lsqncommon(funfcn,xCurrent,lb,ub,options,defaultopt,caller,...
Error in curvefittingpractice2 (line 36)
[x,resnorm,~,exitflag,output] = lsqcurvefit(F,x0,t,y)
If you use the first ‘F’, there should be no problems. The problems occur with the second ‘F’.
Sorry for the confusion, the first F which I commented out is from the example - I am trying to fit a different model to the data which is the one in the line you quoted. I just let that first commented out F in to show how the code works fine without this particular similar line.
The problem is the division-by-zero. There is no way to get around that.
The fit is much better for the first ‘F’ with a y-offset parameter:
F = @(x,xdata)x(1)*exp(-x(2)*xdata) + x(3);
A better fit is likely not possible without a mathematical model of the process that created those data. If available, it would be best to use it for the objective function.
Thanks for your answer. Actually my goal is to fit the equation
F = @(x,xdata)x(1)*exp(x(2)/xdata).^x(3) to a number of datasets and find the parameter values x(1), x(2) and x(3) which carry some physical significance to my experiment. My initial code wasn't working so I started with the example code found here so I could make incremental changes and figure what is wrong with my code (https://uk.mathworks.com/help/optim/ug/nonlinear-data-fitting-example.html). You're right the division is what's causing problems, I can't understand when I have no zero values in my data why this division is still not working though (I removed the zero value from this code I posted). I think this means that my understanding is too simplistic... could you explain why even with data that doesn't contain any zeros that this division component is giving such an error?
My pleasure!
I came up with a ‘sort of’ solution that avoids the divide-by-zero problem by using a logic test to substitute a suitably small number for 0 in the independent variable within the ‘F’ function. This is definitely not a perfect solution, however it has the advantage of producing a reasonable fit even in the presence of 0 values in the independent variable, and does not require prior editing of the data set.
Try this:
F = @(x,xdata) (x(1)*exp(x(2)./(xdata.*(xdata ~= 0)+(0.1).*(xdata==0))).^x(3));
This logic test for ‘xdata’ does the substitution only when the independent variable is 0:
(xdata.*(xdata ~= 0)+(0.1).*(xdata==0))
Experiment with it to get different results.
This works amazingly!! Thanks so much!
My pleasure!
If my Answer helped you solve your problem, please Accept it!
.
The code works perfectly for the dataset that I've posted here, but with the dataset that I actually want to use, I'm just getting a flat line! Do you have any idea why that might be? Thanks again for all your help!
t = set3{1:end,1};
y = set3{1:end,3};
plot(t,y,'ro')
title('Data points')
F = @(x,xdata) (x(1)*exp(x(2)./(xdata.*(xdata ~= 0)+(0.1).*(xdata==0))).^x(3));
x0 = [0.001 0.1 0.5];
[x,resnorm,~,exitflag,output] = lsqcurvefit(F,x0,t,y)
hold on
plot(t,F(x,t))
hold off
My code fits the original data because that was all it was designed to do.
Your model does not even begin to describe the data in that file. It is simply the wrong model, and nothing can be done to fix it. I even tried to estimate the parameters with a genetic algorithm and failed, although most of the time, the genetic algorithm can fit an appropriate model to appropriate data.
I will delete my Answer in a few hours.
Good luck with whatever it is that you're doing!
Thanks a lot for the time and effort you have put in to help me!
As always, my pleasure!

Sign in to comment.

More Answers (0)

Products

Release

R2017a

Asked:

Em
on 2 May 2020

Commented:

on 5 May 2020

Community Treasure Hunt

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

Start Hunting!