class_docstr: Class allowing to aggregate multiple classifiers as an ensemble. The individual classifiers are expected to be
  trained when the ensemble is created and no training procedures are provided through this class.
docstr: Initialize a :class:`.EnsembleClassifier` object. The data range values and colour channel index have to
  be consistent for all the classifiers in the ensemble.
  
  :param classifiers: List of :class:`.Classifier` instances to be ensembled together.
  :param classifier_weights: List of weights, one scalar per classifier, to assign to their prediction when
         aggregating results. If `None`, all classifiers are assigned the same weight.
  :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. Not applicable
         in this 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. Not applicable in this classifier.
docstr_tok: ["Initialize","a",":","class",":","`",".EnsembleClassifier","`","object",".","The","data","range","values","and","colour","channel","index","have","to","be","consistent","for","all","the","classifiers","in","the","ensemble",".",":","param","classifiers",":","List","of",":","class",":","`",".Classifier","`","instances","to","be","ensembled","together",".",":","param","classifier_weights",":","List","of","weights",",","one","scalar","per","classifier",",","to","assign","to","their","prediction","when","aggregating","results",".","If","`","None","`",",","all","classifiers","are","assigned","the","same","weight",".",":","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",".","Not","applicable","in","this","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",".","Not","applicable","in","this","classifier","."]
code: def __init__(
      self,
      classifiers: List["CLASSIFIER_NEURALNETWORK_TYPE"],
      classifier_weights: Union[list, np.ndarray, None] = None,
      channels_first: bool = False,
      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),
  ) -> None:
      """
      Initialize a :class:`.EnsembleClassifier` object. The data range values and colour channel index have to
      be consistent for all the classifiers in the ensemble.
  
      :param classifiers: List of :class:`.Classifier` instances to be ensembled together.
      :param classifier_weights: List of weights, one scalar per classifier, to assign to their prediction when
             aggregating results. If `None`, all classifiers are assigned the same weight.
      :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. Not applicable
             in this 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. Not applicable in this classifier.
      """
      if preprocessing_defences is not None:
          raise NotImplementedError(
              "Preprocessing is not applicable in this classifier."
          )
  
      super().__init__(
          model=None,
          clip_values=clip_values,
          channels_first=channels_first,
          preprocessing_defences=preprocessing_defences,
          postprocessing_defences=postprocessing_defences,
          preprocessing=preprocessing,
      )
      self._nb_classifiers = len(classifiers)
  
      # Assert all classifiers are the right shape(s)
      for classifier in classifiers:
          if not isinstance(
              classifier, NeuralNetworkMixin
          ):  # pragma: no cover
              raise TypeError(
                  f"Expected type `Classifier`, found {type(classifier)} instead."
              )
  
          if (
              isinstance(classifier.clip_values, np.ndarray)
              and isinstance(self.clip_values, np.ndarray)
              and not np.array_equal(
                  self.clip_values, classifier.clip_values
              )
          ):  # pragma: no cover
              raise ValueError(
                  f"Incompatible `clip_values` between classifiers in the ensemble. Found {self.clip_values} and "
                  f"{classifier.clip_values}."
              )
  
          if (
              classifier.nb_classes != classifiers[0].nb_classes
          ):  # pragma: no cover
              raise ValueError(
                  f"Incompatible output shapes between classifiers in the ensemble. Found {classifier.nb_classes} "
                  f"and {classifiers[0].nb_classes}."
              )
  
          if (
              classifier.input_shape != classifiers[0].input_shape
          ):  # pragma: no cover
              raise ValueError(
                  f"Incompatible input shapes between classifiers in the ensemble. Found {classifier.input_shape} "
                  f"and {classifiers[0].input_shape}."
              )
  
      self._input_shape = classifiers[0].input_shape
      self.nb_classes = classifiers[0].nb_classes
  
      # Set weights for classifiers
      if classifier_weights is None:
          self._classifier_weights = (
              np.ones(self._nb_classifiers) / self._nb_classifiers
          )
      else:
          self._classifier_weights = np.array(classifier_weights)
  
      # check for consistent channels_first in ensemble members
      for i_cls, cls in enumerate(classifiers):
          if (
              cls.channels_first != self.channels_first
          ):  # pragma: no cover
              raise ValueError(
                  f"The channels_first boolean of classifier {i_cls} is {cls.channels_first} while this ensemble "
                  f"expects a channels_first boolean of {self.channels_first}. The channels_first booleans of all "
                  f"classifiers and the ensemble need ot be identical."
              )
  
      self._classifiers = classifiers
  
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import logging
  from typing import List, Optional, Union, Tuple, TYPE_CHECKING
  import numpy
  from art.estimators.classification.classifier import ClassifierNeuralNetwork
  from art.estimators.estimator import NeuralNetworkMixin
label_desc: Use image node_id 1 to create a new EnsembleClassifier object from inherited base classes: ClassifierNeuralNetwork with example: obj = EnsembleClassifier(classifiers, classifier_weights, channels_first, clip_values, preprocessing_defences, postprocessing_defences, preprocessing)