Classifier-Free Guidance Combination
Problem Statement
Combine a conditional and an unconditional noise prediction into the guided prediction that every text-to-image sampler actually uses.
Background
Classifier-free guidance (Ho & Salimans, 2022) drops the conditioning at random during training so one network learns both and . At sampling time the two are extrapolated:
The bracket is (proportional to) the score of the implicit classifier : the direction in noise space that makes the sample more like the prompt. Guidance walks along it.
Read off the boundary cases, because they are the whole intuition: gives the unconditional model, gives the plain conditional model (no guidance at all), and extrapolates past the conditional prediction. The usual Stable Diffusion default of guidance_scale = 7.5 is therefore a 7.5x overshoot, trading diversity for prompt fidelity. Note that w = 1 meaning "off" is exactly why some codebases skip the second forward pass when guidance_scale <= 1.
Your Task
Implement:
def cfg_combine(eps_uncond, eps_cond, w):
Return the guided noise prediction, shaped like the inputs.
Input Format
- eps_uncond, eps_cond: NumPy arrays of matching shape.
- w (float): the guidance scale.
Output Format
A NumPy array shaped like the inputs.
Sample
u = np.array([0.1, -0.2])
c = np.array([0.3, 0.2])
print(np.round(cfg_combine(u, c, 7.5), 4).tolist())
The difference is [0.2, 0.4], so the result is [0.1 + 7.50.2, -0.2 + 7.50.4] = [1.6, 2.8].
Example
u = np.array([0.1, -0.2]) c = np.array([0.3, 0.2]) print(np.round(cfg_combine(u, c, 7.5), 4).tolist())
[1.6, 2.8]
The conditional direction is c - u = [0.2, 0.4]. Guidance walks 7.5 times along it from the unconditional base: 0.1 + 7.5*0.2 = 1.6 and -0.2 + 7.5*0.4 = 2.8. Both components are pushed well past the conditional prediction itself -- that overshoot is exactly what a guidance scale above 1 means.
Constraints
- The base of the extrapolation is the unconditional prediction; the scale multiplies the difference.
wmay be any float, including0.0and values below 1.w = 1.0must returneps_condexactly.- Do not round inside the function.