Signal-to-Noise Ratio of a Noise Schedule
Problem Statement
Turn a cumulative-alpha schedule into the two quantities that actually describe "how hard is step t": the signal-to-noise ratio and its logarithm.
Background
Under the closed form xt=αˉtx0+1−αˉtε, the signal power is αˉt and the noise power is 1−αˉt. Hence
SNR(t)=1−αˉtαˉt,λt=logSNR(t)
Two facts make this the right coordinate system for diffusion:
- αˉt=0.5 is exactly the half-signal point: SNR=1 and λt=0.
- λt decreases roughly linearly over the useful part of a schedule, which is why continuous-time formulations parameterize by log-SNR rather than by t, and why two schedules with the same λ curve are the same model.
Your Task
Implement:
def snr_and_logsnr(alpha_bars):
Return (snr, log_snr), two 1-D NumPy arrays the same length as alpha_bars.
Input Format
- alpha_bars: 1-D NumPy array with every entry strictly inside (0, 1).
Output Format
A tuple (snr, log_snr) of NumPy arrays.
Sample
ab = np.array([0.9, 0.5, 0.1])
snr, ls = snr_and_logsnr(ab)
print(np.round(snr, 4).tolist())
print(np.round(ls, 4).tolist())
At αˉ=0.5 signal and noise power are equal, so SNR = 1.0 and log SNR = 0.0; at 0.9 the SNR is 9, and at 0.1 it is one ninth.
Example:
ab = np.array([0.9, 0.5, 0.1]) snr, ls = snr_and_logsnr(ab) print(np.round(snr, 4).tolist()) print(np.round(ls, 4).tolist())
[9.0, 1.0, 0.1111] [2.1972, 0.0, -2.1972]
0.9/(1-0.9) = 9, 0.5/0.5 = 1, 0.1/0.9 = 0.1111. Taking natural logs gives 2.1972, 0.0, -2.1972. The symmetry around alpha_bar = 0.5 is exact: log-SNR is an odd function of the signal fraction about that midpoint.
Constraints:
- Every entry of
alpha_barsis in the open interval(0, 1), so no division by zero and nolog(0). log_snris the natural log.- Do not round inside the function.
- Return arrays, not lists.
1. Background Knowledge
In Diffusion Models, the forward process gradually adds Gaussian noise to data x0 over T steps. The state at step t, denoted xt, can be expressed in closed form using the cumulative noise schedule αˉt:
xt=αˉtx0+1−αˉtεHere, αˉt represents the signal power (variance of the original data component), and 1−αˉt represents the noise power (variance of the added Gaussian noise ε). The Signal-to-Noise Ratio (SNR) is defined as the ratio of these two powers:
SNR(t)=1−αˉtαˉtThis metric quantifies how much of the original signal remains relative to the accumulated noise. A high SNR indicates the data is still recognizable, while a low SNR indicates it is dominated by noise. The log-SNR (λt=logSNR(t)) is often preferred in theoretical analyses and continuous-time formulations because it transforms the multiplicative relationship into an additive one, often resulting in a more linear progression over time steps.
2. Algorithm Approach
The problem requires a direct vectorized computation using NumPy. Since the input alpha_bars is a 1-D NumPy array, you should leverage NumPy's element-wise operations to compute the SNR and log-SNR for all elements simultaneously. This avoids explicit Python loops, ensuring efficiency and concise code. The approach involves two main mathematical transformations applied to the input array: division for SNR and logarithm for log-SNR.
3. Step-by-Step Strategy
- Validate Input (Implicit): Assume the input alpha_bars is a valid NumPy array with values strictly between 0 and 1, as per the problem statement.
- Compute Noise Power: Calculate the noise power component, which is 1−αˉt. In NumPy, this is simply 1 - alpha_bars.
- Compute SNR: Divide the signal power (alpha_bars) by the noise power computed in the previous step. This yields the SNR array.
snr = alpha_bars / (1 - alpha_bars)
- Compute Log-SNR: Apply the natural logarithm to the SNR array. Use np.log for this operation.
log_snr = np.log(snr)
- Return Results: Return the tuple (snr, log_snr). Ensure both are NumPy arrays of the same shape as the input.
4. Common Pitfalls
- Division by Zero: Although the problem states inputs are strictly inside (0,1), be aware that if αˉt approaches 1, the denominator 1−αˉt approaches 0, leading to very large SNR values. If αˉt were exactly 1, this would cause a division-by-zero error. Similarly, if αˉt were 0, the SNR would be 0, and log(0) is undefined (−∞). The constraints prevent this, but understanding the limits is crucial.
- Logarithm Base: The problem specifies λt=logSNR(t). In mathematics and most scientific computing contexts (including NumPy's np.log), this refers to the natural logarithm (base e). Do not use np.log10 unless explicitly requested.
- Data Types: Ensure the output arrays are floating-point types. If alpha_bars is an integer array (unlikely given the range, but possible), the division might perform integer division in older Python versions or specific contexts. Using float conversion or ensuring alpha_bars is float64 is safe practice.
- Vectorization: Avoid using for loops to iterate over alpha_bars. NumPy operations are optimized in C and will be significantly faster for large arrays.
5. Time & Space Complexity
- Time Complexity: O(N), where N is the length of the alpha_bars array. Each element undergoes a constant number of arithmetic operations (subtraction, division, logarithm). NumPy vectorization ensures these operations are performed efficiently in parallel.
- Space Complexity: O(N), as we need to store two new arrays (snr and log_snr) of size N. The input array is not modified in place.