code: def _compute_spsa_gradient(loss_fn, x, delta, samples, iters):
      """
      Approximately compute the gradient of `loss_fn` at `x` using SPSA with the
      given parameters. The gradient is approximated by evaluating `iters` batches
      of `samples` size each.
      """
  
      assert len(x) == 1
      num_dims = len(x.size())
  
      x_batch = x.expand(samples, *([-1] * (num_dims - 1)))
  
      grad_list = []
      for i in range(iters):
          delta_x = delta * torch.sign(torch.rand_like(x_batch) - 0.5)
          delta_x = torch.cat([delta_x, -delta_x])
          with torch.no_grad():
              loss_vals = loss_fn(x + delta_x)
          while len(loss_vals.size()) < num_dims:
              loss_vals = loss_vals.unsqueeze(-1)
          avg_grad = (
              torch.mean(
                  loss_vals * torch.sign(delta_x), dim=0, keepdim=True
              )
              / delta
          )
          grad_list.append(avg_grad)
  
      return torch.mean(torch.cat(grad_list), dim=0, keepdim=True)
  
file_path: cleverhans/cleverhans/torch/attacks/spsa.py
imports: import numpy
  import torch
  from torch import optim
  from cleverhans.torch.utils import clip_eta
label_desc: Use image node_id 3 for calling a global function with example usage: _compute_spsa_gradient(loss_fn, x, delta, samples, iters) and returns: torch