def class_gradient(
        self,
        x: np.ndarray,
        label: int | list[int] | np.ndarray | None = None,
        training_mode: bool = False,
        raw: bool = False,
        **kwargs,
    ) -> np.ndarray:
        """
        Compute per-class derivatives w.r.t. `x`.

        :param x: Sample input with shape as expected by the model.
        :param label: Index of a specific per-class derivative. If `None`, then gradients for all classes will be
                      computed.
        :param training_mode: `True` for model set to training mode and `False` for model set to evaluation mode.
        :param raw: Return the individual classifier raw outputs (not aggregated).
        :return: Array of gradients of input features w.r.t. each class in the form
                 `(batch_size, nb_classes, input_shape)` when computing for all classes, otherwise shape becomes
                 `(batch_size, 1, input_shape)` when `label` parameter is specified. If `raw=True`, an additional
                 dimension is added at the beginning of the array, indexing the different classifiers.
        """
        grads = np.array(
            [
                self.classifier_weights[i]
                * self.classifiers[i].class_gradient(x=x, label=label, training_mode=training_mode, **kwargs)
                for i in range(self._nb_classifiers)
            ]
        )
        if raw:
            return grads

        return np.sum(grads, axis=0)

        Compute per-class derivatives w.r.t. `x`.

        :param x: Sample input with shape as expected by the model.
        :param label: Index of a specific per-class derivative. If `None`, then gradients for all classes will be
                      computed.
        :param training_mode: `True` for model set to training mode and `False` for model set to evaluation mode.
        :param raw: Return the individual classifier raw outputs (not aggregated).
        :return: Array of gradients of input features w.r.t. each class in the form
                 `(batch_size, nb_classes, input_shape)` when computing for all classes, otherwise shape becomes
                 `(batch_size, 1, input_shape)` when `label` parameter is specified. If `raw=True`, an additional
                 dimension is added at the beginning of the array, indexing the different classifiers.
        
art/estimators/classification/ensemble.py