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

        :param x: Samples of shape `(nb_samples)`. Note that, it is allowable that sequences in the batch
                  could have different lengths. A possible example of `x` could be:
                  `x = np.ndarray([[0.1, 0.2, 0.1, 0.4], [0.3, 0.1]])`.
        :param y: Target values of shape (nb_samples). Each sample in `y` is a string, and it may possess different
                  lengths. A possible example of `y` could be: `y = np.array(['SIXTY ONE', 'HELLO'])`.
        :param batch_mode: If `True` calculate gradient per batch or otherwise per sequence.
        :return: Loss gradients of the same shape as `x`.
        """
        # if inputs have 32-bit floating point wav format, the preprocessing argument is required
        is_normalized = max(map(max, np.abs(x))) <= 1.0  # type: ignore
        if is_normalized and self.preprocessing is None:
            raise ValueError(
                "The LingvoASR estimator requires input values in the range [-32768, 32767] or normalized input values"
                " with correct preprocessing argument (mean=0, stddev=1/normalization_factor)."
            )

        # Lingvo model works with lower case transcriptions
        y = np.array([y_i.lower() for y_i in y])

        # Apply preprocessing
        x_preprocessed, y_preprocessed = self._apply_preprocessing(x, y, fit=False)

        if batch_mode:
            gradients = self._loss_gradient_per_batch(x_preprocessed, y_preprocessed)
        else:
            gradients = self._loss_gradient_per_sequence(x_preprocessed, y_preprocessed)

        # Apply preprocessing gradients
        gradients = self._apply_preprocessing_gradient(x, gradients)
        return gradients

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

        :param x: Samples of shape `(nb_samples)`. Note that, it is allowable that sequences in the batch
                  could have different lengths. A possible example of `x` could be:
                  `x = np.ndarray([[0.1, 0.2, 0.1, 0.4], [0.3, 0.1]])`.
        :param y: Target values of shape (nb_samples). Each sample in `y` is a string, and it may possess different
                  lengths. A possible example of `y` could be: `y = np.array(['SIXTY ONE', 'HELLO'])`.
        :param batch_mode: If `True` calculate gradient per batch or otherwise per sequence.
        :return: Loss gradients of the same shape as `x`.
        
art/estimators/speech_recognition/tensorflow_lingvo.py