class_docstr: Gradient descent (with momentum) optimizer.
  
  Update rule for parameter `w` with gradient `g` when `momentum` is 0:
  
  ```python
  w = w - learning_rate * g
  ```
  
  Update rule when `momentum` is larger than 0:
  
  ```python
  velocity = momentum * velocity - learning_rate * g
  w = w + velocity
  ```
  
  When `nesterov=True`, this rule becomes:
  
  ```python
  velocity = momentum * velocity - learning_rate * g
  w = w + momentum * velocity - learning_rate * g
  ```
  
  Args:
    learning_rate: A `Tensor`, floating point value, or a schedule that is a
      `tf.keras.optimizers.schedules.LearningRateSchedule`, or a callable
      that takes no arguments and returns the actual value to use. The
      learning rate. Defaults to 0.01.
    momentum: float hyperparameter >= 0 that accelerates gradient descent
      in the relevant
      direction and dampens oscillations. Defaults to 0, i.e., vanilla gradient
      descent.
    nesterov: boolean. Whether to apply Nesterov momentum.
      Defaults to `False`.
    name: Optional name prefix for the operations created when applying
      gradients.  Defaults to `"SGD"`.
    **kwargs: Keyword arguments. Allowed to be one of
      `"clipnorm"` or `"clipvalue"`.
      `"clipnorm"` (float) clips gradients by norm; `"clipvalue"` (float) clips
      gradients by value.
  
  Usage:
  
  >>> opt = tf.keras.optimizers.SGD(learning_rate=0.1)
  >>> var = tf.Variable(1.0)
  >>> loss = lambda: (var ** 2)/2.0         # d(loss)/d(var1) = var1
  >>> step_count = opt.minimize(loss, [var]).numpy()
  >>> # Step is `- learning_rate * grad`
  >>> var.numpy()
  0.9
  
  >>> opt = tf.keras.optimizers.SGD(learning_rate=0.1, momentum=0.9)
  >>> var = tf.Variable(1.0)
  >>> val0 = var.value()
  >>> loss = lambda: (var ** 2)/2.0         # d(loss)/d(var1) = var1
  >>> # First step is `- learning_rate * grad`
  >>> step_count = opt.minimize(loss, [var]).numpy()
  >>> val1 = var.value()
  >>> (val0 - val1).numpy()
  0.1
  >>> # On later steps, step-size increases because of momentum
  >>> step_count = opt.minimize(loss, [var]).numpy()
  >>> val2 = var.value()
  >>> (val1 - val2).numpy()
  0.18
  
  Reference:
      - For `nesterov=True`, See [Sutskever et al., 2013](
        http://jmlr.org/proceedings/papers/v28/sutskever13.pdf).
code: def _resource_apply_sparse(
      self, grad, var, indices, apply_state=None
  ):
      # This method is only needed for momentum optimization.
      var_device, var_dtype = var.device, var.dtype.base_dtype
      coefficients = (apply_state or {}).get(
          (var_device, var_dtype)
      ) or self._fallback_apply_state(var_device, var_dtype)
  
      momentum_var = self.get_slot(var, "momentum")
      return gen_training_ops.ResourceSparseApplyKerasMomentum(
          var=var.handle,
          accum=momentum_var.handle,
          lr=coefficients["lr_t"],
          grad=grad,
          indices=indices,
          momentum=coefficients["momentum"],
          use_locking=self._use_locking,
          use_nesterov=self.nesterov,
      )
  
file_path: tensorflow/tensorflow/python/keras/optimizer_v2/gradient_descent.py
imports: from tensorflow.python.framework import tensor
  from tensorflow.python.keras.optimizer_v2 import optimizer_v2
  from tensorflow.python.ops import array_ops
  from tensorflow.python.ops import gen_resource_variable_ops
  from tensorflow.python.ops import gen_training_ops
label_desc: Use image node_id 6 for calling the SGD obj's underlying member method code with example usage: obj._resource_apply_sparse(grad, var, indices, apply_state) and returns: gen_training_ops