def loss_gradient(
        self, x: np.ndarray, y: np.ndarray, training_mode: bool = False, raw: bool = False, **kwargs
    ) -> np.ndarray:
        """
        Compute the gradient of the loss function w.r.t. `x`.

        :param x: Sample input with shape as expected by the model.
        :param y: Target values (class labels) one-hot-encoded of shape (nb_samples, nb_classes) or indices of shape
                  (nb_samples,).
        :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 the same shape as `x`. If `raw=True`, shape becomes `[nb_classifiers, x.shape]`.
        """
        grads = np.array(
            [
                self.classifier_weights[i]
                * self.classifiers[i].loss_gradient(x=x, y=y, training_mode=training_mode, **kwargs)
                for i in range(self._nb_classifiers)
            ]
        )
        if raw:
            return grads

        return np.sum(grads, axis=0)

        Compute the gradient of the loss function w.r.t. `x`.

        :param x: Sample input with shape as expected by the model.
        :param y: Target values (class labels) one-hot-encoded of shape (nb_samples, nb_classes) or indices of shape
                  (nb_samples,).
        :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 the same shape as `x`. If `raw=True`, shape becomes `[nb_classifiers, x.shape]`.
        
art/estimators/classification/ensemble.py