def ddim_sample(eps_model, x, key, steps, eta=0.0, record=False):
"""Sample with (eta = 0) or without (eta > 0) determinism on `steps` steps."""
taus = [int(t) for t in jnp.round(jnp.linspace(T - 1, 0, steps))]
a_bars = [float(alpha_bar[t]) for t in taus] + [1.0] # ends at the clean point
trajectory = [x]
for k, t in enumerate(taus):
a_t, a_s = a_bars[k], a_bars[k + 1]
key, subkey = jax.random.split(key)
eps = eps_model(x, jnp.full((len(x),), t))
x0_hat = (x - (1 - a_t) ** 0.5 * eps) / a_t ** 0.5
sigma = eta * ((1 - a_s) / (1 - a_t) * (1 - a_t / a_s)) ** 0.5 if a_s < 1 else 0
x = (a_s ** 0.5 * x0_hat + max(1 - a_s - sigma ** 2, 0) ** 0.5 * eps
+ sigma * jax.random.normal(subkey, x.shape))
trajectory.append(x)
return (x, jnp.stack(trajectory)) if record else x
key, k1, k2 = jax.random.split(key, 3)
x_T = jax.random.normal(k1, (2000, 2))
print(f'target (2000 samples of the mixture): {summarize(data)}')
print(f'DDPM, 200 steps (eta = 1): {summarize(ddim_sample(net, x_T, k2, 200, eta=1.0))}')
for steps in (200, 50, 20, 10):
print(f'DDIM, {steps:>3d} steps (eta = 0): {summarize(ddim_sample(net, x_T, k2, steps))}')