class_docstr: Perturbation of pixels based on analysis result.
  
  :param perturbation_function:
      Defines the function with which the samples are perturbated.
      Can be a function or a string that defines a predefined perturbation function.
  :type perturbation_function:
      function or callable or str
  :param num_perturbed_regions:
      Number of regions to be perturbed.
  :type num_perturbed_regions:
      int
  :param reduce_function:
      Function to reduce the analysis result to one channel,
      e.g. mean or max function.
  :type reduce_function:
      function or callable
  :param aggregation_function:
      Function to aggregate the analysis over subregions.
  :type aggregation_function:
      function or callable
  :param pad_mode:
      How to pad if the image cannot be subdivided into an integer number of regions.
      As in numpy.pad.
  :type pad_mode:
      str or function or callable
  :param in_place:
      If true, the perturbations are performed in place,
      i.e. the input samples are modified.
  :type in_place:
      bool
  :param value_range:
      Minimal and maximal value after perturbation as a tuple:
      (min_val, max_val). The input is clipped to this range
  :type value_range: tuple
code: def __init__(
      self,
      perturbation_function,
      num_perturbed_regions=0,
      region_shape=(9, 9),
      reduce_function=np.mean,
      aggregation_function=np.mean,
      pad_mode="reflect",
      in_place=False,
      value_range=None,
  ):
      if isinstance(perturbation_function, str):
          if perturbation_function == "zeros":
              # This is equivalent to setting the perturbated values
              # to the channel mean if the data are standardized.
              self.perturbation_function = np.zeros_like
          elif perturbation_function == "gaussian":
              # If scale = 1/3, most of the values will be between -1 and 1
              self.perturbation_function = lambda x: np.random.normal(
                  loc=0.0, scale=0.3, size=x.shape
              )
          elif perturbation_function == "mean":
              self.perturbation_function = np.mean
          elif perturbation_function == "invert":
              self.perturbation_function = lambda x: -x
          else:
              raise ValueError(
                  f"Perturbation function type '{perturbation_function}' not known."
              )
      elif callable(perturbation_function):
          self.perturbation_function = perturbation_function
      else:
          raise TypeError(
              f"Cannot handle perturbation function of type {perturbation_function}."
          )
  
      self.num_perturbed_regions = num_perturbed_regions
      self.region_shape = region_shape
      self.reduce_function = reduce_function
      self.aggregation_function = aggregation_function
  
      self.pad_mode = pad_mode  # numpy.pad
  
      self.in_place = in_place
      self.value_range = value_range
  
imports: from __future__ import annotations
  import time
  import warnings
  import numpy
  import tensorflow.keras.backend
  import tensorflow.keras.utils
  import innvestigate.utils.sequence
label_desc: Use image node_id 1 to create a new Perturbation object  with example: obj = Perturbation(perturbation_function, num_perturbed_regions, region_shape, reduce_function, aggregation_function, pad_mode, in_place, value_range)