class_docstr: This class represent a Feature Adversaries evasion attack in PyTorch.
  
  | Paper link: https://arxiv.org/abs/1511.05122
docstr: Generate adversarial batch.
  
  :param x: Source samples.
  :param y: Guide samples.
  :return: Batch of adversarial examples.
code: def _generate_batch(
      self, x: "torch.Tensor", y: "torch.Tensor"
  ) -> "torch.Tensor":
      """
      Generate adversarial batch.
  
      :param x: Source samples.
      :param y: Guide samples.
      :return: Batch of adversarial examples.
      """
      import torch
  
      def loss_fn(source_orig, source_adv, guide):
          representation_loss = torch.zeros(
              size=(source_orig.shape[0],)
          ).to(self.estimator.device)
          for layer_i in self.layer:
              adv_representation = self.estimator.get_activations(
                  source_adv, layer_i, self.batch_size, True
              )
              guide_representation = self.estimator.get_activations(
                  guide, layer_i, self.batch_size, True
              )
  
              dim = tuple(range(1, len(source_adv.shape)))
              soft_constraint = torch.amax(
                  torch.abs(source_adv - source_orig), dim=dim
              )
  
              dim = tuple(range(1, len(adv_representation.shape)))
              representation_loss += torch.sum(
                  torch.square(
                      adv_representation - guide_representation
                  ),
                  dim=dim,
              )
  
          loss = torch.mean(
              representation_loss + self.lambda_ * soft_constraint
          )
          return loss
  
      self.estimator.model.eval()
  
      adv = x.clone().detach().to(self.estimator.device)
      if self.random_start:
          # Starting at a uniformly random point
          adv = adv + torch.empty_like(adv).uniform_(
              -self.delta, self.delta
          )
          if self.estimator.clip_values is not None:
              adv = torch.clamp(adv, *self.estimator.clip_values)
  
      if self.optimizer is None:
          # run a plain-vanilla PGD
          adv.requires_grad = True
  
          for _ in trange(
              self.max_iter,
              desc="Feature Adversaries PyTorch",
              disable=not self.verbose,
          ):
              loss = loss_fn(x, adv, y)
              loss.backward()
  
              # pgd step
              if adv.grad is not None:
                  adv.data = (
                      adv - adv.grad.detach().sign() * self.step_size
                  )
              else:
                  raise ValueError(
                      "Gradient tensor in PyTorch model is `None`."
                  )
              perturbation = torch.clamp(
                  adv.detach() - x.detach(), -self.delta, self.delta
              )
              adv.data = x.detach() + perturbation
              if self.estimator.clip_values is not None:
                  adv.data = torch.clamp(
                      adv.detach(), *self.estimator.clip_values
                  )
              adv.grad.zero_()
      else:
          # optimize soft constraint problem with chosen optimizer
          opt = self.optimizer(params=[adv], **self._optimizer_kwargs)  # type: ignore
  
          for _ in trange(
              self.max_iter,
              desc="Feature Adversaries PyTorch",
              disable=not self.verbose,
          ):
              adv.requires_grad = True
              # clip adversarial within L-Inf delta-ball
              adv.data = x.detach() + torch.clamp(
                  adv.detach() - x.detach(), -self.delta, self.delta
              )
  
              def closure():
                  if torch.is_grad_enabled():
                      opt.zero_grad()
                  loss = loss_fn(x, adv, y)
                  if loss.requires_grad:
                      loss.backward()
                  return loss
  
              opt.step(closure)
  
              if self.estimator.clip_values is not None:
                  adv.data = torch.clamp(
                      adv.detach(), *self.estimator.clip_values
                  )
      return adv.detach().cpu()
  
file_path: adversarial-robustness-toolbox/art/attacks/evasion/feature_adversaries/feature_adversaries_pytorch.py
imports: import logging
  from typing import TYPE_CHECKING, Optional, Tuple, Union
  import numpy
  from tqdm.auto import trange
  from art.attacks.attack import EvasionAttack
  from art.estimators.estimator import BaseEstimator, NeuralNetworkMixin
label_desc: Use image node_id 2 for calling the FeatureAdversariesPyTorch obj's underlying member method code with example usage: obj._generate_batch(x, y) and returns: adv, loss, loss