class_docstr: Class performing adversarial training based on a model architecture and one or multiple attack methods.
  
  Incorporates original adversarial training, ensemble adversarial training (https://arxiv.org/abs/1705.07204),
  training on all adversarial data and other common setups. If multiple attacks are specified, they are rotated
  for each batch. If the specified attacks have as target a different model, then the attack is transferred. The
  `ratio` determines how many of the clean samples in each batch are replaced with their adversarial counterpart.
  
   .. warning:: Both successful and unsuccessful adversarial samples are used for training. In the case of
                unbounded attacks (e.g., DeepFool), this can result in invalid (very noisy) samples being included.
  
  | Paper link: https://arxiv.org/abs/1705.07204
  
  | Please keep in mind the limitations of defences. While adversarial training is widely regarded as a promising,
      principled approach to making classifiers more robust (see https://arxiv.org/abs/1802.00420), very careful
      evaluations are required to assess its effectiveness case by case (see https://arxiv.org/abs/1902.06705).
docstr: Train a model adversarially. See class documentation for more information on the exact procedure.
  
  :param x: Training set.
  :param y: Labels for the training set.
  :param batch_size: Size of batches.
  :param nb_epochs: Number of epochs to use for trainings.
  :param kwargs: Dictionary of framework-specific arguments. These will be passed as such to the `fit` function of
         the target classifier.
code: def fit(  # pylint: disable=W0221
      self,
      x: np.ndarray,
      y: np.ndarray,
      batch_size: int = 128,
      nb_epochs: int = 20,
      **kwargs,
  ) -> None:
      """
      Train a model adversarially. See class documentation for more information on the exact procedure.
  
      :param x: Training set.
      :param y: Labels for the training set.
      :param batch_size: Size of batches.
      :param nb_epochs: Number of epochs to use for trainings.
      :param kwargs: Dictionary of framework-specific arguments. These will be passed as such to the `fit` function of
             the target classifier.
      """
      logger.info(
          "Performing adversarial training using %i attacks.",
          len(self.attacks),
      )
      nb_batches = int(np.ceil(len(x) / batch_size))
      ind = np.arange(len(x))
      attack_id = 0
  
      # Precompute adversarial samples for transferred attacks
      logged = False
      self._precomputed_adv_samples = []
      for attack in tqdm(self.attacks, desc="Precompute adv samples"):
          if "verbose" in attack.attack_params:
              attack.set_params(verbose=False)
          if "targeted" in attack.attack_params and attack.targeted:  # type: ignore
              raise NotImplementedError(
                  "Adversarial training with targeted attacks is currently not implemented"
              )
  
          if attack.estimator != self._classifier:
              if not logged:
                  logger.info(
                      "Precomputing transferred adversarial samples."
                  )
                  logged = True
              self._precomputed_adv_samples.append(
                  attack.generate(x, y=y)
              )
          else:
              self._precomputed_adv_samples.append(None)
  
      for _ in trange(nb_epochs, desc="Adversarial training epochs"):
          # Shuffle the examples
          np.random.shuffle(ind)
  
          for batch_id in range(nb_batches):
              # Create batch data
              x_batch = x[
                  ind[
                      batch_id
                      * batch_size : min(
                          (batch_id + 1) * batch_size, x.shape[0]
                      )
                  ]
              ].copy()
              y_batch = y[
                  ind[
                      batch_id
                      * batch_size : min(
                          (batch_id + 1) * batch_size, x.shape[0]
                      )
                  ]
              ]
  
              # Choose indices to replace with adversarial samples
              nb_adv = int(np.ceil(self.ratio * x_batch.shape[0]))
              attack = self.attacks[attack_id]
              if "verbose" in attack.attack_params:
                  attack.set_params(verbose=False)
              if self.ratio < 1:
                  adv_ids = np.random.choice(
                      x_batch.shape[0], size=nb_adv, replace=False
                  )
              else:
                  adv_ids = np.array(list(range(x_batch.shape[0])))
                  np.random.shuffle(adv_ids)
  
              # If source and target models are the same, craft fresh adversarial samples
              if attack.estimator == self._classifier:
                  x_batch[adv_ids] = attack.generate(
                      x_batch[adv_ids], y=y_batch[adv_ids]
                  )
  
              # Otherwise, use precomputed adversarial samples
              else:
                  x_adv = self._precomputed_adv_samples[attack_id]
                  if x_adv is not None:
                      x_adv = x_adv[
                          ind[
                              batch_id
                              * batch_size : min(
                                  (batch_id + 1) * batch_size,
                                  x.shape[0],
                              )
                          ]
                      ][adv_ids]
                  x_batch[adv_ids] = x_adv
  
              # Fit batch
              self._classifier.fit(
                  x_batch,
                  y_batch,
                  nb_epochs=1,
                  batch_size=x_batch.shape[0],
                  verbose=False,
                  **kwargs,
              )
              attack_id = (attack_id + 1) % len(self.attacks)
  
file_path: adversarial-robustness-toolbox/art/defences/trainer/adversarial_trainer.py
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import logging
  from typing import List, Optional, Union, TYPE_CHECKING
  import numpy
  from tqdm.auto import trange, tqdm
  from art.defences.trainer.trainer import Trainer
label_desc: Use image node_id 3 for calling the AdversarialTrainer obj's underlying member method code with example usage: obj.fit(x, y, batch_size, nb_epochs) without return types