class_docstr: Implementation of the attack framework proposed by Inkawhich et al. (2018). Prioritizes the frame of a sequential
  input to be adversarially perturbed based on the saliency score of each frame.
  
  | Paper link: https://arxiv.org/abs/1811.11875
class_docstr_tok: ["Implementation","of","the","attack","framework","proposed","by","Inkawhich","et","al",".","(","2018",")",".","Prioritizes","the","frame","of","a","sequential","input","to","be","adversarially","perturbed","based","on","the","saliency","score","of","each","frame",".","|","Paper","link",":","https",":","\/\/arxiv.org\/abs\/1811.11875"]
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.
      """
      if len(x.shape) < 3:  # pragma: no cover
          raise ValueError(
              "Frame saliency attack works only on inputs of dimension greater than 2."
          )
  
      if self.frame_index >= len(x.shape):  # pragma: no cover
          raise ValueError(
              "Frame index is out of bounds for the given input shape."
          )
  
      if y is not None:
          y = check_and_transform_label_format(
              y, nb_classes=self.estimator.nb_classes
          )
  
      if self.method == "one_shot":
          if y is None:
              return self.attacker.generate(x)
  
          return self.attacker.generate(x, y)
  
      if y is None:
          # Throw error if attack is targeted, but no targets are provided
          if hasattr(self.attacker, "targeted") and self.attacker.targeted:  # type: ignore  # pragma: no cover
              raise ValueError(
                  "Target labels `y` need to be provided for a targeted attack."
              )
  
          # Use model predictions as correct outputs
          targets = get_labels_np_array(
              self.estimator.predict(x, batch_size=self.batch_size)
          )
      else:
          targets = y
  
      if (
          self.estimator.nb_classes == 2 and targets.shape[1] == 1
      ):  # pragma: no cover
          raise ValueError(
              "This attack has not yet been tested for binary classification with a single output classifier."
          )
  
      nb_samples = x.shape[0]
      nb_frames = x.shape[self.frame_index]
      x_adv = x.astype(ART_NUMPY_DTYPE)
  
      # Determine for which adversarial examples the attack fails:
      attack_failure = self._compute_attack_failure_array(
          x, targets, x_adv
      )
  
      # Determine the order in which to perturb frames, based on saliency scores:
      frames_to_perturb = self._compute_frames_to_perturb(
          x_adv, targets
      )
  
      # Generate adversarial perturbations. If the method is "iterative_saliency_refresh", we will use a mask so that
      # only the next frame to be perturbed is considered in the attack; moreover we keep track of the next frames to
      # be perturbed so they will not be perturbed again later on.
      mask = np.ones(x.shape)
      if self.method == "iterative_saliency_refresh":
          mask = np.zeros(x.shape)
          mask = np.swapaxes(mask, 1, self.frame_index)
          mask[:, frames_to_perturb[:, 0], ::] = 1
          mask = np.swapaxes(mask, 1, self.frame_index)
          disregard = np.zeros((nb_samples, nb_frames))
          disregard[:, frames_to_perturb[:, 0]] = np.inf
  
      x_adv_new = self.attacker.generate(x, targets, mask=mask)
  
      # Here starts the main iteration:
      for i in trange(
          nb_frames, desc="Frame saliency", disable=not self.verbose
      ):
          # Check if attack has already succeeded for all inputs:
          if sum(attack_failure) == 0:
              break
  
          # Update designated frames with adversarial perturbations:
          x_adv = np.swapaxes(x_adv, 1, self.frame_index)
          x_adv_new = np.swapaxes(x_adv_new, 1, self.frame_index)
          x_adv[
              attack_failure,
              frames_to_perturb[:, i][attack_failure],
              ::,
          ] = x_adv_new[
              attack_failure,
              frames_to_perturb[:, i][attack_failure],
              ::,
          ]
          x_adv = np.swapaxes(x_adv, 1, self.frame_index)
          x_adv_new = np.swapaxes(x_adv_new, 1, self.frame_index)
  
          # Update for which adversarial examples the attack still fails:
          attack_failure = self._compute_attack_failure_array(
              x, targets, x_adv
          )
  
          # For the "refresh" method, update the next frames to be perturbed (disregarding the frames that were
          # perturbed already) and also refresh the adversarial perturbations:
          if (
              self.method == "iterative_saliency_refresh"
              and i < nb_frames - 1
          ):
              frames_to_perturb = self._compute_frames_to_perturb(
                  x_adv, targets, disregard
              )
              mask = np.zeros(x.shape)
              mask = np.swapaxes(mask, 1, self.frame_index)
              mask[:, frames_to_perturb[:, i + 1], ::] = 1
              mask = np.swapaxes(mask, 1, self.frame_index)
              disregard[:, frames_to_perturb[:, i + 1]] = np.inf
              x_adv_new = self.attacker.generate(
                  x_adv, targets, mask=mask
              )
  
      return x_adv
  
file_path: adversarial-robustness-toolbox/art/attacks/evasion/frame_saliency.py
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import logging
  from typing import Optional, TYPE_CHECKING
  import numpy
  from tqdm.auto import trange
  from art.config import ART_NUMPY_DTYPE
  from art.estimators.estimator import BaseEstimator, NeuralNetworkMixin
  from art.estimators.classification.classifier import ClassGradientsMixin
  from art.attacks.attack import EvasionAttack
  from art.utils import compute_success_array, get_labels_np_array, check_and_transform_label_format
label_desc: Use image node_id 2 for calling the FrameSaliencyAttack obj's underlying member method code with example usage: obj.generate(x, y) and returns: x_adv, self, self