code: def step(self, closure=None):
      loss = None
      if closure is not None:
          with torch.enable_grad():
              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
              grad = p.grad
              state = self.state[p]
  
              # State initialization
              if len(state) == 0:
                  state["momentum"] = torch.zeros_like(p)
  
              # SGD
              buf = state["momentum"]
              buf.mul_(momentum).add_(grad, alpha=1.0 - dampening)
              if nesterov:
                  d_p = grad + momentum * buf
              else:
                  d_p = buf
  
              # Projection
              wd_ratio = 1.0
              if len(p.shape) > 1:
                  d_p, wd_ratio = projection(
                      p,
                      grad,
                      d_p,
                      group["delta"],
                      group["wd_ratio"],
                      group["eps"],
                  )
  
              # Weight decay
              if weight_decay != 0:
                  p.mul_(
                      1.0
                      - group["lr"]
                      * group["weight_decay"]
                      * wd_ratio
                      / (1 - momentum)
                  )
  
              # Step
              p.add_(d_p, alpha=-group["lr"])
  
      return loss
  
file_path: pytorch-image-models/timm/optim/sgdp.py
imports: import torch
  import torch.nn.functional
  from torch.optim.optimizer import Optimizer, required
  import math
  from .adamp import projection
label_desc: Use image node_id 2 for calling the SGDP obj's underlying member method code with example usage: obj.step(closure) and returns: loss