fix(loss): use raw mel magnitude for the mag_weight term in MultiScal… - #12
Open
andrewwhitecdw wants to merge 2 commits into
Open
fix(loss): use raw mel magnitude for the mag_weight term in MultiScal…#12andrewwhitecdw wants to merge 2 commits into
andrewwhitecdw wants to merge 2 commits into
Conversation
…eMelSpectrogramLoss ## Summary In `MultiScaleMelSpectrogramLoss.forward()` (loss.py), the magnitude (`mag_weight`) portion of the multi-scale mel loss is computed between the *log*-mel spectrograms instead of the *raw* mel spectrograms. As a result, setting `mag_weight > 0` does not add a magnitude-domain loss at all — it just adds a second, differently-weighted copy of the log-mel loss. This is latent with the default `mag_weight=0.0` (term is multiplied by zero), so default BigVGAN training is unaffected; any user enabling `mag_weight` gets the wrong objective. ## Root cause Copy-paste error duplicating the log-mel line: ```python loss += self.log_weight * self.loss_fn(x_logmels, y_logmels) loss += self.mag_weight * self.loss_fn(x_logmels, y_logmels) # wrong operands ``` The class docstring states it is copied from descriptinc/descript-audio-codec `dac/nn/loss.py`, where the upstream `MelSpectrogramLoss.forward()` reads: ```python loss += self.log_weight * self.loss_fn(x_logmels, y_logmels) loss += self.mag_weight * self.loss_fn(x_mels, y_mels) ``` (and DAC's `MultiScaleSTFTLoss` likewise compares raw magnitudes for the `mag_weight` term). ## Fix One-line change: compare `x_mels`/`y_mels` (raw) for the magnitude term: ```python loss += self.mag_weight * self.loss_fn(x_mels, y_mels) ``` ## Testing⚠️ The repo's own tests (tests/test_activation*.py, tests/test_cuda_vs_torch_model.py) require a CUDA GPU and the fused CUDA kernel build; no GPU is available on this machine, so they could not be run here — please rely on CI. Ran a standalone regression script (torch CPU, loss.py imported directly): instantiated `MultiScaleMelSpectrogramLoss(log_weight=0, mag_weight=1)` and compared its output against a hand-computed L1 between raw mel spectrograms: - with fix: loss = 0.061000 == expected 0.061000 → PASS - with fix stashed (unmodified code): loss = 0.193965 (= L1 of *log*-mels) → FAIL, confirming the bug is real and pre-existing on `main` Also verified the default path is unchanged: with `mag_weight=0.0` the term is multiplied by zero, so default training behavior is identical. ## Why existing tests missed it The test suite only covers the Snake activations and CUDA-vs-torch kernel parity; nothing exercises `MultiScaleMelSpectrogramLoss`, and the default `mag_weight=0.0` masks the bug even if it did.
Flags the bug where MultiScaleMelSpectrogramLoss computed the mag_weight term between log-mel spectrograms instead of raw mel spectrograms, so mag_weight > 0 added a second copy of the log-mel loss instead of a magnitude-domain loss (masked by the default mag_weight=0.0). CPU-only; no CUDA/fused kernels required. Also guards that the default mag_weight=0.0 path still equals the log-mel L1 loss. Red-green verification: - uv run --with pytest --with torch --with librosa --with scipy --index https://download.pytorch.org/whl/cpu pytest tests/test_mag_weight_loss.py -> 2 passed with the fix. - git show HEAD~1:loss.py > loss.py, same command -> 1 failed (loss equals log-mel L1, not raw-mel L1), 1 passed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
…eMelSpectrogramLoss
Summary
In
MultiScaleMelSpectrogramLoss.forward()(loss.py), the magnitude (mag_weight) portion of the multi-scale mel loss is computed between the log-mel spectrograms instead of the raw mel spectrograms. As a result, settingmag_weight > 0does not add a magnitude-domain loss at all — it just adds a second, differently-weighted copy of the log-mel loss.This is latent with the default
mag_weight=0.0(term is multiplied by zero), so default BigVGAN training is unaffected; any user enablingmag_weightgets the wrong objective.Root cause
Copy-paste error duplicating the log-mel line:
The class docstring states it is copied from descriptinc/descript-audio-codec
dac/nn/loss.py, where the upstreamMelSpectrogramLoss.forward()reads:(and DAC's
MultiScaleSTFTLosslikewise compares raw magnitudes for themag_weightterm).Fix
One-line change: compare
x_mels/y_mels(raw) for the magnitude term:Testing
Ran a standalone regression script (torch CPU, loss.py imported directly): instantiated
MultiScaleMelSpectrogramLoss(log_weight=0, mag_weight=1)and compared its output against a hand-computed L1 between raw mel spectrograms:mainAlso verified the default path is unchanged: with
mag_weight=0.0the term is multiplied by zero, so default training behavior is identical.Why existing tests missed it
The test suite only covers the Snake activations and CUDA-vs-torch kernel parity; nothing exercises
MultiScaleMelSpectrogramLoss, and the defaultmag_weight=0.0masks the bug even if it did.