lsqcurvefit not adjusting some parameters as expected
Show older comments
I am trying to fit some data to a 3 parameter curve expressed as
.
What I am finding when using lsqcurvefit is that it converges on what appears to be good values for
and
but not for c. In fact, c remains unchanged from the guessed value, regardless of its initial value.
First I try with c = p(3) = 1000
x = 0:2047;
y = load('y.mat'); % see attachment
fun = @(p,x)abs(p(1)*(x-p(3))+p(2)*(x-p(3)).^3);
options = optimoptions(@lsqcurvefit,'StepTolerance',1e-10, 'Display', 'iter-detailed', 'FunctionTolerance', 1E-12);
pGuess = [2.5E-5 2.6E-12 1000];
[p,fminres] = lsqcurvefit(fun,pGuess,x,y, [], [], options)
Norm of First-order
Iteration Func-count f(x) step optimality
0 4 0.00635297 1.03e+08
1 8 0.00632173 3.02663e-13 99.9
2 12 0.00623569 9.85058e-05 1.13e+04
3 16 0.00623569 3.31307e-17 0.0114
Optimization stopped because the relative sum of squares (r) is changing
by less than options.FunctionTolerance = 1.000000e-12.
p =
2.58614068198555e-05 1.75916049599052e-12 1000.00009850203
fminres =
0.00623568562340633
Now I try with c = p(3) = 1400:
pGuess = [2.5E-5 2.6E-12 1400];
[p,fminres] = lsqcurvefit(fun,pGuess,x,y, [], [], options)
Norm of First-order
Iteration Func-count f(x) step optimality
0 4 0.168905 9.79e+09
1 8 0.10571 6.45539e-12 1.16e+06
2 12 0.105681 9.10932e-06 1.43e+08
3 16 0.105681 0.000231759 1.43e+08
4 20 0.105681 5.79397e-05 1.43e+08
5 24 0.105681 1.44849e-05 1.43e+08
6 28 0.105681 3.62123e-06 1.43e+08
7 32 0.105681 9.05308e-07 1.43e+08
8 36 0.105681 2.26327e-07 1.43e+08
9 40 0.105681 5.65817e-08 1.43e+08
10 44 0.105681 1.41454e-08 1.43e+08
11 48 0.105681 3.53636e-09 1.43e+08
12 52 0.105681 8.8409e-10 1.43e+08
13 56 0.105681 2.21022e-10 1.43e+08
14 60 0.105681 5.52556e-11 1.43e+08
Optimization stopped because the norm of the current step, 5.525560e-11,
is less than options.StepTolerance = 1.000000e-10.
p =
2.4936115641411e-05 -3.9025705054523e-12 1399.9999908909
fminres =
0.105680830464589
From the data set it is clear that the min occurs at x = 1066.
>> [m,k] = min(y)
m =
0.000292016392169768
k =
1067
>> x(k)
ans =
1066
3 Comments
Walter Roberson
on 26 Jul 2019
Could you attach y.mat ?
Leor Greenberger
on 26 Jul 2019
Walter Roberson
on 27 Jul 2019
Your function would benefit from a constraint.
fun = @(p,x)abs(p(1)*(x-p(3))+p(2)*(x-p(3)).^3);
if you feed in -p(1) and -p(2) then you the result will have the same abs() as original p(1) and p(2) . Therefore you can constrain one of the values, such as p(1) to be >= 0, which will reduce searching.
Accepted Answer
More Answers (1)
Alex Sha
on 22 Feb 2020
The best solution seems to be:
Root of Mean Square Error (RMSE): 8.58712889537096E-5
Sum of Squared Residual: 1.50943288116718E-5
Correlation Coef. (R): 0.999947601349384
R-Square: 0.999895205444387
Adjusted R-Square: 0.999895102905683
Determination Coef. (DC): 0.99989229572485
Chi-Square: 0.00435400203642259
F-Statistic: 9515701.1004098
Parameter Best Estimate
---------- -------------
p1 -2.54821313582336E-5
p2 -2.52958254532916E-12
p3 1062.58024839597
Categories
Find more on Get Started with Curve Fitting Toolbox 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!