Skip to content
Snippets Groups Projects
Commit 47994d0d authored by MALOU THIBAULT's avatar MALOU THIBAULT
Browse files

update the documentation of the gradient_descent module to the Docstring...

update the documentation of the gradient_descent module to the Docstring NumpyDoc format, and minor updates
parent 234dacf5
No related branches found
No related tags found
No related merge requests found
Pipeline #221321 passed
......@@ -2,40 +2,61 @@ import numpy as np
def gradient_descent(fun, x0, args=(), options=None, callback=None, f_old=np.inf):
r"""
Minimize a function :math:`f(x)` using the gradient descent method.
The steps of the algorithme are the following:
- Initialization: Starting from an initial point :math:`x_0`.
- For each iteration :math:`k`:
1. Compute the gradient of the function :math:`\nabla f(x_k)` at the current point :math:`x_k`.
2. Update the estimate of :math:`x` using the rule :math:`x_{k+1} = x_k - \alpha \nabla f(x_k)`
where :math:`\alpha` is the step size.
- Convergence Check: the algorithm stops
when the change in the function value or the gradient is below a predefined threshold, or
when the maximum number of iterations is reached.
Parameters
----------
fun : callable
Method that, given :math:`x`, returns the evaluation of the function :math:`f(x)` and its gradient :math:`\nabla f(x)`.
x0 : ~numpy.ndarray
Initial point :math:`x_0` from which the iterative optimization algorithm starts.
args : tuple
Arguments that should be given to the callable :meth:`fun` besides the array containing the current value of :math:`x`.
options : dict, optional, default: None
Dictionary containing several options to customize the gradient descent method and its stopping criteria.
These options include:
- 'step size': float or int, default: 1, step size of the gradient descent :math:`\alpha`, also called learning rate.
- 'nit_max': int, default: 50, maximum number of iterations.
- 'ftol': float, default: -1,
tolerance such that the algorithm terminates successfully when :math:`|f(x_{k+1})-f(x_{k})|<\text{ftol}`
- 'gtol': float, default: -1,
tolerance such that the algorithm terminates successfully when :math:`|\nabla f(x_{k})|<\text{gtol}`
callback : callable, optional
Method called at each optimization iteration.
The method should take as sole input the array containing the current value of :math:`x`.
f_old : float, optional, default: numpy.inf
Previous value of the function to optimize :math:`f(x)` if the optimization process is restarted.
Returns
-------
x_opt : ~numpy.ndarray
Optimal value :math:`x^*`.
f_opt : float
Evaluation of the function to minimize at the optimal value :math:`f(x^*)`.
grad_opt : ~numpy.ndarray
Evaluation of the gradient of the function to minimize at the optimal value :math:`\nabla f(x^*)`.
n_iter : int
Number of iterations needed to converge.
"""
Mininize a function using the gradient descent method
- TO DO:
* improve stopping criteria, add ftol and gtol,
* add exceptions to check inputs type
- input:
* fun:
| callable,
| method that given an x return the evaluation in x of the function to minimize and its gradient
* x0:
| array,
| the initial point from which the iterative optimization algorithm will starts
* args:
| tuple,
| arguments that should be given to the callable fun besides x
* options:
| dictionnary, None by default,
| contains several options that can be given to customize the gradient descent method and its stopping criteria
| these options are:
| 'step size': the step size, or learning rate, of the gradient descent, step_size=1 by default,
| 'nit_max': the maximal number of iteration, nit_max=50 by default,
* callback:
| callable,
| method that will be called at each optimization iteration
* f_old:
| float, np.inf by default,
| if the optimization process is restarted, enable to store the previous value of f the function to optimize
- output:
* the optimal value of x
* the evaluation of the function to minimize at the optimal value of x
* the evaluation of the gradient of the function to minimize at the optimal value of x
* the number of iteration needed to converge
"""
# To do:
# Add exceptions to check input types.
if not isinstance(args, tuple):
args = (args,)
......@@ -50,15 +71,15 @@ def gradient_descent(fun, x0, args=(), options=None, callback=None, f_old=np.inf
if options is None:
options = {}
# if 'ftol' in options.keys():
# ftol = options['ftol']
# else:
# ftol = 1e-7
if 'ftol' in options.keys():
ftol = options['ftol']
else:
ftol = -1
# if 'gtol' in options.keys():
# gtol = options['gtol']
# else:
# gtol = 1e-7
if 'gtol' in options.keys():
gtol = options['gtol']
else:
gtol = -1
if 'nit_max' in options.keys():
nit_max = options['nit_max']
......@@ -100,9 +121,9 @@ def gradient_descent(fun, x0, args=(), options=None, callback=None, f_old=np.inf
# update the flag of the stopping criteria and the previous evaluation of the function
flag_ite = nit < nit_max
# flag_ftol = np.abs(f - f_old) < ftol
# flag_gtol = np.max(np.abs(df)) < gtol
flag_stop = flag_ite # and flag_ftol and flag_gtol
flag_ftol = np.abs(f - f_old) > ftol
flag_gtol = np.max(np.abs(df)) > gtol
flag_stop = flag_ite and flag_ftol and flag_gtol
f_old = np.copy(f)
return x, f, df, nit
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment