class_docstr: Empirical distribution.
  
  The Empirical distribution is parameterized by a [batch] multiset of samples.
  It describes the empirical measure (observations) of a variable.
  
  Note: some methods (log_prob, prob, cdf, mode, entropy) are not differentiable
  with regard to samples.
  
  #### Mathematical Details
  
  The probability mass function (pmf) and cumulative distribution function (cdf)
  are
  
  ```none
  pmf(k; s1, ..., sn) = sum_i I(k)^{k == si} / n
  I(k)^{k == si} == 1, if k == si, else 0.
  cdf(k; s1, ..., sn) = sum_i I(k)^{k >= si} / n
  I(k)^{k >= si} == 1, if k >= si, else 0.
  ```
  
  #### Examples
  
  ```python
  
  # Initialize a empirical distribution with 4 scalar samples.
  dist = Empirical(samples=[0., 1., 1., 2.])
  dist.cdf(1.)
  ==> 0.75
  dist.prob([0., 1.])
  ==> [0.25, 0.5] # samples will be broadcast to
                    [[0., 1., 1., 2.], [0., 1., 1., 2.]] to match event.
  
  # Initialize a empirical distribution with a [2] batch of scalar samples.
  dist = Empirical(samples=[[0., 1.], [1., 2.]])
  dist.cdf([0., 2.])
  ==> [0.5, 1.]
  dist.prob(0.)
  ==> [0.5, 0] # event will be broadcast to [0., 0.] to match samples.
  
  # Initialize a empirical distribution with 4 vector-like samples.
  dist = Empirical(samples=[[0., 0.], [0., 1.], [0., 1.], [1., 2.]],
                   event_ndims=1)
  dist.cdf([0., 1.])
  ==> 0.75
  dist.prob([[0., 1.], [1., 2.]])
  ==> [0.5, 0.25] # samples will be broadcast to shape [2, 4, 2] to match event.
  
  # Initialize a empirical distribution with a [2] batch of vector samples.
  dist = Empirical(samples=[[[0., 0.], [0., 1.]], [[0., 1.], [1., 2.]]],
                   event_ndims=1)
  dist.cdf([[0., 0.], [0., 1.]])
  ==> [0.5, 0.5]
  dist.prob([0., 1.])
  ==> [0.5, 1.] # event will be broadcast to shape [[0., 1.], [0., 1.]]
                  to match samples.
  ```
docstr: Initialize `Empirical` distributions.
  
  Args:
    samples: Numeric `Tensor` of shape `[B1, ..., Bk, S, E1, ..., En]`,
      `k, n >= 0`. Samples or batches of samples on which the distribution
      is based. The first `k` dimensions index into a batch of independent
      distributions. Length of `S` dimension determines number of samples
      in each multiset. The last `n` dimension represents samples for each
      distribution. n is specified by argument event_ndims.
    event_ndims: Python `int32`, default `0`. number of dimensions for each
      event. When `0` this distribution has scalar samples. When `1` this
      distribution has vector-like samples.
    validate_args: Python `bool`, default `False`. When `True` distribution
      parameters are checked for validity despite possibly degrading runtime
      performance. When `False` invalid inputs may silently render incorrect
      outputs.
    allow_nan_stats: Python `bool`, default `True`. When `True`, statistics
      (e.g., mean, mode, variance) use the value `NaN` to indicate the
      result is undefined. When `False`, an exception is raised if one or
      more of the statistic's batch members are undefined.
    name: Python `str` name prefixed to Ops created by this class.
  
  Raises:
    ValueError: if the rank of `samples` is statically known and less than
      event_ndims + 1.
