class_docstr: Class performing adversarial training following Fast is Better Than Free protocol.
  
  | Paper link: https://openreview.net/forum?id=BJx040EFvH
  
  | The effectiveness of this protocol is found to be sensitive to the use of techniques like
      data augmentation, gradient clipping and learning rate schedules. Optionally, the use of
      mixed precision arithmetic operation via apex library can significantly reduce the training
      time making this one of the fastest adversarial training protocol.
class_docstr_tok: ["Class","performing","adversarial","training","following","Fast","is","Better","Than","Free","protocol",".","|","Paper","link",":","https",":","\/\/openreview.net\/forum","?","id=BJx040EFvH","|","The","effectiveness","of","this","protocol","is","found","to","be","sensitive","to","the","use","of","techniques","like","data","augmentation",",","gradient","clipping","and","learning","rate","schedules",".","Optionally",",","the","use","of","mixed","precision","arithmetic","operation","via","apex","library","can","significantly","reduce","the","training","time","making","this","one","of","the","fastest","adversarial","training","protocol","."]
docstr: Perform the operations of FBF for a batch of data.
  See class documentation for more information on the exact procedure.
  
  :param x_batch: batch of x.
  :param y_batch: batch of y.
  :param l_r: learning rate for the optimisation step.
docstr_tok: ["Perform","the","operations","of","FBF","for","a","batch","of","data",".","See","class","documentation","for","more","information","on","the","exact","procedure",".",":","param","x_batch",":","batch","of","x.",":","param","y_batch",":","batch","of","y.",":","param","l_r",":","learning","rate","for","the","optimisation","step","."]
code: def _batch_process(
      self, x_batch: np.ndarray, y_batch: np.ndarray, l_r: float
  ) -> Tuple[float, float, float]:
      """
      Perform the operations of FBF for a batch of data.
      See class documentation for more information on the exact procedure.
  
      :param x_batch: batch of x.
      :param y_batch: batch of y.
      :param l_r: learning rate for the optimisation step.
      """
      import torch
  
      if self._classifier._optimizer is None:  # pylint: disable=W0212
          raise ValueError(
              "Optimizer of classifier is currently None, but is required for adversarial training."
          )
  
      n = x_batch.shape[0]
      m = np.prod(x_batch.shape[1:]).item()
      delta = (
          random_sphere(n, m, self._eps, np.inf)
          .reshape(x_batch.shape)
          .astype(ART_NUMPY_DTYPE)
      )
      delta_grad = self._classifier.loss_gradient(
          x_batch + delta, y_batch
      )
      delta = np.clip(
          delta + 1.25 * self._eps * np.sign(delta_grad),
          -self._eps,
          +self._eps,
      )
      if self._classifier.clip_values is not None:
          x_batch_pert = np.clip(
              x_batch + delta,
              self._classifier.clip_values[0],
              self._classifier.clip_values[1],
          )
      else:
          x_batch_pert = x_batch + delta
  
      # Apply preprocessing
      (
          x_preprocessed,
          y_preprocessed,
      ) = self._classifier._apply_preprocessing(  # pylint: disable=W0212
          x_batch_pert, y_batch, fit=True
      )
  
      # Check label shape
      if self._classifier._reduce_labels:  # pylint: disable=W0212
          y_preprocessed = np.argmax(y_preprocessed, axis=1)
  
      i_batch = torch.from_numpy(x_preprocessed).to(
          self._classifier._device
      )  # pylint: disable=W0212
      o_batch = torch.from_numpy(y_preprocessed).to(
          self._classifier._device
      )  # pylint: disable=W0212
  
      # Zero the parameter gradients
      self._classifier._optimizer.zero_grad()  # pylint: disable=W0212
  
      # Perform prediction
      model_outputs = self._classifier._model(
          i_batch
      )  # pylint: disable=W0212
  
      # Form the loss function
      loss = self._classifier._loss(
          model_outputs[-1], o_batch
      )  # pylint: disable=W0212
  
      self._classifier._optimizer.param_groups[0].update(
          lr=l_r
      )  # pylint: disable=W0212
  
      # Actual training
      if self._use_amp:  # pragma: no cover
          from apex import amp  # pylint: disable=E0611
  
          with amp.scale_loss(
              loss, self._classifier._optimizer
          ) as scaled_loss:  # pylint: disable=W0212
              scaled_loss.backward()
      else:
          loss.backward()
  
      # clip the gradients
      torch.nn.utils.clip_grad_norm_(
          self._classifier._model.parameters(), 0.5
      )  # pylint: disable=W0212
      self._classifier._optimizer.step()  # pylint: disable=W0212
  
      train_loss = loss.item() * o_batch.size(0)
      train_acc = (model_outputs[0].max(1)[1] == o_batch).sum().item()
      train_n = o_batch.size(0)
  
      return train_loss, train_acc, train_n
  
file_path: adversarial-robustness-toolbox/art/defences/trainer/adversarial_trainer_fbf_pytorch.py
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import logging
  import time
  from typing import Optional, Tuple, Union, TYPE_CHECKING
  import numpy
  from tqdm.auto import trange
  from art.config import ART_NUMPY_DTYPE
  from art.defences.trainer.adversarial_trainer_fbf import AdversarialTrainerFBF
  from art.utils import random_sphere
label_desc: Use image node_id 4 for calling the AdversarialTrainerFBFPyTorch obj's underlying member method code with example usage: obj._batch_process(x_batch, y_batch, l_r) and returns: train_loss,  train_acc,  train_n