PIXELBANKv9.1.0
Menu

Cosine Noise Schedule

Problem Statement

Implement the cosine noise schedule from Improved Denoising Diffusion Probabilistic Models (Nichol & Dhariwal, 2021), which is defined on αˉ\bar{\alpha} 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

f(t)=cos⁡2 ⁣(t/T+s1+s⋅π2),αˉt=f(t)f(0)f(t) = \cos^2\!\left(\frac{t/T + s}{1+s} \cdot \frac{\pi}{2}\right), \qquad \bar{\alpha}_t = \frac{f(t)}{f(0)}

for t=0,1,…,Tt = 0, 1, \dots, T, where the small offset s=0.008s = 0.008 keeps β1\beta_1 from becoming vanishingly small. By construction αˉ0=1\bar{\alpha}_0 = 1 (no noise) and αˉT≈0\bar{\alpha}_T \approx 0 (pure noise).

The betas are then recovered from the ratio of consecutive cumulative products:

βt=1−αˉtαˉt−1\beta_t = 1 - \frac{\bar{\alpha}_t}{\bar{\alpha}_{t-1}}

Near t=Tt = T this ratio goes to zero and βt\beta_t 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 t=1,…,Tt = 1, \dots, T (0-based index i is t=i+1t = i+1). alpha_bars must be the unclipped αˉt\bar{\alpha}_t 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:

Input:
ab, b = cosine_schedule(4)
print(np.round(ab, 4).tolist())
print(np.round(b, 4).tolist())
Output:
[0.847, 0.4938, 0.1443, 0.0]
[0.153, 0.417, 0.7079, 0.999]
Reasoning:

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 ff on the T+1 grid points t=0,1,…,Tt = 0, 1, \dots, T, then divide by f(0)f(0).
  • Return only the T entries for t≥1t \geq 1.
  • βt\beta_t uses the ratio to the previous αˉ\bar{\alpha}, with αˉ0=1\bar{\alpha}_0 = 1.
  • Clip betas to [0, 0.999]. Do not clip alpha_bars.
  • No rounding inside the function.
solution.py

Test Results

0/0
Run code to see test results.