code: def spsa(
      model_fn,
      x,
      y,
      eps,
      nb_iter,
      clip_min=None,
      clip_max=None,
      targeted=False,
      early_stop_loss_threshold=None,
      learning_rate=0.01,
      delta=0.01,
      spsa_samples=128,
      spsa_iters=1,
      is_debug=False,
  ):
      """Tensorflow 2.0 implementation of SPSA.
  
      This implements the SPSA adversary, as in https://arxiv.org/abs/1802.05666 (Uesato et al. 2018).
      SPSA is a gradient-free optimization method, which is useful when the model is non-differentiable,
      or more generally, the gradients do not point in useful directions.
      :param model_fn: A callable that takes an input tensor and returns the model logits.
      :param x: Input tensor.
      :param y: Tensor with true labels. If targeted is true, then provide the target label.
      :param eps: The size of the maximum perturbation, measured in the L-infinity norm.
      :param nb_iter: The number of optimization steps.
      :param clip_min: If specified, the minimum input value.
      :param clip_max: If specified, the maximum input value.
      :param targeted: (optional) bool. Is the attack targeted or untargeted? Untargeted, the default,
                will try to make the label incorrect. Targeted will instead try to move in the direction
                of being more like y.
      :param early_stop_loss_threshold: A float or None. If specified, the attack will end as soon as
                                        the loss is below `early_stop_loss_threshold`.
      :param learning_rate: Learning rate of ADAM optimizer.
      :param delta: Perturbation size used for SPSA approximation.
      :param spsa_samples:  Number of inputs to evaluate at a single time. The true batch size
                            (the number of evaluated inputs for each update) is `spsa_samples *
                            spsa_iters`
      :param spsa_iters:  Number of model evaluations before performing an update, where each evaluation
                          is on `spsa_samples` different inputs.
      :param is_debug: If True, print the adversarial loss after each update.
      """
      if x.get_shape().as_list()[0] != 1:
          raise ValueError(
              "For SPSA, input tensor x must have batch_size of 1."
          )
  
      optimizer = SPSAAdam(
          lr=learning_rate,
          delta=delta,
          num_samples=spsa_samples,
          num_iters=spsa_iters,
      )
  
      def loss_fn(x, label):
          """
          Margin logit loss, with correct sign for targeted vs untargeted loss.
          """
          logits = model_fn(x)
          loss_multiplier = 1 if targeted else -1
          return loss_multiplier * margin_logit_loss(
              logits, label, nb_classes=logits.get_shape()[-1]
          )
  
      adv_x = projected_optimization(
          loss_fn,
          x,
          y,
          eps,
          nb_iter,
          optimizer,
          clip_min,
          clip_max,
          early_stop_loss_threshold,
          is_debug=is_debug,
      )
  
      return adv_x
  
file_path: cleverhans/cleverhans/tf2/attacks/spsa.py
imports: import tensorflow
label_desc: Use image node_id 1 for calling a global function with example usage: spsa(model_fn, x, y, eps, nb_iter, clip_min, clip_max, targeted, early_stop_loss_threshold, learning_rate, delta, spsa_samples, spsa_iters, is_debug) and returns: adv_x, unknown