class_docstr: This class implements a regressor with the PyTorch framework.
class_docstr_tok: ["This","class","implements","a","regressor","with","the","PyTorch","framework","."]
docstr: 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.
                        Note on RNN-like models: Backpropagation through RNN modules in eval mode raises
                        RuntimeError due to cudnn issues and require training mode, i.e. RuntimeError: cudnn RNN
                        backward can only be called in training mode. Therefore, if the model is an RNN type we
                        always use training mode but freeze batch-norm and dropout layers if
                        `training_mode=False.`
  :return: Array of gradients of the same shape as `x`.
docstr_tok: ["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",".","Note","on","RNN-like","models",":","Backpropagation","through","RNN","modules","in","eval","mode","raises","RuntimeError","due","to","cudnn","issues","and","require","training","mode",",","i.e",".","RuntimeError",":","cudnn","RNN","backward","can","only","be","called","in","training","mode",".","Therefore",",","if","the","model","is","an","RNN","type","we","always","use","training","mode","but","freeze","batch-norm","and","dropout","layers","if","`","training_mode=False.","`",":","return",":","Array","of","gradients","of","the","same","shape","as","`","x","`","."]
code: def loss_gradient(  # pylint: disable=W0221
      self,
      x: Union[np.ndarray, "torch.Tensor"],
      y: Union[np.ndarray, "torch.Tensor"],
      training_mode: bool = False,
      **kwargs,
  ) -> Union[np.ndarray, "torch.Tensor"]:
      """
      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.
                            Note on RNN-like models: Backpropagation through RNN modules in eval mode raises
                            RuntimeError due to cudnn issues and require training mode, i.e. RuntimeError: cudnn RNN
                            backward can only be called in training mode. Therefore, if the model is an RNN type we
                            always use training mode but freeze batch-norm and dropout layers if
                            `training_mode=False.`
      :return: Array of gradients of the same shape as `x`.
      """
      import torch
  
      self._model.train(mode=training_mode)
  
      # Backpropagation through RNN modules in eval mode raises RuntimeError due to cudnn issues and require training
      # mode, i.e. RuntimeError: cudnn RNN backward can only be called in training mode. Therefore, if the model is
      # an RNN type we always use training mode but freeze batch-norm and dropout layers if training_mode=False.
      if self.is_rnn:
          self._model.train(mode=True)
          if not training_mode:
              logger.debug(
                  "Freezing batch-norm and dropout layers for gradient calculation in train mode with eval parameters"
                  "of batch-norm and dropout."
              )
              self.set_batchnorm(train=False)
              self.set_dropout(train=False)
  
      # Apply preprocessing
      if self.all_framework_preprocessing:
          if isinstance(x, torch.Tensor):
              x_grad = x.clone().detach().requires_grad_(True)
          else:
              x_grad = torch.tensor(x).to(self._device)
              x_grad.requires_grad = True
          if isinstance(y, torch.Tensor):
              y_grad = y.clone().detach()
          else:
              y_grad = torch.tensor(y).to(self._device)
          inputs_t, y_preprocessed = self._apply_preprocessing(
              x_grad, y=y_grad, fit=False, no_grad=False
          )
      elif isinstance(x, np.ndarray):
          x_preprocessed, y_preprocessed = self._apply_preprocessing(
              x, y=y, fit=False, no_grad=True
          )
          x_grad = torch.from_numpy(x_preprocessed).to(self._device)
          x_grad.requires_grad = True
          inputs_t = x_grad
      else:
          raise NotImplementedError(
              "Combination of inputs and preprocessing not supported."
          )
  
      # Check label shape
      # y_preprocessed = self.reduce_labels(y_preprocessed)
  
      if isinstance(y_preprocessed, np.ndarray):
          labels_t = torch.from_numpy(y_preprocessed).to(self._device)
      else:
          labels_t = y_preprocessed
  
      # Compute the gradient and return
      model_outputs = self._model(inputs_t)
      loss = self._loss(
          model_outputs[-1].reshape(
              -1,
          ),
          labels_t,
      )
  
      # Clean gradients
      self._model.zero_grad()
  
      # Compute gradients
      if self._use_amp:  # pragma: no cover
          from apex import amp  # pylint: disable=E0611
  
          with amp.scale_loss(loss, self._optimizer) as scaled_loss:
              scaled_loss.backward()
  
      else:
          loss.backward()
  
      if x_grad.grad is not None:
          if isinstance(x, torch.Tensor):
              grads = x_grad.grad
          else:
              grads = x_grad.grad.cpu().numpy().copy()
      else:
          raise ValueError(
              "Gradient tensor in PyTorch model is `None`."
          )
  
      if not self.all_framework_preprocessing:
          grads = self._apply_preprocessing_gradient(x, grads)
  
      assert grads.shape == x.shape
  
      return grads
  
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import copy
  import logging
  import os
  import time
  from typing import Any, Dict, List, Optional, Tuple, Union, TYPE_CHECKING
  import numpy
  import six
  from art import config
  from art.estimators.regression.regressor import RegressorMixin
  from art.estimators.pytorch import PyTorchEstimator
label_desc: Use image node_id 19 for calling the PyTorchRegressor obj's underlying member method code with example usage: obj.loss_gradient(x, y, training_mode) and returns: grads