Skip to content

fix(metrics): mask ignored labels in padding-free seq_acc - #10049

Open
MaxFreedomPollard wants to merge 1 commit into
modelscope:mainfrom
MaxFreedomPollard:fix-padding-free-seq-acc-mask
Open

fix(metrics): mask ignored labels in padding-free seq_acc#10049
MaxFreedomPollard wants to merge 1 commit into
modelscope:mainfrom
MaxFreedomPollard:fix-padding-free-seq-acc-mask

Conversation

@MaxFreedomPollard

Copy link
Copy Markdown

PR type

  • Bug Fix
  • New Feature
  • Document Updates
  • More Models or Datasets Support

PR information

seq_acc is always 0 when training with --padding_free true --acc_strategy seq, even for sequences the model predicts perfectly.

compute_acc in swift/metrics/acc.py builds masks = labels != -100 and then splits in two. The padded branch scores np.all(preds[i, m] == labels[i, m]), so it only looks at supervised positions. The padding-free branch, which Seq2SeqTrainer.compute_loss reaches by passing cu_seqlens, scores np.all(preds[0, start:end] == labels[0, start:end]) and never touches masks. Prompt tokens carry the label -100 and preds holds token ids, so any packed sequence with a prompt in front of it compares -100 against a token id, np.all is False, and the metric reports 0.

The fix slices masks alongside preds and labels, so the padding-free branch scores the same positions the padded branch already scores. acc_strategy=token and the padded seq path do not reach this branch and are unchanged.

tests/utils/test_acc_metrics.py packs two sequences of two prompt tokens plus two response tokens, the first answered correctly and the second not. It asserts the result is [True, False], and that it equals the result for the same data laid out as an ordinary padded batch.

Experiment results

Both new tests fail on main and pass with this change.

python -m pytest tests/utils/test_acc_metrics.py -q on unmodified main: 2 failed, the assertion diff being - [False, False] against + [True, False].

python -m pytest tests/utils/test_acc_metrics.py -q with this change: 2 passed.

python -m pytest tests/utils -q: 1 failed, 89 passed, 22 skipped. The single failure is test_opsd_teacher_images.py::test_real_qwen2_vl_template_handles_fewer_teacher_images_than_tags, which fails identically on unmodified main in my environment because qwen_vl_utils is not installed.

pre-commit run --files swift/metrics/acc.py tests/utils/test_acc_metrics.py: flake8, isort and yapf all pass.

`compute_acc` in swift/metrics/acc.py scores each packed sequence by slicing
`preds` and `labels` with `cu_seqlens`, but that branch never applies the
`labels != -100` mask that the padded branch right below it applies. Prompt
tokens carry the label -100 and predictions are token ids, so every slice that
contains a prompt compares -100 against a token id and `np.all` returns False.
With `--padding_free` and `--acc_strategy seq`, seq_acc is therefore reported
as 0 for every sequence, including sequences the model answered perfectly.

Slice `masks` alongside `preds` and `labels` so the padding-free branch scores
the same positions as the padded one. Added tests/utils/test_acc_metrics.py,
which checks a packed batch of two sequences and asserts the padding-free
result equals the result for the same data as an ordinary padded batch.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant