class_docstr: A smoothed classifier g 
docstr: Monte Carlo algorithm for certifying that g's prediction around x is
  constant within some L2 radius.
  With probability at least 1 - alpha, the class returned by this method will
  equal g(x), and g's prediction will be robust within a L2 ball of radius R
  around x.
  
  :param x: the input [height x width x channel]
  :param n0: the number of Monte Carlo samples to use for selection
  :param n: the number of Monte Carlo samples to use for estimation
  :param alpha: the failure probability
  :param batch_size: batch size to use when evaluating the base classifier
  :return: (predicted class, certified radius)
           in the case of abstention, the class will be ABSTAIN and the
          radius 0.
code: def certify(
      self,
      x: np.ndarray,
      n0: int,
      n: int,
      alpha: float,
      batch_size: int,
  ) -> (int, float):
      """Monte Carlo algorithm for certifying that g's prediction around x is
      constant within some L2 radius.
      With probability at least 1 - alpha, the class returned by this method will
      equal g(x), and g's prediction will be robust within a L2 ball of radius R
      around x.
  
      :param x: the input [height x width x channel]
      :param n0: the number of Monte Carlo samples to use for selection
      :param n: the number of Monte Carlo samples to use for estimation
      :param alpha: the failure probability
      :param batch_size: batch size to use when evaluating the base classifier
      :return: (predicted class, certified radius)
               in the case of abstention, the class will be ABSTAIN and the
              radius 0.
      """
      # draw samples of f(x+ epsilon)
      counts_selection = self._sample_noise(x, n0, batch_size)
      # use these samples to take a guess at the top class
      c_hat = counts_selection.argmax().item()
      # draw more samples of f(x + epsilon)
      counts_estimation = self._sample_noise(x, n, batch_size)
      # use these samples to estimate a lower bound on pA
      na = counts_estimation[c_hat].item()
      pa_bar = self._lower_confidence_bound(na, n, alpha)
      if pa_bar < 0.5:
          return Smooth.ABSTAIN, 0.0
      else:
          radius = self.sigma * norm.ppf(pa_bar)
          return c_hat, radius
  
file_path: neural-structured-learning/research/third_party/denoised_smoothing/scripts/certification_utils.py
imports: from math import ceil
  from statsmodels.stats.proportion import proportion_confint
  from scipy.stats import norm, binom_test
  import tensorflow
  import numpy
label_desc: Use image node_id 2 for calling the Smooth obj's underlying member method code with example usage: obj.certify(x, n0, n, alpha, batch_size) and returns: Smooth,  int, c_hat,  radius