class_docstr: Interface class for the two De-randomized smoothing approaches supported by ART for pytorch.
  
  If a regular pytorch neural network is fed in then (De)Randomized Smoothing as introduced in Levine et al. (2020)
  is used.
  
  Otherwise, if a timm vision transfomer is fed in then Certified Patch Robustness via Smoothed Vision Transformers
  as introduced in Salman et al. (2021) is used.
docstr: Create a smoothed classifier.
  
  :param model: Either a CNN or a VIT. For a ViT supply a string specifying which ViT architecture to load from
                the ViT library, or a vision transformer already created with the
                Pytorch Image Models (timm) library. To run Levine et al. (2020) provide a regular pytorch model.
  :param loss: The loss function for which to compute gradients for training. The target label must be raw
               categorical, i.e. not converted to one-hot encoding.
  :param input_shape: The shape of one input instance.
  :param nb_classes: The number of classes of the model.
  :param ablation_size: The size of the data portion to retain after ablation.
  :param algorithm: Either 'salman2021' or 'levine2020'. For salman2021 we support ViTs and CNNs. For levine2020
                    there is only CNN support.
  :param replace_last_layer: ViT Specific. If to replace the last layer of the ViT with a fresh layer
                             matching the number of classes for the dataset to be examined.
                             Needed if going from the pre-trained imagenet models to fine-tune
                             on a dataset like CIFAR.
  :param drop_tokens: ViT Specific. If to drop the fully ablated tokens in the ViT
  :param load_pretrained: ViT Specific. If to load a pretrained model matching the ViT name.
                          Will only affect the ViT if a string name is passed to model rather than a ViT directly.
  :param optimizer: The optimizer used to train the classifier.
  :param ablation_type: The type of ablation to perform. Either "column", "row", or "block"
  :param threshold: Specific to Levine et al. The minimum threshold to count a prediction.
  :param logits: Specific to Levine et al. If the model returns logits or normalized probabilities
  :param channels_first: Set channels first or last.
  :param clip_values: Tuple of the form `(min, max)` of floats or `np.ndarray` representing the minimum and
         maximum values allowed for features. If floats are provided, these will be used as the range of all
         features. If arrays are provided, each value will be considered the bound for a feature, thus
         the shape of clip values needs to match the total number of features.
  :param preprocessing_defences: Preprocessing defence(s) to be applied by the classifier.
  :param postprocessing_defences: Postprocessing defence(s) to be applied by the classifier.
  :param preprocessing: Tuple of the form `(subtrahend, divisor)` of floats or `np.ndarray` of values to be
         used for data preprocessing. The first value will be subtracted from the input. The input will then
         be divided by the second one.
  :param device_type: Type of device on which the classifier is run, either `gpu` or `cpu`.
