DDPM Posterior Mean and Variance
Problem Statement
Compute the exact reverse-process posterior -- the distribution the denoising network is trained to imitate.
Background
The reverse of the forward chain is intractable in general, but if you are also told it is available in closed form and it is Gaussian:
with the convention for the very first step.
Both coefficients are positive, so the mean sits between and : early in the reverse trajectory (large ) almost all the weight is on and the posterior barely moves, while near it swings onto . (They sum to slightly less than 1, not exactly 1 -- the forward process shrinks the signal a little at every step.) At the convention makes the coefficients exactly and : knowing pins with no uncertainty left. Handling that boundary is the part implementations get wrong.
Your Task
Implement:
def posterior(x0, x_t, t, betas):
Derive alphas and alpha_bars from betas inside the function. Return (mean, var) where mean is an array shaped like x0 and var is a Python float.
Input Format
- x0, x_t: NumPy arrays of the same shape.
- t (int): 0-based timestep index, 0 <= t < len(betas).
- betas: 1-D NumPy array of the noise schedule.
Output Format
A tuple (mean, var): a NumPy array shaped like x0, and a float.
Sample
betas = np.array([0.1, 0.2, 0.3])
x0 = np.array([1.0, -1.0])
x_t = np.array([0.4, 0.2])
m, v = posterior(x0, x_t, 1, betas)
print(np.round(m, 4).tolist())
print(round(v, 4))
Here alpha_bar_1 = 0.72, alpha_bar_0 = 0.9, so the coefficients are *sqrt(0.9)0.2/0.28 on x0 and *sqrt(0.8)0.1/0.28 on x_t, and the variance is *(0.1/0.28)0.2.
Example
betas = np.array([0.1, 0.2, 0.3]) x0 = np.array([1.0, -1.0]) x_t = np.array([0.4, 0.2]) m, v = posterior(x0, x_t, 1, betas) print(np.round(m, 4).tolist()) print(round(v, 4))
[0.8054, -0.6137] 0.0714
alphas = [0.9, 0.8, 0.7], so alpha_bar_0 = 0.9 and alpha_bar_1 = 0.72, giving 1 - alpha_bar_1 = 0.28. The x0 coefficient is sqrt(0.9)*0.2/0.28 = 0.6776 and the x_t coefficient is sqrt(0.8)*0.1/0.28 = 0.3194, so the mean is 0.6776*1.0 + 0.3194*0.4 = 0.8054 and 0.6776*(-1.0) + 0.3194*0.2 = -0.6137. The variance is (0.1/0.28)*0.2 = 0.0714.
Constraints
0 <= t < len(betas).- Use when
t == 0; the mean is then exactlyx0and the variance exactly0.0. - The coefficient uses the cumulative , while the coefficient uses the per-step together with ; mixing the two up is the usual bug.
- Return
varas a plain Pythonfloat. - Do not round inside the function.