Closed-Form Forward Sample q(x_t | x_0)
Problem Statement
Jump straight from a clean sample to any noise level in a single operation, without simulating the intermediate steps.
Background
Applying the forward kernel times and repeatedly using the fact that the sum of two independent Gaussians is Gaussian collapses the whole chain into one closed form:
Via the reparameterization trick this becomes an explicit, differentiable formula:
This is the single most-used line of code in diffusion training: it lets you sample a random timestep for every element of a batch and produce its noisy version in O(1), instead of running a t-step loop.
Note the coefficients are square roots of and , and that they satisfy : the forward process is variance preserving.
Your Task
Implement:
def q_sample(x0, t, alpha_bars, noise):
Return the noisy sample as a NumPy array with the same shape as x0.
Input Format
- x0: NumPy array of any shape, the clean data.
- t (int): 0-based index into alpha_bars.
- alpha_bars: 1-D NumPy array of cumulative alphas.
- noise: NumPy array with the same shape as x0, the standard-normal sample .
Output Format
A NumPy array with the same shape as x0.
Sample
x0 = np.array([1.0, -1.0, 0.5])
noise = np.array([0.2, 0.4, -0.6])
ab = np.array([0.9, 0.5, 0.1])
print(np.round(q_sample(x0, 1, ab, noise), 4).tolist())
With both coefficients equal , so the output is 0.7071 * x0 + 0.7071 * noise.
Example
x0 = np.array([1.0, -1.0, 0.5]) noise = np.array([0.2, 0.4, -0.6]) ab = np.array([0.9, 0.5, 0.1]) print(np.round(q_sample(x0, 1, ab, noise), 4).tolist())
[0.8485, -0.4243, -0.0707]
At t = 1 the schedule gives alpha_bar = 0.5, so sqrt(0.5) = 0.7071 multiplies both terms. Element-wise: 0.7071*1.0 + 0.7071*0.2 = 0.8485, 0.7071*(-1.0) + 0.7071*0.4 = -0.4243, 0.7071*0.5 + 0.7071*(-0.6) = -0.0707. Scaling by alpha_bar instead of its square root would break the variance-preserving property.
Constraints
0 <= t < len(alpha_bars).- Use the square roots of and , not the raw values.
- Do not draw any randomness:
noiseis supplied. - Do not round inside the function.