class_docstr: Performs the perturbation analysis.
  
  :param analyzer: Analyzer.
  :type analyzer: innvestigate.analyzer.base.AnalyzerBase
  :param model: Trained Keras model.
  :param generator: Data generator.
  :type generator: innvestigate.sequence.BatchSequence
  :param perturbation: Instance of Perturbation class that performs the perturbation.
  :type perturbation: innvestigate.tools.Perturbation
  :param steps: Number of perturbation steps.
  :type steps: int
  :param regions_per_step: Number of regions that are perturbed per step.
  :type regions_per_step: float
  :param recompute_analysis:
      If true, the analysis is recomputed after each perturbation step.
  :type recompute_analysis: bool
  :param verbose: If true, print some useful information, e.g. timing, progress etc.
docstr: Evaluates the model on a data generator.
  
  The generator should return the same kind of data
  as accepted by `test_on_batch`.
  For documentation, refer to keras.engine.training.evaluate_generator
  (https://keras.io/models/model/)
docstr_tok: ["Evaluates","the","model","on","a","data","generator",".","The","generator","should","return","the","same","kind","of","data","as","accepted","by","`","test_on_batch","`",".","For","documentation",",","refer","to","keras.engine.training.evaluate_generator","(","https",":","\/\/keras.io\/models\/model\/",")"]
code: def evaluate_generator(
      self,
      generator,
      steps=None,
      max_queue_size=10,
      workers=1,
      use_multiprocessing=False,
  ):
      """Evaluates the model on a data generator.
  
      The generator should return the same kind of data
      as accepted by `test_on_batch`.
      For documentation, refer to keras.engine.training.evaluate_generator
      (https://keras.io/models/model/)
      """
  
      steps_done = 0
      all_outs = []
      batch_sizes = []
      is_sequence = isinstance(generator, kutils.Sequence)
      if not is_sequence and use_multiprocessing and workers > 1:
          warnings.warn(
              UserWarning(
                  "Using a generator with `use_multiprocessing=True`"
                  " and multiple workers may duplicate your data."
                  " Please consider using the`keras.utils.Sequence"
                  " class."
              )
          )
      if steps is None:
          if is_sequence:
              steps = len(generator)
          else:
              raise ValueError(
                  "`steps=None` is only valid for a generator"
                  " based on the `keras.utils.Sequence` class."
                  " Please specify `steps` or use the"
                  " `keras.utils.Sequence` class."
              )
      enqueuer = None
  
      try:
          if workers > 0:
              if is_sequence:
                  enqueuer = kutils.OrderedEnqueuer(
                      generator, use_multiprocessing=use_multiprocessing
                  )
              else:
                  enqueuer = kutils.GeneratorEnqueuer(
                      generator,
                      use_multiprocessing=use_multiprocessing,
                  )
              enqueuer.start(
                  workers=workers, max_queue_size=max_queue_size
              )
              output_generator = enqueuer.get()
          else:
              output_generator = generator
  
          while steps_done < steps:
              generator_output = next(output_generator)
              if not hasattr(generator_output, "__len__"):
                  raise ValueError(
                      "Output of generator should be a tuple "
                      "(x, y, sample_weight) "
                      "or (x, y). Found: " + str(generator_output)
                  )
              if len(generator_output) == 2:
                  x, y = generator_output
                  analysis = None
              elif len(generator_output) == 3:
                  x, y, analysis = generator_output
              else:
                  raise ValueError(
                      "Output of generator should be a tuple "
                      "(x, y, analysis) "
                      "or (x, y). Found: " + str(generator_output)
                  )
              outs = self.evaluate_on_batch(
                  x, y, analysis=analysis, sample_weight=None
              )
  
              if isinstance(x, list):
                  batch_size = x[0].shape[0]
              elif isinstance(x, dict):
                  batch_size = list(x.values())[0].shape[0]
              else:
                  batch_size = x.shape[0]
              if batch_size == 0:
                  raise ValueError(
                      "Received an empty batch. "
                      "Batches should at least contain one item."
                  )
              all_outs.append(outs)
  
              steps_done += 1
              batch_sizes.append(batch_size)
  
      finally:
          if enqueuer is not None:
              enqueuer.stop()
  
      if not isinstance(outs, list):
          return np.average(np.asarray(all_outs), weights=batch_sizes)
      averages = []
      for i in range(len(outs)):
          averages.append(
              np.average(
                  [out[i] for out in all_outs], weights=batch_sizes
              )
          )
      return averages
  
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 4 for calling the PerturbationAnalysis obj's underlying member method code with example usage: obj.evaluate_generator(generator, steps, max_queue_size, workers, use_multiprocessing) and returns: averages, np