class_docstr: A variant of the Adam optimizer that can handles both sparse and non-sparse updates.
  
  The original Adam algorithm maintains two moving-average accumulators for
  each trainable variable; the accumulators are updated at every step.
  This class provides lazier handling of gradient updates for sparse
  variables.  It only updates moving-average accumulators for sparse variable
  indices that appear in the current batch, rather than updating the
  accumulators for all indices. Compared with the original Adam optimizer,
  it can provide large improvements in model training throughput for some
  applications. However, it provides slightly different semantics than the
  original Adam algorithm, and may lead to different empirical results.
docstr: Perform a single optimization step.
  
  :param closure: A optional callable. A closure that reevaluates the model
          and returns the loss.
code: def step(self, closure=None):
      """
      Perform a single optimization step.
  
      :param closure: A optional callable. A closure that reevaluates the model
              and returns the loss.
      """
      loss = None
      if closure is not None:
          loss = closure()
  
      for group in self.param_groups:
          for p in group["params"]:
              if p.grad is None:
                  continue
              grad = p.grad.data
  
              if grad.is_sparse:
                  self._sparse_step(group, p, grad)
              else:
                  self._dense_step(group, p, grad)
  
      return loss
  
file_path: BigDL/python/nano/src/bigdl/nano/pytorch/optim/sparseadam.py
imports: import math
  import torch
  from torch.optim.optimizer import Optimizer
  from bigdl.nano.utils.common import invalidInputError
label_desc: Use image node_id 2 for calling the SparseAdam obj's underlying member method code with example usage: obj.step(closure) and returns: loss