def __init__(
        self,
        classifiers: list["CLASSIFIER_NEURALNETWORK_TYPE"],
        classifier_weights: list | np.ndarray | None = None,
        channels_first: bool = False,
        clip_values: "CLIP_VALUES_TYPE" | None = None,
        preprocessing_defences: "Preprocessor" | list["Preprocessor"] | None = None,
        postprocessing_defences: "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

        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.
        
art/estimators/classification/ensemble.py