class_docstr: `LowProFool` attack.
  
  | Paper link: https://arxiv.org/abs/1911.03274
class_docstr_tok: ["`","LowProFool","`","attack",".","|","Paper","link",":","https",":","\/\/arxiv.org\/abs\/1911.03274"]
docstr: Generate adversaries for the samples passed in the `x` data matrix, whose targets are specified in `y`,
  one-hot-encoded target matrix. This procedure makes use of the LowProFool algorithm. In the case of failure,
  the resulting array will contain the initial samples on the problematic positions - which otherwise should
  contain the best adversary found in the process.
  
  :param x: An array with the original inputs to be attacked.
  :param y: One-hot-encoded target classes of shape (nb_samples, nb_classes).
  :param kwargs:
  :return: An array holding the adversarial examples.
docstr_tok: ["Generate","adversaries","for","the","samples","passed","in","the","`","x","`","data","matrix",",","whose","targets","are","specified","in","`","y","`",",","one-hot-encoded","target","matrix",".","This","procedure","makes","use","of","the","LowProFool","algorithm",".","In","the","case","of","failure",",","the","resulting","array","will","contain","the","initial","samples","on","the","problematic","positions","-","which","otherwise","should","contain","the","best","adversary","found","in","the","process",".",":","param","x",":","An","array","with","the","original","inputs","to","be","attacked",".",":","param","y",":","One-hot-encoded","target","classes","of","shape","(","nb_samples",",","nb_classes",")",".",":","param","kwargs",":",":","return",":","An","array","holding","the","adversarial","examples","."]
code: def generate(
      self, x: np.ndarray, y: Optional[np.ndarray] = None, **kwargs
  ) -> np.ndarray:
      """
      Generate adversaries for the samples passed in the `x` data matrix, whose targets are specified in `y`,
      one-hot-encoded target matrix. This procedure makes use of the LowProFool algorithm. In the case of failure,
      the resulting array will contain the initial samples on the problematic positions - which otherwise should
      contain the best adversary found in the process.
  
      :param x: An array with the original inputs to be attacked.
      :param y: One-hot-encoded target classes of shape (nb_samples, nb_classes).
      :param kwargs:
      :return: An array holding the adversarial examples.
      """
      if self.importance_vec is None:
          raise ValueError(
              "No feature importance vector has been provided yet."
          )
      if y is None:
          raise ValueError(
              "It is required to pass target classes as `y` parameter."
          )
  
      # Make sure samples and targets are of type np.ndarray.
      samples = np.array(x, dtype=np.float64)
      targets = np.array(y, dtype=np.float64)
  
      # Extract the target classes as integers implying their classes' indices.
      targets_integer = np.argmax(y, axis=1)
  
      if targets.shape[1] != self.n_classes:
          raise ValueError(
              "Targets shape is not compatible with number of classes."
          )
      if samples.shape[1] != self.n_features:
          raise ValueError(
              "Samples shape is not compatible with number of features."
          )
  
      # Initialize perturbation vectors and learning rate.
      perturbations = np.zeros(samples.shape, dtype=np.float64)
      eta = self.eta
  
      # Initialize 'keep-the-best' variables.
      best_norm_losses = np.inf * np.ones(
          samples.shape[0], dtype=np.float64
      )
      best_perturbations = perturbations.copy()
  
      # Success indicators per sample.
      success_indicators = np.zeros(samples.shape[0], dtype=np.float64)
  
      # Predicate used to determine whether the target was met based on the given probabilities.
      def met_target(probas, target_class):
          if self.threshold is None:
              return np.argmax(probas) == target_class
          return probas[target_class] > self.threshold
  
      # Main loop.
      for _ in trange(
          self.n_steps, desc="LowProFool", disable=not self.verbose
      ):
          # Calculate gradients, apply them to perturbations and clip if needed.
          grad = self.__get_gradients(samples, perturbations, targets)
          perturbations -= eta * grad
          perturbations = self.__apply_clipping(samples, perturbations)
  
          # Decrease learning rate for the next iteration.
          eta = max(eta * self.eta_decay, self.eta_min)
  
          # Calculate class-wise probabilities.
          y_probas = self.estimator.predict(
              (samples + perturbations).astype(np.float32)
          )
  
          # Examine the quality of adversaries in the current step.
          for j, target_int in enumerate(targets_integer):
              # Check for every sample whether the threshold probability is reached.
              if met_target(y_probas[j], target_int):
                  success_indicators[j] = 1.0
                  # Calculate weighted Lp-norm loss.
                  norm_loss = self.__weighted_lp_norm(
                      perturbations[j : j + 1]
                  )[0, 0]
  
                  # Note it, if the adversary improves.
                  if norm_loss < best_norm_losses[j]:
                      best_norm_losses[j] = norm_loss
                      best_perturbations[j] = perturbations[j].copy()
  
      logger.info(
          "Success rate of LowProFool attack: %.2f}%%",
          100 * np.sum(success_indicators) / success_indicators.size,
      )
  
      # The generated adversaries are a sum of initial samples and best perturbation vectors found by the algorithm.
      return samples + best_perturbations
  
imports: import logging
  from typing import Callable, Optional, Union, TYPE_CHECKING
  import numpy
  from scipy.stats import pearsonr
  from tqdm.auto import trange
  from art.attacks.attack import EvasionAttack
  from art.estimators.estimator import LossGradientsMixin
  from art.estimators.estimator import BaseEstimator
  from art.estimators.classification.classifier import ClassifierMixin
label_desc: Use image node_id 8 for calling the LowProFool obj's underlying member method code with example usage: obj.generate(x, y) and returns: unknown, unknown, unknown