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 and self.step_size is not None:
                    adv.data = adv - adv.grad.detach().sign() * self.step_size
                else:
                    raise ValueError("Gradient tensor in PyTorch model or step_size 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()

        Generate adversarial batch.

        :param x: Source samples.
        :param y: Guide samples.
        :return: Batch of adversarial examples.
        
art/attacks/evasion/feature_adversaries/feature_adversaries_pytorch.py