code: def _kl_dirichlet_dirichlet(d1, d2, name=None):
      """Batchwise KL divergence KL(d1 || d2) with d1 and d2 Dirichlet.
  
      Args:
        d1: instance of a Dirichlet distribution object.
        d2: instance of a Dirichlet distribution object.
        name: Python `str` name to use for created operations.
          Default value: `None` (i.e., `'kl_dirichlet_dirichlet'`).
  
      Returns:
        kl_div: Batchwise KL(d1 || d2)
      """
      with tf.name_scope(name or "kl_dirichlet_dirichlet"):
          # The KL between Dirichlet distributions can be derived as follows. We have
          #
          #   Dir(x; a) = 1 / B(a) * prod_i[x[i]^(a[i] - 1)]
          #
          # where B(a) is the multivariate Beta function:
          #
          #   B(a) = Gamma(a[1]) * ... * Gamma(a[n]) / Gamma(a[1] + ... + a[n])
          #
          # The KL is
          #
          #   KL(Dir(x; a), Dir(x; b)) = E_Dir(x; a){log(Dir(x; a) / Dir(x; b))}
          #
          # so we'll need to know the log density of the Dirichlet. This is
          #
          #   log(Dir(x; a)) = sum_i[(a[i] - 1) log(x[i])] - log B(a)
          #
          # The only term that matters for the expectations is the log(x[i]). To
          # compute the expectation of this term over the Dirichlet density, we can
          # use the following facts about the Dirichlet in exponential family form:
          #   1. log(x[i]) is a sufficient statistic
          #   2. expected sufficient statistics (of any exp family distribution) are
          #      equal to derivatives of the log normalizer with respect to
          #      corresponding natural parameters: E{T[i](x)} = dA/d(eta[i])
          #
          # To proceed, we can rewrite the Dirichlet density in exponential family
          # form as follows:
          #
          #   Dir(x; a) = exp{eta(a) . T(x) - A(a)}
          #
          # where '.' is the dot product of vectors eta and T, and A is a scalar:
          #
          #   eta[i](a) = a[i] - 1
          #     T[i](x) = log(x[i])
          #        A(a) = log B(a)
          #
          # Now, we can use fact (2) above to write
          #
          #   E_Dir(x; a)[log(x[i])]
          #       = dA(a) / da[i]
          #       = d/da[i] log B(a)
          #       = d/da[i] (sum_j lgamma(a[j])) - lgamma(sum_j a[j])
          #       = digamma(a[i])) - digamma(sum_j a[j])
          #
          # Putting it all together, we have
          #
          # KL[Dir(x; a) || Dir(x; b)]
          #     = E_Dir(x; a){log(Dir(x; a) / Dir(x; b)}
          #     = E_Dir(x; a){sum_i[(a[i] - b[i]) log(x[i])} - (lbeta(a) - lbeta(b))
          #     = sum_i[(a[i] - b[i]) * E_Dir(x; a){log(x[i])}] - lbeta(a) + lbeta(b)
          #     = sum_i[(a[i] - b[i]) * (digamma(a[i]) - digamma(sum_j a[j]))]
          #          - lbeta(a) + lbeta(b))
  
          concentration1 = tf.convert_to_tensor(d1.concentration)
          concentration2 = tf.convert_to_tensor(d2.concentration)
          digamma_sum_d1 = tf.math.digamma(
              tf.reduce_sum(concentration1, axis=-1, keepdims=True)
          )
          digamma_diff = (
              tf.math.digamma(concentration1) - digamma_sum_d1
          )
          concentration_diff = concentration1 - concentration2
  
          return (
              tf.reduce_sum(concentration_diff * digamma_diff, axis=-1)
              - tf.math.lbeta(concentration1)
              + tf.math.lbeta(concentration2)
          )
  
imports: import numpy
  import tensorflow.compat.v2
  from tensorflow_probability.python.bijectors import softmax_centered
  from tensorflow_probability.python.bijectors import softplus
  from tensorflow_probability.python.distributions import distribution
  from tensorflow_probability.python.distributions import gamma
  from tensorflow_probability.python.distributions import kullback_leibler
  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 tensor_util
  from tensorflow_probability.python.internal import tensorshape_util
label_desc: Use image node_id 1 for calling a global function with example usage: _kl_dirichlet_dirichlet(d1, d2, name) and returns: unknown