class_docstr: Continuous Bernoulli distribution.
  
  This distribution is parameterized by `probs`, a (batch of) parameters
  taking values in `(0, 1)`. Note that, unlike in the Bernoulli case, `probs`
  does not correspond to a probability, but the same name is used due to the
  similarity with the Bernoulli.
  
  #### Mathematical Details
  
  The continuous Bernoulli is a distribution over the interval `[0, 1]`,
  parameterized by `probs` in `(0, 1)`.
  
  The probability density function (pdf) is,
  
  ```none
  pdf(x; probs) = probs**x * (1 - probs)**(1 - x) * C(probs)
  C(probs) = (2 * atanh(1 - 2 * probs) / (1 - 2 * probs) if probs != 0.5
              else 2.)
  ```
  
  While the normalizing constant `C(probs)` is a continuous function of `probs`
  (even at `probs = 0.5`), computing it at values close to 0.5 can result in
  numerical instabilities due to 0/0 errors. A Taylor approximation of
  `C(probs)` is thus used for values of `probs`
  in a small interval around 0.5.
  
  NOTE: Unlike the Bernoulli, numerical instabilities can happen for `probs`
  very close to 0 or 1. Current implementation allows any value in `(0, 1)`,
  but this could be changed to `(1e-6, 1-1e-6)` to avoid these issues.
  
  #### References
  
  [1] Loaiza-Ganem G and Cunningham JP. The continuous Bernoulli: fixing a
      pervasive error in variational autoencoders. NeurIPS2019.
      https://arxiv.org/abs/1907.06845
code: def _variance(self):
      # The variance is var = probs (probs - 1) / (2 * probs - 1)**2 +
      # 1 / (2 * arctanh(1 - 2 * probs))**2
      # with the removable singularity at 0.5 removed.
      # We write this in logits space.
      # Let v = 1 + exp(-logits) = 1 / probs
      # The first term becomes
      # probs * (probs - 1) / (2 * probs - 1)**2 turns in to:
      # 1 / v * (1 / v - 1) / (2 / v - 1) ** 2 =
      # (1 / v ** 2) * (1 - v) / (2 / v - 1) ** 2 =
      # (1 - v) / (2 - v) ** 2 =
      # -exp(-logits) / (1 - exp(-logits))**2 =
      # -exp(-logits) / (1 + exp(-2 * logits) - 2 * exp(-logits)) =
      # -1 / (exp(logits) + exp(-logits) - 2) =
      # 1 / (2 - 2 * cosh(logits))
      # For the second term, we have
      # 1 / (2 * arctanh(1 - 2 * probs))**2 =
      # 1 / (2 * 0.5 * log((1 + 1 - 2 * probs) / (1 - (1 - 2 * probs))))**2 =
      # 1 / (log(2 * (1 - probs) / (2 * probs)))**2 =
      # 1 / (log((1 - probs) / probs))**2 =
      # 1 / (log(1 / probs - 1))**2 =
      # 1 / (log(1 + exp(-logits) - 1))**2 =
      # 1 / (-logits)**2 =
      # 1 / logits**2
  
      # Thus we have var = 1 / (2 - 2 * cosh(logits)) + 1 / logits**2
  
      # For the function f(x) = exp(-x) / (1 - exp(-x)) ** 2 + 1 / x ** 2, when
      # logits is close to zero, we can compute the Laurent series for the first
      # term as:
      # -1 / x**2 + 1 / 12 - x**2 / 240 + x**4 / 6048 + x**6 / 172800 + O(x**8).
      # Thus we get the pole at zero canceling out with the second term.
  
      dtype = dtype_util.as_numpy_dtype(self.dtype)
      eps = np.finfo(dtype).eps
  
      logits = self._logits_parameter_no_checks()
  
      small_cutoff = np.power(eps * 172800, 1 / 6.0)
      logits_sq = tf.math.square(logits)
      small_result = (
          dtype(1 / 12.0)
          - logits_sq / 240.0
          + tf.math.square(logits_sq) / 6048
      )
  
      safe_logits_large = tf.where(
          tf.math.abs(logits) > small_cutoff, logits, dtype(1.0)
      )
      return tf.where(
          tf.math.abs(logits) > small_cutoff,
          (
              tf.math.reciprocal(
                  2 * (1.0 - tf.math.cosh(safe_logits_large))
              )
              + tf.math.reciprocal(tf.math.square(safe_logits_large))
          ),
          small_result,
      )
  
imports: import numpy
  import tensorflow.compat.v2
  from tensorflow_probability.python.bijectors import sigmoid
  from tensorflow_probability.python.distributions import distribution
  from tensorflow_probability.python.distributions import kullback_leibler
  from tensorflow_probability.python.internal import assert_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.math import generic
label_desc: Use image node_id 14 for calling the ContinuousBernoulli obj's underlying member method code with example usage: obj._variance() and returns: tf