Cosine Noise Schedule
Problem Statement
Implement the cosine noise schedule from Improved Denoising Diffusion Probabilistic Models (Nichol & Dhariwal, 2021), which is defined on directly and only afterwards converted back into betas.
Background
The linear schedule destroys information too fast: by the middle of the trajectory the image is already almost pure noise, so the later steps contribute little. The cosine schedule instead defines
for , where the small offset keeps from becoming vanishingly small. By construction (no noise) and (pure noise).
The betas are then recovered from the ratio of consecutive cumulative products:
Near this ratio goes to zero and approaches 1, which makes the sampler unstable, so the paper clips every beta to at most 0.999.
Your Task
Implement:
def cosine_schedule(T, s=0.008):
Return (alpha_bars, betas), both 1-D NumPy arrays of length T covering (0-based index i is ). alpha_bars must be the unclipped values; betas must be clipped to the range [0, 0.999].
Input Format
- T (int): number of diffusion steps, T >= 1.
- s (float): the small offset, default 0.008.
Output Format
A tuple (alpha_bars, betas) of NumPy arrays of length T.
Sample
ab, b = cosine_schedule(4)
print(np.round(ab, 4).tolist())
print(np.round(b, 4).tolist())
With T = 4 the cosine curve drops from just below 1 down to essentially 0, and the betas grow monotonically, with the final one hitting the 0.999 clip.
Example
ab, b = cosine_schedule(4) print(np.round(ab, 4).tolist()) print(np.round(b, 4).tolist())
[0.847, 0.4938, 0.1443, 0.0] [0.153, 0.417, 0.7079, 0.999]
With T = 4 and s = 0.008 the offset grid is t/T = 0, 0.25, 0.5, 0.75, 1. Each maps through cos^2(((t/T + s)/(1+s)) * pi/2), and dividing by the t = 0 value normalises alpha_bar_0 to 1. Dropping that first entry leaves the four returned alpha-bars, which decay smoothly to ~0. Each beta is one minus the ratio of consecutive alpha-bars; the last ratio is essentially 0, so the raw beta would be ~1 and the 0.999 clip takes effect.
Constraints
- Evaluate on the T+1 grid points , then divide by .
- Return only the
Tentries for . - uses the ratio to the previous , with .
- Clip betas to
[0, 0.999]. Do not clipalpha_bars. - No rounding inside the function.