minimize_bfgs

paddle.incubate.optimizer.functional. minimize_bfgs ( objective_func, initial_position, max_iters=50, tolerance_grad=1e-07, tolerance_change=1e-09, initial_inverse_hessian_estimate=None, line_search_fn='strong_wolfe', max_line_search_iters=50, initial_step_length=1.0, dtype='float32', name=None ) [source]

Minimizes a differentiable function func using the BFGS method. The BFGS is a quasi-Newton method for solving an unconstrained optimization problem over a differentiable function. Closely related is the Newton method for minimization. Consider the iterate update formula:

\[x_{k+1} = x_{k} + H_k \nabla{f_k}\]

If \(H_k\) is the inverse Hessian of \(f\) at \(x_k\), then it’s the Newton method. If \(H_k\) is symmetric and positive definite, used as an approximation of the inverse Hessian, then it’s a quasi-Newton. In practice, the approximated Hessians are obtained by only using the gradients, over either whole or part of the search history, the former is BFGS, the latter is L-BFGS.

Reference:

Jorge Nocedal, Stephen J. Wright, Numerical Optimization, Second Edition, 2006. pp140: Algorithm 6.1 (BFGS Method).

Parameters
  • objective_func – the objective function to minimize. objective_func accepts a 1D Tensor and returns a scalar.

  • initial_position (Tensor) – the starting point of the iterates, has the same shape with the input of objective_func .

  • max_iters (int, optional) – the maximum number of minimization iterations. Default value: 50.

  • tolerance_grad (float, optional) – terminates if the gradient norm is smaller than this. Currently gradient norm uses inf norm. Default value: 1e-7.

  • tolerance_change (float, optional) – terminates if the change of function value/position/parameter between two iterations is smaller than this value. Default value: 1e-9.

  • initial_inverse_hessian_estimate (Tensor, optional) – the initial inverse hessian approximation at initial_position. It must be symmetric and positive definite. If not given, will use an identity matrix of order N, which is size of initial_position . Default value: None.

  • line_search_fn (str, optional) – indicate which line search method to use, only support ‘strong wolfe’ right now. May support ‘Hager Zhang’ in the future. Default value: ‘strong wolfe’.

  • max_line_search_iters (int, optional) – the maximum number of line search iterations. Default value: 50.

  • initial_step_length (float, optional) – step length used in first iteration of line search. different initial_step_length may cause different optimal result. For methods like Newton and quasi-Newton the initial trial step length should always be 1.0. Default value: 1.0.

  • dtype ('float32' | 'float64', optional) – data type used in the algorithm, the data type of the input parameter must be consistent with the dtype. Default value: ‘float32’.

  • name (str, optional) – Name for the operation. For more information, please refer to Name. Default value: None.

Returns

  • is_converge (bool): Indicates whether found the minimum within tolerance.

  • num_func_calls (int): number of objective function called.

  • position (Tensor): the position of the last iteration. If the search converged, this value is the argmin of the objective function regrading to the initial position.

  • objective_value (Tensor): objective function value at the position.

  • objective_gradient (Tensor): objective function gradient at the position.

  • inverse_hessian_estimate (Tensor): the estimate of inverse hessian at the position.

Return type

output(tuple)

Examples

>>> # Example1: 1D Grid Parameters
>>> import paddle
>>> # Randomly simulate a batch of input data
>>> inputs = paddle. normal(shape=(100, 1))
>>> labels = inputs * 2.0
>>> # define the loss function
>>> def loss(w):
...     y = w * inputs
...     return paddle.nn.functional.square_error_cost(y, labels).mean()
>>> # Initialize weight parameters
>>> w = paddle.normal(shape=(1,))
>>> # Call the bfgs method to solve the weight that makes the loss the smallest, and update the parameters
>>> for epoch in range(0, 10):
...     # Call the bfgs method to optimize the loss, note that the third parameter returned represents the weight
...     w_update = paddle.incubate.optimizer.functional.minimize_bfgs(loss, w)[2]
...     # Use paddle.assign to update parameters in place
...     paddle. assign(w_update, w)
>>> # Example2: Multidimensional Grid Parameters
>>> import paddle
>>> def flatten(x):
...     return x. flatten()
>>> def unflatten(x):
...     return x.reshape((2,2))
>>> # Assume the network parameters are more than one dimension
>>> def net(x):
...     assert len(x.shape) > 1
...     return x.square().mean()
>>> # function to be optimized
>>> def bfgs_f(flatten_x):
...     return net(unflatten(flatten_x))
>>> x = paddle.rand([2,2])
>>> for i in range(0, 10):
...     # Flatten x before using minimize_bfgs
...     x_update = paddle.incubate.optimizer.functional.minimize_bfgs(bfgs_f, flatten(x))[2]
...     # unflatten x_update, then update parameters
...     paddle.assign(unflatten(x_update), x)