From dc85f4fa5149983c0f8b0e5a37ca4ebbb5469aff Mon Sep 17 00:00:00 2001 From: Mr-Neutr0n <64578610+Mr-Neutr0n@users.noreply.github.com> Date: Thu, 12 Feb 2026 00:14:38 +0530 Subject: [PATCH] Fix three bugs in vocoder loss computation 1. Boolean logic error in GeneratorLoss.forward(): the condition `if self.use_hinge_gan_loss and not scores_fake is not None` evaluates as `(not scores_fake) is not None` due to operator precedence, which is always True. This caused the hinge loss block to execute even when scores_fake was None. Fixed to `and scores_fake is not None`. Applied same fix to the feat_match_loss guard which had an analogous issue. 2. Variable shadowing in _apply_D_loss(): the loop unpacking `total_loss, real_loss, fake_loss = loss_func(...)` shadows the accumulator variables real_loss and fake_loss, so `real_loss += real_loss` just doubles the current iteration's value instead of accumulating across scales. Renamed the unpacked variables to cur_real_loss and cur_fake_loss. 3. Feature loss normalization in MelganFeatureLoss.forward(): `loss_feats /= len(fake_feats) + len(real_feats)` divides by 2N instead of N since both lists have the same length. The loss is summed over N pairs, so the denominator should be N. Fixed to `loss_feats /= len(fake_feats)`. --- TTS/vocoder/layers/losses.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/TTS/vocoder/layers/losses.py b/TTS/vocoder/layers/losses.py index 1107b3c5e..d6582fa6b 100644 --- a/TTS/vocoder/layers/losses.py +++ b/TTS/vocoder/layers/losses.py @@ -143,7 +143,7 @@ def forward(self, fake_feats, real_feats): loss_feats = 0 for fake_feat, real_feat in zip(fake_feats, real_feats): loss_feats += self.loss_func(fake_feat, real_feat) - loss_feats /= len(fake_feats) + len(real_feats) + loss_feats /= len(fake_feats) return loss_feats @@ -175,10 +175,10 @@ def _apply_D_loss(scores_fake, scores_real, loss_func): if isinstance(scores_fake, list): # multi-scale loss for score_fake, score_real in zip(scores_fake, scores_real): - total_loss, real_loss, fake_loss = loss_func(score_fake=score_fake, score_real=score_real) + total_loss, cur_real_loss, cur_fake_loss = loss_func(score_fake=score_fake, score_real=score_real) loss += total_loss - real_loss += real_loss - fake_loss += fake_loss + real_loss += cur_real_loss + fake_loss += cur_fake_loss # normalize loss values with number of scales loss /= len(scores_fake) real_loss /= len(scores_real) @@ -252,13 +252,13 @@ def forward(self, y_hat=None, y=None, scores_fake=None, feats_fake=None, feats_r adv_loss += self.mse_gan_loss_weight * mse_fake_loss # multiscale Hinge adversarial loss - if self.use_hinge_gan_loss and not scores_fake is not None: + if self.use_hinge_gan_loss and scores_fake is not None: hinge_fake_loss = _apply_G_adv_loss(scores_fake, self.hinge_loss) return_dict['G_hinge_fake_loss'] = hinge_fake_loss adv_loss += self.hinge_gan_loss_weight * hinge_fake_loss # Feature Matching Loss - if self.use_feat_match_loss and not feats_fake: + if self.use_feat_match_loss and feats_fake is not None: feat_match_loss = self.feat_match_loss(feats_fake, feats_real) return_dict['G_feat_match_loss'] = feat_match_loss adv_loss += self.feat_match_loss_weight * feat_match_loss