docstr_tok: ["Initialize","`","Empirical","`","distributions",".","Args",":","samples",":","Numeric","`","Tensor","`","of","shape","`","[","B1",",","...",",","Bk",",","S",",","E1",",","...",",","En","]","`",",","`","k",",","n",">","=","0","`",".","Samples","or","batches","of","samples","on","which","the","distribution","is","based",".","The","first","`","k","`","dimensions","index","into","a","batch","of","independent","distributions",".","Length","of","`","S","`","dimension","determines","number","of","samples","in","each","multiset",".","The","last","`","n","`","dimension","represents","samples","for","each","distribution",".","n","is","specified","by","argument","event_ndims",".","event_ndims",":","Python","`","int32","`",",","default","`","0","`",".","number","of","dimensions","for","each","event",".","When","`","0","`","this","distribution","has","scalar","samples",".","When","`","1","`","this","distribution","has","vector-like","samples",".","validate_args",":","Python","`","bool","`",",","default","`","False","`",".","When","`","True","`","distribution","parameters","are","checked","for","validity","despite","possibly","degrading","runtime","performance",".","When","`","False","`","invalid","inputs","may","silently","render","incorrect","outputs",".","allow_nan_stats",":","Python","`","bool","`",",","default","`","True","`",".","When","`","True","`",",","statistics","(","e.g.",",","mean",",","mode",",","variance",")","use","the","value","`","NaN","`","to","indicate","the","result","is","undefined",".","When","`","False","`",",","an","exception","is","raised","if","one","or","more","of","the","statistic","'s","batch","members","are","undefined",".","name",":","Python","`","str","`","name","prefixed","to","Ops","created","by","this","class",".","Raises",":","ValueError",":","if","the","rank","of","`","samples","`","is","statically","known","and","less","than","event_ndims","+","1","."]
code: def __init__(
      self,
      samples,
      event_ndims=0,
      validate_args=False,
      allow_nan_stats=True,
      name="Empirical",
  ):
      """Initialize `Empirical` distributions.
  
      Args:
        samples: Numeric `Tensor` of shape `[B1, ..., Bk, S, E1, ..., En]`,
          `k, n >= 0`. Samples or batches of samples on which the distribution
          is based. The first `k` dimensions index into a batch of independent
          distributions. Length of `S` dimension determines number of samples
          in each multiset. The last `n` dimension represents samples for each
          distribution. n is specified by argument event_ndims.
        event_ndims: Python `int32`, default `0`. number of dimensions for each
          event. When `0` this distribution has scalar samples. When `1` this
          distribution has vector-like samples.
        validate_args: Python `bool`, default `False`. When `True` distribution
          parameters are checked for validity despite possibly degrading runtime
          performance. When `False` invalid inputs may silently render incorrect
          outputs.
        allow_nan_stats: Python `bool`, default `True`. When `True`, statistics
          (e.g., mean, mode, variance) use the value `NaN` to indicate the
          result is undefined. When `False`, an exception is raised if one or
          more of the statistic's batch members are undefined.
        name: Python `str` name prefixed to Ops created by this class.
  
      Raises:
        ValueError: if the rank of `samples` is statically known and less than
          event_ndims + 1.
      """
  
      parameters = dict(locals())
      with tf.name_scope(name):
          self._samples = tensor_util.convert_nonref_to_tensor(samples)
          dtype = dtype_util.common_dtype(
              [self._samples], dtype_hint=self._samples.dtype
          )
          self._event_ndims = event_ndims
  
          # Note: this tf.rank call affects the graph, but is ok in `__init__`
          # because we don't expect shapes (or ranks) to be runtime-variable, nor
          # ever need to differentiate with respect to them.
          samples_rank = ps.rank(self._samples)
          self._samples_axis = ps.cast(
              samples_rank - self._event_ndims - 1, tf.int32
          )
  
          super(Empirical, self).__init__(
              dtype=dtype,
              reparameterization_type=reparameterization.FULLY_REPARAMETERIZED,
              validate_args=validate_args,
              allow_nan_stats=allow_nan_stats,
              parameters=parameters,
              name=name,
          )
  
imports: import tensorflow.compat.v2
  from tensorflow_probability.python.distributions import distribution
  from tensorflow_probability.python.internal import assert_util
  from tensorflow_probability.python.internal import distribution_util
  from tensorflow_probability.python.internal import dtype_util
  from tensorflow_probability.python.internal import parameter_properties
  from tensorflow_probability.python.internal import prefer_static
  from tensorflow_probability.python.internal import reparameterization
  from tensorflow_probability.python.internal import samplers
  from tensorflow_probability.python.internal import tensor_util
  from tensorflow_probability.python.internal import tensorshape_util
label_desc: Use image node_id 1 to create a new Empirical object from inherited base classes: distribution, distribution with example: obj = Empirical(samples, event_ndims, validate_args, allow_nan_stats, name)