class_docstr: Implementation of Randomized Smoothing applied to classifier predictions and gradients, as introduced
  in Cohen et al. (2019).
  
  | Paper link: https://arxiv.org/abs/1902.02918
class_docstr_tok: ["Implementation","of","Randomized","Smoothing","applied","to","classifier","predictions","and","gradients",",","as","introduced","in","Cohen","et","al",".","(","2019",")",".","|","Paper","link",":","https",":","\/\/arxiv.org\/abs\/1902.02918"]
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: Correct labels, one-vs-rest encoding.
  :param training_mode: `True` for model set to training mode and `'False` for model set to evaluation mode.
  :param sampling: True if loss gradients should be determined with Monte Carlo sampling.
  :type sampling: `bool`
  :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",":","Correct","labels",",","one-vs-rest","encoding",".",":","param","training_mode",":","`","True","`","for","model","set","to","training","mode","and","`","'False","`","for","model","set","to","evaluation","mode",".",":","param","sampling",":","True","if","loss","gradients","should","be","determined","with","Monte","Carlo","sampling",".",":","type","sampling",":","`","bool","`",":","return",":","Array","of","gradients","of","the","same","shape","as","`","x","`","."]
code: def loss_gradient(
      self,
      x: np.ndarray,
      y: np.ndarray,
      training_mode: 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: Correct labels, one-vs-rest encoding.
      :param training_mode: `True` for model set to training mode and `'False` for model set to evaluation mode.
      :param sampling: True if loss gradients should be determined with Monte Carlo sampling.
      :type sampling: `bool`
      :return: Array of gradients of the same shape as `x`.
      """
      import tensorflow as tf
  
      sampling = kwargs.get("sampling")
  
      if sampling:
          # Apply preprocessing
          x_preprocessed, _ = self._apply_preprocessing(x, y, fit=False)
  
          if tf.executing_eagerly():
              with tf.GradientTape() as tape:
                  inputs_t = tf.convert_to_tensor(x_preprocessed)
                  tape.watch(inputs_t)
  
                  inputs_repeat_t = tf.repeat(
                      inputs_t, repeats=self.sample_size, axis=0
                  )
  
                  noise = tf.random.normal(
                      shape=inputs_repeat_t.shape,
                      mean=0.0,
                      stddev=self.scale,
                      dtype=inputs_repeat_t.dtype,
                      seed=None,
                      name=None,
                  )
  
                  inputs_noise_t = inputs_repeat_t + noise
                  if self.clip_values is not None:
                      inputs_noise_t = tf.clip_by_value(
                          inputs_noise_t,
                          clip_value_min=self.clip_values[0],
                          clip_value_max=self.clip_values[1],
                          name=None,
                      )
  
                  model_outputs = self._model(
                      inputs_noise_t, training=training_mode
                  )
                  softmax = tf.nn.softmax(
                      model_outputs, axis=1, name=None
                  )
                  average_softmax = tf.reduce_mean(
                      tf.reshape(
                          softmax,
                          shape=(
                              -1,
                              self.sample_size,
                              model_outputs.shape[-1],
                          ),
                      ),
                      axis=1,
                  )
  
                  loss = tf.reduce_mean(
                      tf.keras.losses.categorical_crossentropy(
                          y_true=y,
                          y_pred=average_softmax,
                          from_logits=False,
                          label_smoothing=0,
                      )
                  )
  
              gradients = tape.gradient(loss, inputs_t).numpy()
          else:  # pragma: no cover
              raise ValueError("Expecting eager execution.")
  
          # Apply preprocessing gradients
          gradients = self._apply_preprocessing_gradient(x, gradients)
  
      else:
          gradients = TensorFlowV2Classifier.loss_gradient(
              self, x=x, y=y, training_mode=training_mode, **kwargs
          )
  
      return gradients
  
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import logging
  from typing import Callable, List, Optional, Tuple, Union, TYPE_CHECKING
  import warnings
  from tqdm.auto import trange
  import numpy
  from art.estimators.classification.tensorflow import TensorFlowV2Classifier
  from art.estimators.certification.randomized_smoothing.randomized_smoothing import RandomizedSmoothingMixin
  from art.utils import check_and_transform_label_format
label_desc: Use image node_id 6 for calling the TensorFlowV2RandomizedSmoothing obj's underlying member method code with example usage: obj.loss_gradient(x, y, training_mode) and returns: gradients