class_docstr: Class performing adversarial training following Adversarial Weight Perturbation (AWP) protocol.
  
  | Paper link: https://proceedings.neurips.cc/paper/2020/file/1ef91c212e30e14bf125e9374262401f-Paper.pdf
class_docstr_tok: ["Class","performing","adversarial","training","following","Adversarial","Weight","Perturbation","(","AWP",")","protocol",".","|","Paper","link",":","https",":","\/\/proceedings.neurips.cc\/paper\/2020\/file\/1ef91c212e30e14bf125e9374262401f-Paper.pdf"]
docstr: Perform the operations of AWP 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.
  :return: tuple containing batch data loss, batch data accuracy and number of samples in the batch
docstr_tok: ["Perform","the","operations","of","AWP","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.",":","return",":","tuple","containing","batch","data","loss",",","batch","data","accuracy","and","number","of","samples","in","the","batch"]
code: def _batch_process(
      self, x_batch: np.ndarray, y_batch: np.ndarray
  ) -> Tuple[float, float, float]:
      """
      Perform the operations of AWP 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.
      :return: tuple containing batch data loss, batch data accuracy and number of samples in the batch
      """
      import torch
      from torch import nn
      import torch.nn.functional as F
  
      if self._classifier.optimizer is None:
          raise ValueError(
              "Optimizer of classifier is currently None, but is required for adversarial training."
          )
  
      if self._proxy_classifier.optimizer is None:
          raise ValueError(
              "Optimizer of proxy classifier is currently None, but is required for adversarial training."
          )
  
      self._classifier.model.train(mode=False)
      x_batch_pert = self._attack.generate(x_batch, y=y_batch)
  
      # Apply preprocessing
      y_batch = check_and_transform_label_format(
          y_batch, nb_classes=self.classifier.nb_classes
      )
  
      (
          x_preprocessed,
          y_preprocessed,
      ) = self._classifier._apply_preprocessing(  # pylint: disable=W0212
          x_batch, y_batch, fit=True
      )
      (
          x_preprocessed_pert,
          _,
      ) = 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
      )
      i_batch_pert = torch.from_numpy(x_preprocessed_pert).to(
          self._classifier.device
      )
      o_batch = torch.from_numpy(y_preprocessed).to(
          self._classifier.device
      )
  
      self._classifier.model.train(mode=True)
  
      if self._apply_wp:
          w_perturb = self._weight_perturbation(
              x_batch=i_batch,
              x_batch_pert=i_batch_pert,
              y_batch=o_batch,
          )
          list_keys = list(w_perturb.keys())
          self._modify_classifier(
              self._classifier, list_keys, w_perturb, op="add"
          )
  
      # Zero the parameter gradients
      self._classifier.optimizer.zero_grad()
  
      if self._mode.lower() == "pgd":
          # Perform prediction
          model_outputs_pert = self._classifier.model(i_batch_pert)
          loss = self._classifier.loss(model_outputs_pert, o_batch)
  
      elif self._mode.lower() == "trades":
          n = x_batch.shape[0]
          # Perform prediction
          model_outputs = self._classifier.model(i_batch)
          model_outputs_pert = self._classifier.model(i_batch_pert)
  
          # Form the loss function
          loss_clean = self._classifier.loss(model_outputs, o_batch)
          loss_kl = (1.0 / n) * nn.KLDivLoss(reduction="sum")(
              F.log_softmax(model_outputs_pert, dim=1),
              torch.clamp(F.softmax(model_outputs, dim=1), min=EPS),
          )
          loss = loss_clean + self._beta * loss_kl
  
      else:
          raise ValueError(
              "Incorrect mode provided for base adversarial training. 'mode' must be among 'PGD' and 'TRADES'."
          )
  
      loss.backward()
  
      self._classifier.optimizer.step()
  
      if self._apply_wp:
          self._modify_classifier(
              self._classifier, list_keys, w_perturb, op="subtract"
          )
  
      train_loss = loss.item() * o_batch.size(0)
      train_acc = (model_outputs_pert.max(1)[1] == o_batch).sum().item()
      train_n = o_batch.size(0)
  
      self._classifier.model.train(mode=False)
  
      return train_loss, train_acc, train_n
  
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import logging
  import time
  from typing import Optional, Tuple, TYPE_CHECKING, List, Dict
  from collections import OrderedDict
  import numpy
  from tqdm.auto import trange
  from art.defences.trainer.adversarial_trainer_awp import AdversarialTrainerAWP
  from art.estimators.classification.pytorch import PyTorchClassifier
  from art.data_generators import DataGenerator
  from art.attacks.attack import EvasionAttack
  from art.utils import check_and_transform_label_format
label_desc: Use image node_id 4 for calling the AdversarialTrainerAWPPyTorch obj's underlying member method code with example usage: obj._batch_process(x_batch, y_batch) and returns: train_loss,  train_acc,  train_n