class_docstr: Implements SGDW algorithm.
  
  It has been proposed in `Decoupled Weight Decay Regularization`__.
  
  Arguments:
      params: iterable of parameters to optimize or dicts defining
          parameter groups
      lr: learning rate (default: 1e-3)
      momentum: momentum factor (default: 0)
      weight_decay: weight decay (L2 penalty) (default: 0)
      dampening: dampening for momentum (default: 0)
      nesterov: enables Nesterov momentum (default: False)
  
  Example:
      >>> import torch_optimizer as optim
      >>> optimizer = optim.SGDW(model.parameters(), lr=0.1, momentum=0.9)
      >>> optimizer.zero_grad()
      >>> loss_fn(model(input), target).backward()
      >>> optimizer.step()
  
  __ https://arxiv.org/abs/1711.05101
  
  Note:
      Reference code: https://github.com/pytorch/pytorch/pull/22466
docstr: Performs a single optimization step.
  
  Arguments:
      closure: A closure that reevaluates the model and returns the loss.
docstr_tok: ["Performs","a","single","optimization","step",".","Arguments",":","closure",":","A","closure","that","reevaluates","the","model","and","returns","the","loss","."]
code: def step(self, closure: OptLossClosure = None) -> OptFloat:
      """Performs a single optimization step.
  
      Arguments:
          closure: 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:
          weight_decay = group["weight_decay"]
          momentum = group["momentum"]
          dampening = group["dampening"]
          nesterov = group["nesterov"]
  
          for p in group["params"]:
              if p.grad is None:
                  continue
              d_p = p.grad.data
  
              if p.grad.is_sparse:
                  msg = (
                      "SGDW does not support sparse gradients, "
                      "please consider SparseAdam instead"
                  )
                  raise RuntimeError(msg)
  
              if momentum != 0:
                  param_state = self.state[p]
                  if "momentum_buffer" not in param_state:
                      buf = param_state[
                          "momentum_buffer"
                      ] = torch.clone(d_p).detach()
                  else:
                      buf = param_state["momentum_buffer"]
                      buf.mul_(momentum).add_(d_p, alpha=1 - dampening)
                  if nesterov:
                      d_p = d_p.add(momentum, buf)
                  else:
                      d_p = buf
  
              # Apply momentum
              p.data.add_(d_p, alpha=-group["lr"])
  
              # Apply weight decay
              if weight_decay != 0:
                  p.data.add_(weight_decay, alpha=-group["lr"])
      return loss
  
imports: import torch
  from torch.optim.optimizer import Optimizer
  from .types import OptFloat, OptLossClosure, Params, State
label_desc: Use image node_id 3 for calling the SGDW obj's underlying member method code with example usage: obj.step(closure) and returns: loss