Fix chattering: boundary layer SMC instead of hard sign()

The hard sign(s) creates a random +/-1 pattern in regions where the
guidance error is near zero. When amplified by cond_scale (e.g. 12),
this produces severe high-frequency noise artifacts, especially on
SDXL which has smaller guidance magnitudes than SD3/FLUX.

Replace sign(s) with sat(s/phi) — the standard boundary layer approach
in practical sliding mode control. phi adapts to the guidance error
std so the switching threshold is meaningful across different models.

- |s| >> phi: correction = +/-K (same as paper)
- |s| << phi: correction = K*s/phi (smooth, proportional)
- Near-zero guidance regions get near-zero correction (no noise)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-04 18:00:57 +01:00
parent 5f0bd6825d
commit a0d6bf39f7

View File

@@ -86,8 +86,14 @@ class SMCCFGCtrl:
# Sliding surface: s_t = (e_t - e_{t-1}) + lambda * e_{t-1}
s = (guidance_eps - prev_eps) + lam * prev_eps
# Switching control: u_sw = -K * sign(s_t)
u_sw = -K * torch.sign(s)
# Boundary layer SMC: replaces hard sign(s) with sat(s/phi).
# Hard sign() creates random ±1 in regions where |s| is near zero,
# which cond_scale amplifies into visible noise. The boundary layer
# uses a linear transition near zero (standard chattering prevention
# in practical SMC). phi adapts to the guidance magnitude so K stays
# meaningful across models with different guidance scales.
phi = guidance_eps.std().clamp(min=1e-6)
u_sw = -K * (s / phi).clamp(-1.0, 1.0)
# Corrected guidance error (in normalized noise space)
guidance_eps = guidance_eps + u_sw