class_docstr: Implementation of the attack from Moosavi-Dezfooli et al. (2016). Computes a fixed perturbation to be applied to all
  future inputs. To this end, it can use any adversarial attack method.
  
  | Paper link: https://arxiv.org/abs/1610.08401
class_docstr_tok: ["Implementation","of","the","attack","from","Moosavi-Dezfooli","et","al",".","(","2016",")",".","Computes","a","fixed","perturbation","to","be","applied","to","all","future","inputs",".","To","this","end",",","it","can","use","any","adversarial","attack","method",".","|","Paper","link",":","https",":","\/\/arxiv.org\/abs\/1610.08401"]
docstr: Generate adversarial samples and return them in an array.
  
  :param x: An array with the original inputs.
  :param y: An array with the original labels to be predicted.
  :return: An array holding the adversarial examples.
docstr_tok: ["Generate","adversarial","samples","and","return","them","in","an","array",".",":","param","x",":","An","array","with","the","original","inputs",".",":","param","y",":","An","array","with","the","original","labels","to","be","predicted",".",":","return",":","An","array","holding","the","adversarial","examples","."]
code: def generate(
      self, x: np.ndarray, y: Optional[np.ndarray] = None, **kwargs
  ) -> np.ndarray:
      """
      Generate adversarial samples and return them in an array.
  
      :param x: An array with the original inputs.
      :param y: An array with the original labels to be predicted.
      :return: An array holding the adversarial examples.
      """
      logger.info(
          "Computing universal perturbation based on %s attack.",
          self.attacker,
      )
  
      if y is not None:
          y = check_and_transform_label_format(
              y, nb_classes=self.estimator.nb_classes
          )
  
      if y is None:
          # Use model predictions as true labels
          logger.info("Using model predictions as true labels.")
          y = get_labels_np_array(
              self.estimator.predict(x, batch_size=self.batch_size)
          )
  
      if self.estimator.nb_classes == 2 and y.shape[1] == 1:
          raise ValueError(
              "This attack has not yet been tested for binary classification with a single output classifier."
          )
  
      y_index = np.argmax(y, axis=1)
  
      # Init universal perturbation
      noise = np.zeros_like(x[[0]])
      fooling_rate = 0.0
      nb_instances = len(x)
  
      # Instantiate the middle attacker
      attacker = self._get_attack(self.attacker, self.attacker_params)
  
      # Generate the adversarial examples
      nb_iter = 0
      pbar = tqdm(
          total=self.max_iter,
          desc="Universal perturbation",
          disable=not self.verbose,
      )
  
      while fooling_rate < 1.0 - self.delta and nb_iter < self.max_iter:
          # Go through all the examples randomly
          rnd_idx = random.sample(range(nb_instances), nb_instances)
  
          # Go through the data set and compute the perturbation increments sequentially
          for j, ex in enumerate(x[rnd_idx]):
              x_i = ex[None, ...]
  
              current_label = np.argmax(
                  self.estimator.predict(x_i + noise)[0]
              )
              original_label = y_index[rnd_idx][j]
  
              if current_label == original_label:
                  # Compute adversarial perturbation
                  adv_xi = attacker.generate(
                      x_i + noise, y=y[rnd_idx][[j]]
                  )
                  new_label = np.argmax(
                      self.estimator.predict(adv_xi)[0]
                  )
  
                  # If the class has changed, update v
                  if current_label != new_label:
                      noise = adv_xi - x_i
  
                      # Project on L_p ball
                      noise = projection(noise, self.eps, self.norm)
          nb_iter += 1
          pbar.update(1)
  
          # Apply attack and clip
          x_adv = x + noise
          if self.estimator.clip_values is not None:
              clip_min, clip_max = self.estimator.clip_values
              x_adv = np.clip(x_adv, clip_min, clip_max)
  
          # Compute the error rate
          y_adv = np.argmax(
              self.estimator.predict(x_adv, batch_size=1), axis=1
          )
          fooling_rate = np.sum(y_index != y_adv) / nb_instances
  
      pbar.close()
      self._fooling_rate = fooling_rate
      self._converged = nb_iter < self.max_iter
      self._noise = noise
      logger.info(
          "Success rate of universal perturbation attack: %.2f%%",
          100 * fooling_rate,
      )
  
      return x_adv
  
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import logging
  import random
  import types
  from typing import Any, Dict, Optional, Union, TYPE_CHECKING
  import numpy
  from tqdm.auto import tqdm
  from art.attacks.attack import EvasionAttack
  from art.estimators.estimator import BaseEstimator
  from art.estimators.classification.classifier import ClassifierMixin
  from art.utils import projection, get_labels_np_array, check_and_transform_label_format
label_desc: Use image node_id 5 for calling the UniversalPerturbation obj's underlying member method code with example usage: obj.generate(x, y) and returns: x_adv