Skip to content

Fix cropped EEGRegressor loss broadcasting for a 1-D numpy y - #1198

Merged
bruAristimunha merged 1 commit into
braindecode:masterfrom
raghav-rathi:fix/cropped-loss-target-shape
Oct 4, 2026
Merged

bruAristimunha merged 1 commit into
braindecode:masterfrom
raghav-rathi:fix/cropped-loss-target-shape

Conversation

@raghav-rathi

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #1197, which fixed #1180 for trialwise training. Cropped training still compares every prediction with every target when y is a 1-D numpy array. EEGRegressor.fit reshapes that y to (n, 1), and CroppedLoss then squeezes the time-averaged prediction to (batch,), so the MSE runs over a (batch, batch) broadcast. Cropped training on a braindecode dataset is fine, since those targets are 1-D.

Same data and seed as the training script in #1180, cropped ShallowFBCSPNet, 30 epochs:

correlation with held-out targets test MSE
fit(X, y), master 0.275 0.1414
fit(X, y), this PR 0.964 0.0123
fit(dataset), master and this PR 0.964 0.0123
predict the mean 0.1490

Changes

CroppedLoss keeps the output dimension when the target is a 2-D tensor, so (batch, 1) targets meet (batch, 1) predictions. 1-D targets (class labels, dataset regression targets) and Mixup's (y_a, y_b, lam) list are squeezed as before.

Testing

  • test_eegregressor_cropped_loss_is_per_trial_mse[numpy] fails on master 55afc12 with Expected 0.18911918997764587 but got 0.2287747859954834 and passes here. The [dataset] case passes on both.

  • test_cropped_loss_accepts_mixup_target passes on both. Mixup gives CroppedLoss a list, so a bare targets.ndim check would break cropped training with Mixup.

  • pytest test/unit_tests/test_eegneuralnet.py test/unit_tests/training/ test/unit_tests/augmentation/ -n 8: 222 passed, 8 skipped.

  • Full suite with the tests.yml command, pytest -vv --durations=0 -n 16 --dist worksteal test/, CPU only (Linux, Python 3.12, torch 2.14): 4003 passed, 255 skipped, 0 failed.

  • Only tested on Linux, so macOS, Windows and Python 3.13 weren't run, and I didn't build the docs.

  • New or changed behavior is covered by relevant regression tests (or N/A with reason)

  • Style checks recorded, e.g. pre-commit run --files <changed files> (clean on the changed files)

  • docs/whats_new.rst updated (required by the changelog CI check)

Notes for reviewers

CroppedLoss is shared with EEGClassifier. Classification targets are 1-D, so they take the same path as before.

In cropped mode, EEGRegressor.fit reshapes a 1-D numpy y to (n, 1), but
CroppedLoss squeezed the time-averaged prediction to (batch,), so the
criterion compared every prediction with every target of the batch.
braindecode#1197 fixed the trialwise counterpart of this in EEGRegressor.get_loss.

CroppedLoss now keeps the output dimension when the target is a 2-D
tensor. 1-D targets, such as class labels and dataset regression
targets, and Mixup's (y_a, y_b, lam) list are handled as before.
@codecov

codecov Bot commented Oct 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.79%. Comparing base (55afc12) to head (4526810).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #1198   +/-   ##
=======================================
  Coverage   87.78%   87.79%           
=======================================
  Files         149      149           
  Lines       17461    17462    +1     
=======================================
+ Hits        15329    15330    +1     
  Misses       2132     2132           
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@bruAristimunha
bruAristimunha merged commit c047f44 into braindecode:master Oct 4, 2026
14 of 15 checks passed
@bruAristimunha

Copy link
Copy Markdown
Collaborator

Thank you so much @raghav-rathi, great addition

bruAristimunha added a commit to lindicaphxag-tech/braindecode that referenced this pull request Oct 5, 2026
Resolved docs/whats_new.rst conflict by keeping both the NeuroRVQ entry and
master's new llms.txt/docs entry. All other paths auto-merged, including
training/losses.py and test/unit_tests/training/test_losses.py, which now
exactly match origin/master (the braindecode#1198 CroppedLoss fix and its regression
test are restored).
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.

EEGRegressor computes its loss on a (batch, batch) broadcast when each trial has one target, and the model doesn't learn

2 participants