class_docstr: Approximate Kullback-Leibler.
code: def __init__(self, obs_data):
      if obs_data.ndim == 1:
          obs_data = obs_data[:, None]
      n, d = obs_data.shape
      rho_d, _ = cKDTree(obs_data).query(obs_data, 2)
      self.rho_d = rho_d[:, 1]
      self.d_n = d / n
      self.log_r = np.log(n / (n - 1))
      self.obs_data = obs_data
  
imports: import logging
  import numpy
  import pytensor
  import pytensor.tensor
  from pytensor.graph.op import Apply, Op
  from pytensor.tensor.random.op import RandomVariable
  from pytensor.tensor.variable import TensorVariable
  from scipy.spatial import cKDTree
  from pymc.distributions.distribution import Distribution, _moment
  from pymc.logprob.abstract import _logprob
  from pymc.pytensorf import floatX
label_desc: Use image node_id 1 to create a new KullbackLeibler object  with example: obj = KullbackLeibler(obs_data)