in jcm/likelihood.py [0:0]
def likelihood_fn(rng, state, data):
"""Compute an unbiased estimate to the log-likelihood in bits/dim.
Args:
rng: An array of random states.
state: Replicated training state for running on multiple devices.
data: A JAX array of shape [batch size, ...].
Returns:
bpd: A JAX array of shape [batch size]. The log-likelihoods on `data` in bits/dim.
z: A JAX array of the same shape as `data`. The latent representation of `data` under the
probability flow ODE.
nfe: An integer. The number of function evaluations used for running the black-box ODE solver.
"""
div_fn = get_div_fn(lambda x, t: drift_fn(state, x, t))
rng = hk.PRNGSequence(rng)
shape = data.shape
if hutchinson_type == "Gaussian":
epsilon = jax.random.normal(next(rng), shape)
elif hutchinson_type == "Rademacher":
epsilon = jax.random.rademacher(next(rng), shape, dtype=data.dtype)
else:
raise NotImplementedError(f"Hutchinson type {hutchinson_type} unknown.")
## ODE function for diffrax ODE solver
def ode_func(t, x, args):
sample = x[..., :-1]
vec_t = jnp.ones((sample.shape[0],)) * t
drift = drift_fn(sample, vec_t)
logp_grad = div_fn(sample, vec_t, epsilon)
return jnp.stack([drift, logp_grad], axis=-1)
term = diffrax.ODETerm(ode_func)
solver = diffrax.Tsit5()
stepsize_controller = diffrax.PIDController(rtol=rtol, atol=atol)
solution = diffrax.diffeqsolve(
term,
solver,
t0=sde.T,
t1=eps,
dt0=eps - sde.T,
y0=jnp.stack([data, jnp.zeros_like((data.shape[0],))], axis=-1),
stepsize_controller=stepsize_controller,
)
nfe = solution.stats["num_steps"]
z = solution.ys[-1, ..., :-1]
delta_logp = solution.ys[-1, ..., -1]
prior_logp = sde.prior_logp(z)
bpd = -(prior_logp + delta_logp) / np.log(2)
N = np.prod(shape[1:])
bpd = bpd / N
offset = 7.0
bpd += offset
return bpd, z, nfe