Fix Moonshine training-loss double-shift (train against labels, not labels[..., 1:])#46784
Merged
Rocketknight1 merged 3 commits intoJun 24, 2026
Conversation
Rocketknight1
approved these changes
Jun 22, 2026
Rocketknight1
left a comment
Member
There was a problem hiding this comment.
Yes, this looks good, and the test is nice!
Moonshine right-shifts labels into decoder_input_ids, then computes the loss via ForCausalLMLoss, which shifts again, so it trains against labels[..., 1:]. Use a plain CrossEntropyLoss instead, matching Whisper/Bart and the VisionEncoderDecoder fix in #40863. Adds a regression test (with and without -100 padding).
Rocketknight1
force-pushed
the
fix-moonshine-loss-double-shift
branch
from
June 22, 2026 13:20
cf51c69 to
0263a7a
Compare
Rocketknight1
enabled auto-merge
June 22, 2026 13:20
Member
|
cc @Incheonkirin I'm seeing the CI complain about the modular conversion. Can you rerun |
|
The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update. |
auto-merge was automatically disabled
June 22, 2026 14:51
Head branch was pushed to by a user without write access
Member
|
|
make fix-repo propagated the loss fix to the streaming model, so the same no-double-shift test should guard it there too.
Contributor
|
[For maintainers] Suggested jobs to run (before merge) run-slow: moonshine, moonshine_streaming |
Contributor
|
CI Dashboard: View test results in Grafana |
Rocketknight1
enabled auto-merge
June 24, 2026 11:10
Member
|
Yep, LGTM now! |
This was referenced Jun 25, 2026
This was referenced Jun 26, 2026
Closed
OmkumarSolanki
added a commit
to OmkumarSolanki/transformers
that referenced
this pull request
Jun 26, 2026
…t labels[..., 1:]) forward right-shifts the target into decoder_input_ids, then ForCausalLMLoss shifts the labels again, so the model trains against labels[..., 1:]. Use a plain CrossEntropyLoss instead, matching Whisper/Bart and the Moonshine fix (huggingface#46784). Adds a regression test, with and without -100.
Stanley00
pushed a commit
to stanley-fork/hf-transformers
that referenced
this pull request
Jun 29, 2026
huggingface#46898) * Fix Florence2 training-loss double-shift (same pattern as Moonshine huggingface#46784) Florence2ForConditionalGeneration shifts labels right via shift_tokens_right() to create decoder_input_ids, then calls self.loss_function() which maps to ForCausalLMLoss — that function shifts labels again internally. This causes the model to train against labels[..., 1:] instead of labels. Replace self.loss_function() with plain CrossEntropyLoss, matching the fix applied to Moonshine in huggingface#46784 and CohereASR. * Fix import sort order for ruff I001 * Use shift_labels parameter instead of CrossEntropyLoss (per reviewer feedback) * Fix ruff formatting (one param per line) * Use do_shift_labels flag: only skip shift when shift_tokens_right() was called (per reviewer) * Simplify: always pass shift_labels=labels (per reviewer feedback)
OmkumarSolanki
added a commit
to OmkumarSolanki/transformers
that referenced
this pull request
Jun 29, 2026
…t labels[..., 1:]) forward right-shifts the target into decoder_input_ids, then ForCausalLMLoss shifts the labels again, so the model trains against labels[..., 1:]. Use a plain CrossEntropyLoss instead, matching Whisper/Bart and the Moonshine fix (huggingface#46784). Adds a regression test, with and without -100.
5 tasks
eliaghazal
added a commit
to eliaghazal/transformers
that referenced
this pull request
Jul 17, 2026
Moonshine's huggingface#46784 fix used a plain CrossEntropyLoss, dropping num_items_in_batch handling; PPFormulaNet overrides Florence2's forward and missed the huggingface#46898 fix, double-shifting labels. Both now pass labels as shift_labels through self.loss_function, keeping gradient accumulation reduction. Regression tests use a global token count that differs from the per-step count so the summed path is distinguishable.
This was referenced Jul 18, 2026
pull Bot
pushed a commit
to Zezo-Ai/transformers
that referenced
this pull request
Jul 21, 2026
…ngface#46784) (huggingface#46895) * Fix CohereASR training-loss double-shift (same as Moonshine fix huggingface#46784) CohereAsrForConditionalGeneration shifts labels right via shift_tokens_right() to create decoder_input_ids, then calls self.loss_function() which maps to ForCausalLMLoss — that function shifts labels again internally. This causes the model to train against labels[..., 1:] instead of labels. Replace self.loss_function() with plain CrossEntropyLoss, matching the fix applied to Moonshine in huggingface#46784. * Use shift_labels parameter instead of CrossEntropyLoss (per reviewer feedback) * Use do_shift_labels flag: only skip shift when shift_tokens_right() was called (per reviewer) * Add test for training loss no double shift * Retrigger CI * Fix test: use ParakeetEncoderModelOutput with attention_mask * Simplify: always pass shift_labels=labels (per reviewer feedback)
OmkumarSolanki
added a commit
to OmkumarSolanki/transformers
that referenced
this pull request
Jul 22, 2026
Encoder-decoder LM heads right-shift their targets into decoder_input_ids, so their logits are already position-aligned with `labels`. Two related bugs mishandle that alignment: - PPFormulaNet (and, pre-huggingface#46784, Moonshine) routed `labels` through ForCausalLMLoss without `shift_labels`, so the loss shifted a second time and the model trained against labels[..., 1:]. - Trainer._loss_shifts_labels counted num_items_in_batch over labels[..., 1:] for every ForCausalLMLoss head. Encoder-decoder heads have a real target at every non-`-100` position, so this under-counts targets (one position per sequence) and over-scales the gradient-accumulation loss. Changes: - trainer.py: _loss_shifts_labels additionally requires config.is_encoder_decoder to be false, so encoder-decoder heads count every valid label. Decoder-only heads are unchanged; Csm (decoder-only) is unaffected. - pp_formulanet: compute the loss via self.loss_function with shift_labels=kwargs.pop("shift_labels", labels) (caller-safe, keeps num_items_in_batch normalization). - moonshine / moonshine_streaming: route through self.loss_function with shift_labels=labels instead of a plain CrossEntropyLoss that ignored num_items_in_batch. Tests: generic guard test_encoder_decoder_loss_no_double_shift in tests/test_modeling_common.py, plus Trainer num_items, PPFormulaNet compute_loss and Moonshine coverage. Fixes huggingface#46901
SangbumChoi
added a commit
to SangbumChoi/transformers
that referenced
this pull request
Jul 22, 2026
* upstream/main: (39 commits) Remove deprecated training args and `is_fast` property (huggingface#46917) Consistent output shape from `get_image_features` (huggingface#46405) Fix multi-device mxfp4 dequantization race in `_convert_moe_packed_tensors` (huggingface#47423) fix failed test cases for qwen3_omni_moe model (huggingface#47449) Fix Hunyuan-VL PIL image resize parity with reference preprocessing (huggingface#47233) Move `value` padding into the attention interfaces that need it (huggingface#47451) Simplify function dispatch for linear attention (huggingface#47450) [cache] Allow sliding window layers to be roll-backed for speculative decoding (huggingface#47447) Fix double-shifted training loss in GitForCausalLM (huggingface#47395) Fix CohereASR training-loss double-shift (same as Moonshine fix huggingface#46784) (huggingface#46895) Warn when `group_by_length` is silently ignored for iterable datasets (huggingface#47379) Update bug report list (huggingface#46607) Fix shape mismatch in KyutaiSpeechToText `generate()` last window (huggingface#46952) Optimize flash attention max seqlen computation in vision attention (huggingface#47170) fix: remove unreachable return in special token builder (huggingface#47420) Add Harry to slow CI (huggingface#47454) BLT: vectorize patch length processing (huggingface#47385) Fix `TrackioCallback` fails to log evaluation metrics after training ends (huggingface#46935) [Kimi] add integration tests (huggingface#47383) Fix typo in `MusicgenForCausalLM.generate()` (huggingface#46974) ...
OmkumarSolanki
added a commit
to OmkumarSolanki/transformers
that referenced
this pull request
Jul 22, 2026
Encoder-decoder LM heads right-shift their targets into decoder_input_ids, so their logits are already position-aligned with `labels`. Two related bugs mishandle that alignment: - PPFormulaNet (and, pre-huggingface#46784, Moonshine) routed `labels` through ForCausalLMLoss without `shift_labels`, so the loss shifted a second time and the model trained against labels[..., 1:]. - Trainer._loss_shifts_labels counted num_items_in_batch over labels[..., 1:] for every ForCausalLMLoss head. Encoder-decoder heads have a real target at every non-`-100` position, so this under-counts targets (one position per sequence) and over-scales the gradient-accumulation loss. Changes: - trainer.py: _loss_shifts_labels additionally requires config.is_encoder_decoder to be false, so encoder-decoder heads count every valid label. Decoder-only heads are unchanged; Csm (decoder-only) is unaffected. - pp_formulanet: compute the loss via self.loss_function with labels=None and the aligned targets passed as shift_labels. shift_labels is popped from kwargs before the inner model call, so a caller-supplied value is honored, does not collide with the derived one, and does not leak into the inner model. - moonshine / moonshine_streaming: same form, replacing a plain CrossEntropyLoss that ignored num_items_in_batch. Tests: - tests/test_modeling_common.py: generic guard test_encoder_decoder_loss_no_double_shift. It supplies the right-shifted decoder_input_ids itself and compares gradients of the reported loss w.r.t. output.logits against the aligned and the shifted cross-entropy, which stays decisive on testers whose initialization makes the logits near-uniform. No per-model branches. - Dia and ProphetNet skip it via @unittest.skip in their own testers. - tests/trainer/test_trainer.py: Bart encoder-decoder num_items_in_batch count. - The Moonshine loss test also covers num_items_in_batch scaling and a caller-supplied shift_labels. Fixes huggingface#46901
pull Bot
pushed a commit
to k-tahiro/transformers
that referenced
this pull request
Jul 23, 2026
…els (huggingface#46903) Fix encoder-decoder loss alignment and Trainer token counting Encoder-decoder LM heads right-shift their targets into decoder_input_ids, so their logits are already position-aligned with `labels`. Two related bugs mishandle that alignment: - PPFormulaNet (and, pre-huggingface#46784, Moonshine) routed `labels` through ForCausalLMLoss without `shift_labels`, so the loss shifted a second time and the model trained against labels[..., 1:]. - Trainer._loss_shifts_labels counted num_items_in_batch over labels[..., 1:] for every ForCausalLMLoss head. Encoder-decoder heads have a real target at every non-`-100` position, so this under-counts targets (one position per sequence) and over-scales the gradient-accumulation loss. Changes: - trainer.py: _loss_shifts_labels additionally requires config.is_encoder_decoder to be false, so encoder-decoder heads count every valid label. Decoder-only heads are unchanged; Csm (decoder-only) is unaffected. - pp_formulanet: compute the loss via self.loss_function with labels=None and the aligned targets passed as shift_labels. shift_labels is popped from kwargs before the inner model call, so a caller-supplied value is honored, does not collide with the derived one, and does not leak into the inner model. - moonshine / moonshine_streaming: same form, replacing a plain CrossEntropyLoss that ignored num_items_in_batch. Tests: - tests/test_modeling_common.py: generic guard test_encoder_decoder_loss_no_double_shift. It supplies the right-shifted decoder_input_ids itself and compares gradients of the reported loss w.r.t. output.logits against the aligned and the shifted cross-entropy, which stays decisive on testers whose initialization makes the logits near-uniform. No per-model branches. - Dia and ProphetNet skip it via @unittest.skip in their own testers. - tests/trainer/test_trainer.py: Bart encoder-decoder num_items_in_batch count. - The Moonshine loss test also covers num_items_in_batch scaling and a caller-supplied shift_labels. Fixes huggingface#46901
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.
What does this PR do?
Moonshine right-shifts
labelsintodecoder_input_ids, then computes the loss withself.loss_function(ForCausalLMLoss), which shifts again, so it trains againstlabels[..., 1:]. Switch to a plainCrossEntropyLoss, matchingWhisperForConditionalGeneration/BartForConditionalGenerationand theVisionEncoderDecoderModelfix in #40863 for the same issue (#40111).Only the training loss (when
labelsare passed) changes; logits andgenerate()are unchanged, and-100stays ignored. Adds a regression test, with and without-100.