The thousand timesteps are a property of the loss, not of inference. Nothing in the derivation of the objective says a sampler has to visit all of them, and the shipped model visits twenty-five.
What licenses that is a change of sampler. DDPM's ancestral step draws fresh noise at every timestep, so the chain is a genuine stochastic process and skipping links in it changes the distribution being sampled. DDIM removes the noise draw, and what is left is a deterministic map from to that happens to agree with the DDPM marginals — a map you can compose in any strides you like.
The DDIM step, and why a stride is exact
-
Start by converting whatever the network emitted into both endpoints, using the rotation from the previous concept. Every sampler in this family begins here, whatever its prediction type.
-
The noise budget for this jump, as a fraction η of the DDPM posterior standard deviation. Setting η = 1 reproduces the ancestral sampler exactly; η = 0 is DDIM proper.
-
The step. Read the three terms as a budget: the next timestep needs total variance 1 − ᾱ_{t’}, σ² of it is spent on fresh randomness, and whatever is left is filled by pointing along the estimated noise direction rather than by drawing.
-
And that is the closed form of the forward process at t’, exactly. With a perfect network the step lands on the right point for a stride of any length — nothing about skipping is approximate, which is what makes 25 steps a defensible number rather than a shortcut.
The rescale, and the spacing that has to go with it
-
The defect, as a number. The terminal signal-to-noise ratio is small but not zero, and inference assumes it is zero.
-
The whole fix: a two-point affine map on √ᾱ. Shift the tail to zero, then stretch what is left so that √ᾱ₀ comes back to where it was. Nothing is retrained and nothing is approximated — it is a rescaling of a lookup table.
-
Now the last training input really is pure noise, so training and inference agree about what the first sampler step is looking at. This is also the timestep at which ε-prediction went degenerate in the previous concept — the rescale is why that topic mattered.
-
And this is why the spacing is not a free choice. The diffusers default, "leading", starts a 25-step sampler at t = 961 for this model — 960 from the stride, plus the steps_offset: 1 the shipped scheduler_config.json carries — where the rescaled schedule still expects 1.8 % signal. A sampler fed pure noise there reintroduces exactly the mismatch the rescale was added to remove. Without the offset the timestep is 960 and √ᾱ′ is 0.0188; the argument is the same number to two figures either way, but 960 is not what the library prints for this configuration.
The shipped numbers are 25 steps for the dehazing branch and 20 for depth, from the training config's validation block.
It is worth being honest about what those numbers are. Nothing in the configuration says why, and neither is derived from anything on this page: they are the result of somebody sweeping the step count and finding the knee. The useful thing is knowing what to measure to defend or move them — run the same input at 5, 10, 25 and 50 steps and look at where the outputs stop differing from each other, not at where a metric stops improving, because a per-pixel metric against a single reference will keep improving past the point where the samples have converged.
That the depth branch runs fewer steps than the RGB branch is the kind of asymmetry worth noticing and not worth explaining away. The plausible reading is that a depth field is a smoother target with less trajectory curvature, so it tolerates a coarser stride — but that is a hypothesis about the model, and the config records a decision rather than a reason.
Someone reports that raising a sampler from 25 to 100 steps made their outputs worse. Is that possible, or did they make a mistake?
Show answer
Entirely possible, and there are three separate mechanisms to check before calling it a mistake.
The trajectory changed. More steps is a different discretisation of the same ODE, so with you land somewhere else — near the old answer, not on it. "Worse" may mean "different, and they preferred the old one".
More noise went in. If then step count and injected randomness are the same knob, and 100 steps means 100 draws instead of 25.
The spacing moved. Most libraries recompute the subsequence from the step count, so a schedule that started at with 25 leading steps starts at with 100 — both including this model's steps_offset: 1 — which, on a zero-terminal-SNR schedule, changes how much mismatch the first step is carrying. The step count and the spacing are not independent, even though they are two arguments.