def loss_gradient(self, x: np.ndarray, y: np.ndarray, **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,)`.
        :return: Array of gradients of the same shape as `x`.
        """
        # Apply preprocessing
        x_preprocessed, _ = self._apply_preprocessing(x, y, fit=False)

        eps = 0.00001
        grads = np.zeros(np.shape(x))
        for i in range(np.shape(x)[0]):
            # 1.0 - to mimic loss, [0,np.argmax] to get right class
            ind = 1.0 - self.predict(x_preprocessed[i].reshape(1, -1))[0, np.argmax(y[i])]
            sur = (
                1.0
                - self.predict(
                    np.repeat(x_preprocessed[i].reshape(1, -1), np.shape(x_preprocessed)[1], 0)
                    + eps * np.eye(np.shape(x_preprocessed)[1])
                )[:, np.argmax(y[i])]
            )
            grads[i] = ((sur - ind) * eps).reshape(1, -1)

        grads = self._apply_preprocessing_gradient(x, grads)

        return grads

        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,)`.
        :return: Array of gradients of the same shape as `x`.
        
art/estimators/classification/GPy.py