docstr_tok: ["Create","a","smoothed","classifier",".",":","param","model",":","Either","a","CNN","or","a","VIT",".","For","a","ViT","supply","a","string","specifying","which","ViT","architecture","to","load","from","the","ViT","library",",","or","a","vision","transformer","already","created","with","the","Pytorch","Image","Models","(","timm",")","library",".","To","run","Levine","et","al",".","(","2020",")","provide","a","regular","pytorch","model",".",":","param","loss",":","The","loss","function","for","which","to","compute","gradients","for","training",".","The","target","label","must","be","raw","categorical",",","i.e",".","not","converted","to","one-hot","encoding",".",":","param","input_shape",":","The","shape","of","one","input","instance",".",":","param","nb_classes",":","The","number","of","classes","of","the","model",".",":","param","ablation_size",":","The","size","of","the","data","portion","to","retain","after","ablation",".",":","param","algorithm",":","Either","'salman2021","'","or","'levine2020","'",".","For","salman2021","we","support","ViTs","and","CNNs",".","For","levine2020","there","is","only","CNN","support",".",":","param","replace_last_layer",":","ViT","Specific",".","If","to","replace","the","last","layer","of","the","ViT","with","a","fresh","layer","matching","the","number","of","classes","for","the","dataset","to","be","examined",".","Needed","if","going","from","the","pre-trained","imagenet","models","to","fine-tune","on","a","dataset","like","CIFAR",".",":","param","drop_tokens",":","ViT","Specific",".","If","to","drop","the","fully","ablated","tokens","in","the","ViT",":","param","load_pretrained",":","ViT","Specific",".","If","to","load","a","pretrained","model","matching","the","ViT","name",".","Will","only","affect","the","ViT","if","a","string","name","is","passed","to","model","rather","than","a","ViT","directly",".",":","param","optimizer",":","The","optimizer","used","to","train","the","classifier",".",":","param","ablation_type",":","The","type","of","ablation","to","perform",".","Either","``","column","''",",","``","row","''",",","or","``","block","''",":","param","threshold",":","Specific","to","Levine","et","al",".","The","minimum","threshold","to","count","a","prediction",".",":","param","logits",":","Specific","to","Levine","et","al",".","If","the","model","returns","logits","or","normalized","probabilities",":","param","channels_first",":","Set","channels","first","or","last",".",":","param","clip_values",":","Tuple","of","the","form","`","(","min",",","max",")","`","of","floats","or","`","np.ndarray","`","representing","the","minimum","and","maximum","values","allowed","for","features",".","If","floats","are","provided",",","these","will","be","used","as","the","range","of","all","features",".","If","arrays","are","provided",",","each","value","will","be","considered","the","bound","for","a","feature",",","thus","the","shape","of","clip","values","needs","to","match","the","total","number","of","features",".",":","param","preprocessing_defences",":","Preprocessing","defence","(","s",")","to","be","applied","by","the","classifier",".",":","param","postprocessing_defences",":","Postprocessing","defence","(","s",")","to","be","applied","by","the","classifier",".",":","param","preprocessing",":","Tuple","of","the","form","`","(","subtrahend",",","divisor",")","`","of","floats","or","`","np.ndarray","`","of","values","to","be","used","for","data","preprocessing",".","The","first","value","will","be","subtracted","from","the","input",".","The","input","will","then","be","divided","by","the","second","one",".",":","param","device_type",":","Type","of","device","on","which","the","classifier","is","run",",","either","`","gpu","`","or","`","cpu","`","."]
code: def __init__(
      self,
      model: Union[str, "VisionTransformer", "torch.nn.Module"],
      loss: "torch.nn.modules.loss._Loss",
      input_shape: Tuple[int, ...],
      nb_classes: int,
      ablation_size: int,
      algorithm: str = "salman2021",
      ablation_type: str = "column",
      replace_last_layer: Optional[bool] = None,
      drop_tokens: bool = True,
      load_pretrained: bool = True,
      optimizer: Union[type, "torch.optim.Optimizer", None] = None,
      optimizer_params: Optional[dict] = None,
      channels_first: bool = True,
      threshold: Optional[float] = None,
      logits: Optional[bool] = True,
      clip_values: Optional["CLIP_VALUES_TYPE"] = None,
      preprocessing_defences: Union[
          "Preprocessor", List["Preprocessor"], None
      ] = None,
      postprocessing_defences: Union[
          "Postprocessor", List["Postprocessor"], None
      ] = None,
      preprocessing: "PREPROCESSING_TYPE" = (0.0, 1.0),
      device_type: str = "gpu",
      verbose: bool = True,
      **kwargs,
  ):
      """
      Create a smoothed classifier.
  
      :param model: Either a CNN or a VIT. For a ViT supply a string specifying which ViT architecture to load from
                    the ViT library, or a vision transformer already created with the
                    Pytorch Image Models (timm) library. To run Levine et al. (2020) provide a regular pytorch model.
      :param loss: The loss function for which to compute gradients for training. The target label must be raw
                   categorical, i.e. not converted to one-hot encoding.
      :param input_shape: The shape of one input instance.
      :param nb_classes: The number of classes of the model.
      :param ablation_size: The size of the data portion to retain after ablation.
      :param algorithm: Either 'salman2021' or 'levine2020'. For salman2021 we support ViTs and CNNs. For levine2020
                        there is only CNN support.
      :param replace_last_layer: ViT Specific. If to replace the last layer of the ViT with a fresh layer
                                 matching the number of classes for the dataset to be examined.
                                 Needed if going from the pre-trained imagenet models to fine-tune
                                 on a dataset like CIFAR.
      :param drop_tokens: ViT Specific. If to drop the fully ablated tokens in the ViT
      :param load_pretrained: ViT Specific. If to load a pretrained model matching the ViT name.
                              Will only affect the ViT if a string name is passed to model rather than a ViT directly.
      :param optimizer: The optimizer used to train the classifier.
      :param ablation_type: The type of ablation to perform. Either "column", "row", or "block"
      :param threshold: Specific to Levine et al. The minimum threshold to count a prediction.
      :param logits: Specific to Levine et al. If the model returns logits or normalized probabilities
      :param channels_first: Set channels first or last.
      :param clip_values: Tuple of the form `(min, max)` of floats or `np.ndarray` representing the minimum and
             maximum values allowed for features. If floats are provided, these will be used as the range of all
             features. If arrays are provided, each value will be considered the bound for a feature, thus
             the shape of clip values needs to match the total number of features.
      :param preprocessing_defences: Preprocessing defence(s) to be applied by the classifier.
      :param postprocessing_defences: Postprocessing defence(s) to be applied by the classifier.
      :param preprocessing: Tuple of the form `(subtrahend, divisor)` of floats or `np.ndarray` of values to be
             used for data preprocessing. The first value will be subtracted from the input. The input will then
             be divided by the second one.
      :param device_type: Type of device on which the classifier is run, either `gpu` or `cpu`.
      """
  
      import torch
  
      if not channels_first:
          raise ValueError("Channels must be set to first")
      logger.info("Running algorithm: %s", algorithm)
  
      # Default value for output shape
      output_shape = input_shape
      self.mode = None
      if (
          importlib.util.find_spec("timm") is not None
          and algorithm == "salman2021"
      ):
          from timm.models.vision_transformer import VisionTransformer
  
          if isinstance(model, (VisionTransformer, str)):
              import timm
              from art.estimators.certification.derandomized_smoothing.vision_transformers.pytorch import (
                  PyTorchVisionTransformer,
              )
  
              if replace_last_layer is None:
                  raise ValueError(
                      "If using ViTs please specify if the last layer should be replaced"
                  )
  
              # temporarily assign the original method to tmp_func
              tmp_func = (
                  timm.models.vision_transformer._create_vision_transformer
              )
  
              # overrride with ART's ViT creation function
              timm.models.vision_transformer._create_vision_transformer = (
                  self.create_vision_transformer
              )
              if isinstance(model, str):
                  model = timm.create_model(
                      model,
                      pretrained=load_pretrained,
                      drop_tokens=drop_tokens,
                      device_type=device_type,
                  )
                  if replace_last_layer:
                      model.head = torch.nn.Linear(
                          model.head.in_features, nb_classes
                      )
                  if isinstance(optimizer, type):
                      if optimizer_params is not None:
                          optimizer = optimizer(
                              model.parameters(), **optimizer_params
                          )
                      else:
                          raise ValueError(
                              "If providing an optimiser please also supply its parameters"
                          )
  
              elif isinstance(model, VisionTransformer):
                  pretrained_cfg = model.pretrained_cfg
                  supplied_state_dict = model.state_dict()
                  supported_models = self.get_models()
                  if (
                      pretrained_cfg["architecture"]
                      not in supported_models
                  ):
                      raise ValueError(
                          "Architecture not supported. Use PyTorchDeRandomizedSmoothing.get_models() "
                          "to get the supported model architectures."
                      )
                  model = timm.create_model(
                      pretrained_cfg["architecture"],
                      drop_tokens=drop_tokens,
                      device_type=device_type,
                  )
                  model.load_state_dict(supplied_state_dict)
                  if replace_last_layer:
                      model.head = torch.nn.Linear(
                          model.head.in_features, nb_classes
                      )
  
                  if optimizer is not None:
                      if not isinstance(
                          optimizer, torch.optim.Optimizer
                      ):
                          raise ValueError(
                              "Optimizer error: must be a torch.optim.Optimizer instance"
                          )
  
                      converted_optimizer: Union[
                          torch.optim.Adam, torch.optim.SGD
                      ]
                      opt_state_dict = optimizer.state_dict()
                      if isinstance(optimizer, torch.optim.Adam):
                          logging.info("Converting Adam Optimiser")
                          converted_optimizer = torch.optim.Adam(
                              model.parameters(), lr=1e-4
                          )
                      elif isinstance(optimizer, torch.optim.SGD):
                          logging.info("Converting SGD Optimiser")
                          converted_optimizer = torch.optim.SGD(
                              model.parameters(), lr=1e-4
                          )
                      else:
                          raise ValueError(
                              "Optimiser not supported for conversion"
                          )
                      converted_optimizer.load_state_dict(
                          opt_state_dict
                      )
  
              self.to_reshape = False
              if not isinstance(model, PyTorchVisionTransformer):
                  raise ValueError(
                      "Vision transformer is not of PyTorchViT. Error occurred in PyTorchViT creation."
                  )
  
              if model.default_cfg["input_size"][0] != input_shape[0]:
                  raise ValueError(
                      f'ViT requires {model.default_cfg["input_size"][0]} channel input,'
                      f" but {input_shape[0]} channels were provided."
                  )
  
              if model.default_cfg["input_size"] != input_shape:
                  if verbose:
                      logger.warning(
                          " ViT expects input shape of: (%i, %i, %i) but (%i, %i, %i) specified as the input shape."
                          " The input will be rescaled to (%i, %i, %i)",
                          *model.default_cfg["input_size"],
                          *input_shape,
                          *model.default_cfg["input_size"],
                      )
  
                  self.to_reshape = True
              output_shape = model.default_cfg["input_size"]
  
              # set the method back to avoid unexpected side effects later on should timm need to be reused.
              timm.models.vision_transformer._create_vision_transformer = (
                  tmp_func
              )
              self.mode = "ViT"
          else:
              if isinstance(model, torch.nn.Module):
                  self.mode = "CNN"
                  output_shape = input_shape
                  self.to_reshape = False
  
      elif algorithm == "levine2020":
          if (
              ablation_type is None
              or threshold is None
              or logits is None
          ):
              raise ValueError(
                  "If using CNN please specify if the model returns logits, "
                  " the prediction threshold, and ablation type"
              )
          self.mode = "CNN"
          # input channels are internally doubled.
          input_shape = (
              input_shape[0] * 2,
              input_shape[1],
              input_shape[2],
          )
          output_shape = input_shape
          self.to_reshape = False
  
      if optimizer is None or isinstance(
          optimizer, torch.optim.Optimizer
      ):
          super().__init__(
              model=model,
              loss=loss,
              input_shape=input_shape,
              nb_classes=nb_classes,
              optimizer=optimizer,
              channels_first=channels_first,
              clip_values=clip_values,
              preprocessing_defences=preprocessing_defences,
              postprocessing_defences=postprocessing_defences,
              preprocessing=preprocessing,
              device_type=device_type,
          )
      else:
          raise ValueError("Error occurred in optimizer creation")
  
      self.threshold = threshold
      self.logits = logits
      self.ablation_size = (ablation_size,)
      self.algorithm = algorithm
      self.ablation_type = ablation_type
      if verbose:
          logger.info(self.model)
  
      from art.estimators.certification.derandomized_smoothing.ablators.pytorch import (
          ColumnAblatorPyTorch,
          BlockAblatorPyTorch,
      )
  
      if TYPE_CHECKING:
          self.ablator: Union[ColumnAblatorPyTorch, BlockAblatorPyTorch]
  
      if self.mode is None:
          raise ValueError("Model type not recognized.")
  
      if ablation_type in {"column", "row"}:
          self.ablator = ColumnAblatorPyTorch(
              ablation_size=ablation_size,
              channels_first=True,
              ablation_mode=ablation_type,
              to_reshape=self.to_reshape,
              original_shape=input_shape,
              output_shape=output_shape,
              device_type=device_type,
              algorithm=algorithm,
              mode=self.mode,
          )
      elif ablation_type == "block":
          self.ablator = BlockAblatorPyTorch(
              ablation_size=ablation_size,
              channels_first=True,
              to_reshape=self.to_reshape,
              original_shape=input_shape,
              output_shape=output_shape,
              device_type=device_type,
              algorithm=algorithm,
              mode=self.mode,
          )
      else:
          raise ValueError(
              f"ablation_type of {ablation_type} not recognized. Must be either column, row, or block"
          )
  
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import importlib
  import logging
  from typing import List, Optional, Tuple, Union, Any, TYPE_CHECKING
  import random
  import numpy
  from tqdm import tqdm
  from art.estimators.classification.pytorch import PyTorchClassifier
  from art.estimators.certification.derandomized_smoothing.derandomized import DeRandomizedSmoothingMixin
  from art.utils import check_and_transform_label_format
label_desc: Use image node_id 1 to create a new PyTorchDeRandomizedSmoothing object from inherited base classes: DeRandomizedSmoothingMixin, PyTorchClassifier with example: obj = PyTorchDeRandomizedSmoothing(model, loss, input_shape, nb_classes, ablation_size, algorithm, ablation_type, replace_last_layer, drop_tokens, load_pretrained, optimizer, optimizer_params, channels_first, threshold, logits, clip_values, preprocessing_defences, postprocessing_defences, preprocessing, device_type, verbose)