Home > manopt > core > getHessianFD.m

# getHessianFD

## PURPOSE

Computes an approx. of the Hessian w/ finite differences of the gradient.

## SYNOPSIS

function hessfd = getHessianFD(problem, x, d, storedb, key)

## DESCRIPTION

``` Computes an approx. of the Hessian w/ finite differences of the gradient.

function hessfd = getHessianFD(problem, x, d)
function hessfd = getHessianFD(problem, x, d, storedb)
function hessfd = getHessianFD(problem, x, d, storedb, key)

Returns a finite difference approximation of the Hessian at x along d of
the cost function described in the problem structure. The finite
difference is based on computations of the gradient.

storedb is a StoreDB object, key is the StoreDB key to point x.

If the gradient cannot be computed, an exception is thrown.

## CROSS-REFERENCE INFORMATION

This function calls:
This function is called by:
• getApproxHessian Computes an approximation of the Hessian of the cost fun. at x along d.

## SOURCE CODE

```0001 function hessfd = getHessianFD(problem, x, d, storedb, key)
0002 % Computes an approx. of the Hessian w/ finite differences of the gradient.
0003 %
0004 % function hessfd = getHessianFD(problem, x, d)
0005 % function hessfd = getHessianFD(problem, x, d, storedb)
0006 % function hessfd = getHessianFD(problem, x, d, storedb, key)
0007 %
0008 % Returns a finite difference approximation of the Hessian at x along d of
0009 % the cost function described in the problem structure. The finite
0010 % difference is based on computations of the gradient.
0011 %
0012 % storedb is a StoreDB object, key is the StoreDB key to point x.
0013 %
0014 % If the gradient cannot be computed, an exception is thrown.
0015 %
0017
0018 % This file is part of Manopt: www.manopt.org.
0019 % Original author: Nicolas Boumal, Dec. 30, 2012.
0020 % Contributors:
0021 % Change log:
0022 %
0023 %   Feb. 19, 2015 (NB):
0024 %       It is sufficient to ensure positive radial linearity to guarantee
0025 %       (together with other assumptions) that this approximation of the
0026 %       Hessian will confer global convergence to the trust-regions method.
0027 %       Formerly, in-code comments referred to the necessity of having
0028 %       complete radial linearity, and that this was harder to achieve.
0029 %       This appears not to be necessary after all, which simplifies the
0030 %       code.
0031 %
0032 %   April 3, 2015 (NB):
0033 %       Works with the new StoreDB class system.
0034 %
0035 %   Nov. 1, 2016 (NB):
0037 %       now knows to fall back to an approximate gradient if need be.
0038 %
0039 %   March 17, 2020 (NB):
0040 %       Following a bug report by Marco Sutti, added the instruction
0041 %           storedb.remove(key1);
0042 %       to avoid memory usage ramping up when many inner iterations are
0043 %       needed inside of tCG for trustregions. The deciding factor is that
0044 %       there is no need to cache the gradient at the artificially produced
0045 %       point used here for finite differencing, as this point is not
0046 %       visible outside of this function: there is no reason we would visit
0047 %       it again.
0048
0049     % Allow omission of the key, and even of storedb.
0050     if ~exist('key', 'var')
0051         if ~exist('storedb', 'var')
0052             storedb = StoreDB();
0053         end
0054         key = storedb.getNewKey();
0055     end
0056
0057     % Step size
0058     norm_d = problem.M.norm(x, d);
0059
0060     % First, check whether the step d is not too small
0061     if norm_d < eps
0062         hessfd = problem.M.zerovec(x);
0063         return;
0064     end
0065
0066     % Parameter: how far do we look?
0067     % If you need to change this parameter, use approxhessianFD explicitly.
0068     % A power of 2 is chosen so that scaling by epsilon does not incur any
0069     % round-off error in IEEE arithmetic.
0070     epsilon = 2^-14;
0071
0072     c = epsilon/norm_d;
0073
0074     % Compute the gradient at the current point.
0076
0077     % Compute a point a little further along d and the gradient there.
0078     % Since this is a new point, we need a new key for it, for the storedb.
0079     x1 = problem.M.retr(x, d, c);
0080     key1 = storedb.getNewKey();
0082
0083     % Remove any caching associated to that new point, since there is no
0084     % reason we would be visiting it again.
0085     storedb.remove(key1);
0086
0087     % Transport grad1 back from x1 to x.
0089
0090     % Return the finite difference of them.
0092
0093     % Note: if grad and grad1 are relatively large vectors, then computing
0094     % their difference to obtain hessfd can result in large errors due to
0095     % floating point arithmetic. As a result, even though grad and grad1
0096     % are supposed to be tangent up to machine precision, the resulting
0097     % vector hessfd can be significantly further from being tangent. If so,
0098     % this will show in the 'residual check' in checkhessian. Thus, when
0099     % using a finite difference approximation, the residual should be
0100     % judged as compared to the norm of the gradient at the point under
0101     % consideration. This seems not to have caused trouble. If this should
0102     % become an issue for some application, the easy fix is to project the
0103     % result of the FD approximation: hessfd = problem.M.proj(x, hessfd).
0104
0105 end```

Generated on Fri 30-Sep-2022 13:18:25 by m2html © 2005