Skip to content

Commit 604dff6

Browse files
committed
docs: postmortem for c_spec DiT conditioning regression (v0.5.4–v0.8.0) — records wrong decisions and principles to prevent recurrence
1 parent b8999aa commit 604dff6

1 file changed

Lines changed: 81 additions & 0 deletions

File tree

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Postmortem: c_spec DiT Conditioning Regression (v0.5.4–v0.8.0)
2+
3+
## Summary
4+
5+
Models trained on versions v0.5.4 through v0.8.0 produced significantly less
6+
varied and less interesting sounds, and took longer to train. The root cause
7+
was the decision at v0.5.4 (PR #30) to pass `c_spec` (spectral conditioning)
8+
into the DiT during training and inference. Each subsequent version compounded
9+
this with additional machinery (CFG, eta mapping, Min-SNR weighting, per-sample
10+
conditioning) that patched symptoms rather than addressing the root cause.
11+
12+
This document records the wrong decisions so they are not repeated.
13+
14+
## Root Cause: v0.5.4 (PR #30)
15+
16+
At v0.5.3, `train_audio_diffusion` calls the DiT as `dit(z_t, t)` — a fully
17+
unconditional forward pass. From v0.5.4 this became `dit(z_t, t, c_spec=c_spec)`,
18+
passing the spectral conditioning vector directly into the denoiser. The model
19+
now learns to denoise toward specific spectral regions rather than freely
20+
exploring the latent space. At inference, every sample in a bank is anchored
21+
to the same spectral attractor — diversity comes only from per-sample noise
22+
seeds, not from genuinely diverse latent trajectories.
23+
24+
## Compounding Decisions
25+
26+
| Version | Change | Why it was wrong |
27+
|---------|--------|-----------------|
28+
| v0.5.4 | `c_spec` passed to DiT in training + `target_c_spec` in bank generator | Spectral bias funnel — all bank samples converge on same region |
29+
| v0.5.7 | CFG two-pass `cfg_forward` + `guidance_scale` | Doubles forward cost per step; amplified conditioning reduces off-manifold exploration |
30+
| v0.6.0 | `--temperature` remapped to DDIM `eta` | Removes post-hoc latent scaling that provided cheap diversity |
31+
| v0.7.0 | Min-SNR loss weighting (default) + `chart_loss` fix + `grad_clip` | Training distribution collapses toward lower-variance attractors; longer training time |
32+
| v0.8.0 | Per-sample `c_spec` seeding | Adds complexity to patch a problem that shouldn't exist |
33+
34+
## What v0.5.3 Had Right
35+
36+
- **Unconditional DiT**: `dit(z_t, t)` — no spectral steering during diffusion.
37+
- **`noise_std` in `train_audio_decoder`**: the primary lever for sound diversity.
38+
Gaussian noise injected into the latent `z` before decoding. The docstring
39+
explicitly calls it "a feature for artistic exploration rather than a bug."
40+
- **`_apply_temperature`**: post-hoc latent scaling (`z * temperature`) with
41+
no-op at `temperature == 1.0`. Diversity at default settings comes entirely
42+
from `seed + i`.
43+
- **`c_spec` for decoder gate only**: derived post-hoc from `z.mean(dim=2)`,
44+
used by the decoder, never by the DiT.
45+
- **`chart_loss` no-op**: `A_hat = A.detach()` makes `chart_loss` always zero.
46+
This was a silent no-op due to the detach, not because of a `0.0` default.
47+
The v0.7.0 "fix" activated it, contributing to the training collapse.
48+
49+
## Principles to Prevent Recurrence
50+
51+
1. **Noise-seed diversity is the primary mechanism.** The diffusion model's
52+
job is to explore the latent manifold freely. Spectral steering constrains
53+
it to a subspace. If diversity is lacking, increase `noise_std` or vary
54+
seeds — do not add conditioning to the DiT.
55+
56+
2. **`c_spec` is a decoder gate, not a DiT conditioner.** The spectral chart
57+
descriptor shapes how the decoder turns a latent into a waveform. It must
58+
never steer the diffusion process itself.
59+
60+
3. **Preserve the `chart_loss` no-op deliberately.** The `A_hat = A.detach()`
61+
pattern in `trainer.py` makes `chart_loss` zero. This is intentional for
62+
Phase 1 — the constraint is too strong and collapses training toward
63+
lower-variance outputs. Do not "fix" this without understanding why it was
64+
a no-op in the first place.
65+
66+
4. **`noise_std` / `NOISE_INJECT` is the diversity lever.** It corresponds to
67+
`NOISE_INJECT` in notebook 07. It must not be removed or disabled.
68+
69+
5. **Avoid compounding fixes.** When a change reduces diversity, do not add
70+
more machinery to compensate. Revert the change. Each layer of
71+
compensation makes the system harder to understand and debug.
72+
73+
## Resolution
74+
75+
- `main` re-pointed to `simplify/v053-core` (v0.5.3 + neutral fixes only)
76+
- Post-v0.5.3 work preserved on `stash/post-053-complexity` branch
77+
- Neutral fixes cherry-picked back: weight_norm migration, STFT window
78+
caching, safetensors export + config.json, CI workflow
79+
- Abandoned tags v0.5.4–v0.8.0 deleted
80+
- See [issue #42](https://github.com/tuned-org-uk/latent-sound-diffusion/issues/42)
81+
for the full investigation

0 commit comments

Comments
 (0)