code: def _gradient_descent(
      objective,
      p0,
      it,
      n_iter,
      objective_error=None,
      n_iter_check=1,
      n_iter_without_progress=50,
      momentum=0.5,
      learning_rate=1000.0,
      min_gain=0.01,
      min_grad_norm=1e-7,
      min_error_diff=1e-7,
      verbose=0,
      args=None,
      kwargs=None,
  ):
      """Batch gradient descent with momentum and individual gains.
  
      Parameters
      ----------
      objective : function or callable
          Should return a tuple of cost and gradient for a given parameter
          vector. When expensive to compute, the cost can optionally
          be None and can be computed every n_iter_check steps using
          the objective_error function.
  
      p0 : array-like, shape (n_params,)
          Initial parameter vector.
  
      it : int
          Current number of iterations (this function will be called more than
          once during the optimization).
  
      n_iter : int
          Maximum number of gradient descent iterations.
  
      n_iter_check : int
          Number of iterations before evaluating the global error. If the error
          is sufficiently low, we abort the optimization.
  
      objective_error : function or callable
          Should return a tuple of cost and gradient for a given parameter
          vector.
  
      n_iter_without_progress : int, optional (default: 30)
          Maximum number of iterations without progress before we abort the
          optimization.
  
      momentum : float, within (0.0, 1.0), optional (default: 0.5)
          The momentum generates a weight for previous gradients that decays
          exponentially.
  
      learning_rate : float, optional (default: 1000.0)
          The learning rate should be extremely high for t-SNE! Values in the
          range [100.0, 1000.0] are common.
  
      min_gain : float, optional (default: 0.01)
          Minimum individual gain for each parameter.
  
      min_grad_norm : float, optional (default: 1e-7)
          If the gradient norm is below this threshold, the optimization will
          be aborted.
  
      min_error_diff : float, optional (default: 1e-7)
          If the absolute difference of two successive cost function values
          is below this threshold, the optimization will be aborted.
  
      verbose : int, optional (default: 0)
          Verbosity level.
  
      args : sequence
          Arguments to pass to objective function.
  
      kwargs : dict
          Keyword arguments to pass to objective function.
  
      Returns
      -------
      p : array, shape (n_params,)
          Optimum parameters.
  
      error : float
          Optimum.
  
      i : int
          Last iteration.
      """
      if args is None:
          args = []
      if kwargs is None:
          kwargs = {}
  
      p = p0.copy().ravel()
      update = np.zeros_like(p)
      gains = np.ones_like(p)
      error = np.finfo(np.float).max
      best_error = np.finfo(np.float).max
      best_iter = 0
  
      for i in range(it, n_iter):
          new_error, grad = objective(p, *args, **kwargs)
          grad_norm = linalg.norm(grad)
  
          inc = update * grad >= 0.0
          dec = np.invert(inc)
          gains[inc] += 0.05
          gains[dec] *= 0.95
          np.clip(gains, min_gain, np.inf)
          grad *= gains
          update = momentum * update - learning_rate * grad
          p += update
  
          if (i + 1) % n_iter_check == 0:
              if new_error is None:
                  new_error = objective_error(p, *args)
              error_diff = np.abs(new_error - error)
              error = new_error
  
              if verbose >= 2:
                  m = "[t-SNE] Iteration %d: error = %.7f, gradient norm = %.7f"
                  print(m % (i + 1, error, grad_norm))
  
              if error < best_error:
                  best_error = error
                  best_iter = i
              elif i - best_iter > n_iter_without_progress:
                  if verbose >= 2:
                      print(
                          "[t-SNE] Iteration %d: did not make any progress "
                          "during the last %d episodes. Finished."
                          % (i + 1, n_iter_without_progress)
                      )
                  break
              if grad_norm <= min_grad_norm:
                  if verbose >= 2:
                      print(
                          "[t-SNE] Iteration %d: gradient norm %f. Finished."
                          % (i + 1, grad_norm)
                      )
                  break
              if error_diff <= min_error_diff:
                  if verbose >= 2:
                      m = "[t-SNE] Iteration %d: error difference %f. Finished."
                      print(m % (i + 1, error_diff))
                  break
  
          if new_error is not None:
              error = new_error
  
      return p, error, i
  
imports: import numpy
  from scipy import linalg
  import scipy.sparse
  from scipy.spatial.distance import pdist
  from scipy.spatial.distance import squareform
  from ..neighbors import BallTree
  from ..base import BaseEstimator
  from ..utils import check_array
  from ..utils import check_random_state
  from ..utils.extmath import _ravel
  from ..decomposition import PCA
  from ..metrics.pairwise import pairwise_distances
  from .None import _utils
  from .None import _barnes_hut_tsne
  from ..utils.fixes import astype
  from ..externals.six import string_types
label_desc: Use image node_id 6 for calling a global function with example usage: _gradient_descent(objective, p0, it, n_iter, objective_error, n_iter_check, n_iter_without_progress, momentum, learning_rate, min_gain, min_grad_norm, min_error_diff, verbose, args, kwargs) and returns: p,  error,  i