Loading...
Invert the forward process: given a noisy sample and the network's predicted noise, reconstruct the model's estimate of the clean data.
A DDPM ε-predictor never outputs an image. What it outputs is the noise it believes was added. Because the forward process is a closed-form affine map,
\quad\Longrightarrow\quad \hat{x}_0 = \frac{x_t - \sqrt{1-\bar{\alpha}_t}\,\hat{\varepsilon}_\theta(x_t, t)}{\sqrt{\bar{\alpha}_t}}$$ This conversion is everywhere: the DDPM posterior mean, the DDIM update and every guidance trick are all written in terms of $\hat{x}_0$. It is also numerically delicate. At high noise $\bar{\alpha}_t$ is tiny, so the division blows up any error in $\hat{\varepsilon}$ and $\hat{x}_0$ can land far outside the valid data range. Real samplers therefore **clip** the reconstruction to the data range (typically $[-1, 1]$ for images) before feeding it onward -- the **clip_denoised** flag in the reference implementation. ## Your Task Implement: ```python def predict_x0_from_eps(x_t, t, eps, alpha_bars, clip=True): ``` Return the estimated $x_0$ as an array shaped like **x_t**, clipped element-wise to **[-1.0, 1.0]** when **clip** is true. ## Input Format - **x_t**: NumPy array of any shape. - **t** (int): 0-based index into **alpha_bars**. - **eps**: array shaped like **x_t**, the predicted noise. - **alpha_bars**: 1-D array of cumulative alphas. - **clip** (bool): whether to clamp the result to **[-1, 1]**. ## Output Format A NumPy array shaped like **x_t**. ## Sample ```python ab = np.array([0.9, 0.5, 0.04]) x_t = np.array([0.6, -0.4]) eps = np.array([0.1, 0.2]) print(np.round(predict_x0_from_eps(x_t, 1, eps, ab, clip=False), 4).tolist()) ``` Both coefficients are $\sqrt{0.5}$, so the result is **(x_t - 0.7071 * eps) / 0.7071**.ab = np.array([0.9, 0.5, 0.04]) x_t = np.array([0.6, -0.4]) eps = np.array([0.1, 0.2]) print(np.round(predict_x0_from_eps(x_t, 1, eps, ab, clip=False), 4).tolist())
[0.7485, -0.7657]
At t = 1, alpha_bar = 0.5, so both square roots are 0.7071. First element: (0.6 - 0.7071*0.1)/0.7071 = 0.5293/0.7071 = 0.7485. Second: (-0.4 - 0.7071*0.2)/0.7071 = -0.5414/0.7071 = -0.7657. With clip=False nothing is clamped, so these are returned as-is.
0 <= t < len(alpha_bars).clip is true.