How to supply user gradient in simultaneous fitting with lsqcurvefit
2 views (last 30 days)
Show older comments
xdata={[1 3 5 7]' [5 7 9 11]' [9 11 13 15]'};
y={[10 11 12 13]' [10 11 12 13]' [10 11 13]'};
yy = vertcat(y{:});
%variables v(1:4) are m, c1, c2, c3
fn = @(v,xdata) [v(1).*xdata{1} + v(2); v(1).*xdata{2} + v(3); v(1).*xdata{3} + v(4)];
x0 = [1; 10; 9; 8];
fitvars = lsqcurvefit(fn,x0,xdata,yy);
Based on the above code snippet example is there any way that we can tell lsqcurvefit to use user supplied gradients for each function?
0 Comments
Answers (2)
John D'Errico
on 21 Jan 2019
Edited: John D'Errico
on 21 Jan 2019
This problem is linear in the parameters. Supplying the gradient is a waste of time. In fact, using lsqcurvefit is a waste of time too, since you could solve the problem using backslash.
But since lsqcurvefit will differentiate the problem itself, and since the derivatives of a linear function are rather trivial to estimate exactly, lsqcurvefit will work adequately well. Just far more slowly than you could have done it using backslash.
If you want to supply the gradients for some reason, like you think lsqcurvefit is not doing sufficiently well, don't bother. If you think it too slow, then you need to learn to formulate the problem for solution using backslash. The funny thing is, that the gradient that you wanted to learn to supply to lsqcurvefit is the same array that you need to generate to use backslash.
As far as actually writing any code, I would point out that you have 11 values in xdata, and 12 in y. So nothing you do will really work here.
3 Comments
John D'Errico
on 21 Jan 2019
It is often true that analytical gradients do not improve either speed OR accuracy. People seem to deceive themselves into thinking this will be an improvement, yet it rarely really helps. Very often, the gradient computation itself takes more time to compute than multiple calls to the objective, so there is little speed gain. As well, tiny errors in the gradient from a well chosen finite difference approximation, as long as they do not result in a non-descent direction, are not a problem.
The error of too many output arguments is something I cannot resolve, since I do not have your code. You have not written the code so it runs porperly. The fix is to write proper code. Sorry. That may seem trite, but how can I say it better?
Torsten
on 21 Jan 2019
Edited: Torsten
on 21 Jan 2019
From the documentation:
If the Jacobian can also be computed and the Jacobian option is 'on', set by
options = optimoptions('lsqcurvefit','SpecifyObjectiveGradient',true)
then the function fun must return a second output argument with the Jacobian
value J (a matrix) at x.
By checking the value of nargout, the function can avoid computing J when fun
is called with only one output argument (in the case where the optimization
algorithm only needs the value of F but not J).
function [F,J] = myfun(x,xdata)
F = ... % objective function values at x
if nargout > 1 % two output arguments
J = ... % Jacobian of the function evaluated at x
end
If fun returns a vector (matrix) of m components and x has n elements,
where n is the number of elements of x0, the Jacobian J is an m-by-n matrix
where J(i,j) is the partial derivative of F(i) with respect to x(j).
(The Jacobian J is the transpose of the gradient of F.)
For more information, see Writing Vector and Matrix Objective Functions.
9 Comments
Torsten
on 22 Jan 2019
Edited: Torsten
on 22 Jan 2019
Pass all the information to "fun" needed to build I and J for your specific purpose.
In the case above, the call to "driver" could be e.g.
fun = @(p,xdata) driver(p,xdata(1:19,1),fun1,xdata(20:end),fun2)
which would indicate that xdata(1:19,1) is to be evaluated with fun1 (a function handle) and xdata(20:end) is to be evaluated with fun2 (maybe a different function handle).
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!