class_docstr: Class performing adversarial training following Oracle Aligned Adversarial Training (OAAT) protocol.
  
  | Paper link: https://link.springer.com/chapter/10.1007/978-3-031-20065-6_18
class_docstr_tok: ["Class","performing","adversarial","training","following","Oracle","Aligned","Adversarial","Training","(","OAAT",")","protocol",".","|","Paper","link",":","https",":","\/\/link.springer.com\/chapter\/10.1007\/978-3-031-20065-6_18"]
docstr: Return the output of the specified layers for input `x`. `layers` is a list of either layer indices (between 0
  and `nb_layers - 1`) or layers' name. The number of layers can be determined by counting the results returned by
  calling `layer_names`.
  
  :param p_classifier: model for adversarial training protocol.
  :param x: Input for computing the activations.
  :param layers: Layers for computing the activations
  :return: Tuple containing the output dict and a list of layers' names. In dictionary each element is a
           layer's output where the first dimension is the batch size corresponding to `x'.
docstr_tok: ["Return","the","output","of","the","specified","layers","for","input","`","x","`",".","`","layers","`","is","a","list","of","either","layer","indices","(","between","0","and","`","nb_layers","-","1","`",")","or","layers","'","name",".","The","number","of","layers","can","be","determined","by","counting","the","results","returned","by","calling","`","layer_names","`",".",":","param","p_classifier",":","model","for","adversarial","training","protocol",".",":","param","x",":","Input","for","computing","the","activations",".",":","param","layers",":","Layers","for","computing","the","activations",":","return",":","Tuple","containing","the","output","dict","and","a","list","of","layers","'","names",".","In","dictionary","each","element","is","a","layer","'s","output","where","the","first","dimension","is","the","batch","size","corresponding","to","`","x","'","."]
code: def get_layer_activations(  # type: ignore
      p_classifier: PyTorchClassifier,
      x: "torch.Tensor",
      layers: List[Union[int, str]],
  ) -> Tuple[Dict[str, "torch.Tensor"], List[str]]:
      """
      Return the output of the specified layers for input `x`. `layers` is a list of either layer indices (between 0
      and `nb_layers - 1`) or layers' name. The number of layers can be determined by counting the results returned by
      calling `layer_names`.
  
      :param p_classifier: model for adversarial training protocol.
      :param x: Input for computing the activations.
      :param layers: Layers for computing the activations
      :return: Tuple containing the output dict and a list of layers' names. In dictionary each element is a
               layer's output where the first dimension is the batch size corresponding to `x'.
      """
  
      p_classifier.model.train(mode=False)
  
      list_layer_names = []
      for layer in layers:
          if isinstance(layer, six.string_types):
              if (
                  layer not in p_classifier._layer_names
              ):  # pylint: disable=W0212
                  raise ValueError(f"Layer name {layer} not supported")
              layer_name = layer
              list_layer_names.append(layer_name)
  
          elif isinstance(layer, int):
              layer_index = layer
              layer_name = p_classifier._layer_names[
                  layer_index
              ]  # pylint: disable=W0212
              list_layer_names.append(layer_name)
  
          else:
              raise TypeError("Layer must be of type str or int")
  
      def get_feature(name):
          # the hook signature
          def hook(model, input, output):  # pylint: disable=W0622,W0613
              p_classifier._features[
                  name
              ] = output  # pylint: disable=W0212
  
          return hook
  
      if not hasattr(p_classifier, "_features"):
          p_classifier._features = {}  # pylint: disable=W0212
          # register forward hooks on the layers of choice
  
      for layer_name in list_layer_names:
          if (
              layer_name not in p_classifier._features
          ):  # pylint: disable=W0212
              interim_layer = dict(
                  [*p_classifier._model._model.named_modules()]
              )[
                  layer_name
              ]  # pylint: disable=W0212
              interim_layer.register_forward_hook(
                  get_feature(layer_name)
              )
  
      p_classifier.model(x)
      return p_classifier._features, list_layer_names
  
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  from collections import OrderedDict
  import logging
  import os
  import time
  from typing import Optional, Tuple, TYPE_CHECKING, List, Dict, Union
  import six
  import numpy
  from tqdm.auto import trange
  from art import config
  from art.defences.trainer.adversarial_trainer_oaat import AdversarialTrainerOAAT
  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, random_sphere
  from art.config import ART_NUMPY_DTYPE
label_desc: Use image node_id 8 for calling the AdversarialTrainerOAATPyTorch obj's underlying member method code with example usage: obj.get_layer_activations(p_classifier, x, layers) and returns: p_classifier,  list_layer_names, hook