braindecode 1.8.1.dev183280391__tar.gz → 1.8.1.dev183301950__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/NOTICE.txt +1 -0
- {braindecode-1.8.1.dev183280391/braindecode.egg-info → braindecode-1.8.1.dev183301950}/PKG-INFO +1 -1
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datasets/base.py +11 -2
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/functional/functions.py +19 -8
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/__init__.py +2 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/axon.py +42 -8
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/brainmodule.py +13 -1
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/codebrain.py +15 -4
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/ctnet.py +9 -1
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/eegconformer.py +14 -1
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/eegnex.py +6 -2
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/eegpt.py +12 -8
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/eegsym.py +68 -16
- braindecode-1.8.1.dev183301950/braindecode/models/epint.py +311 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/luna.py +4 -3
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/medformer.py +47 -20
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/mirepnet.py +15 -4
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/msvtnet.py +115 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/neurorvq.py +3 -2
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/patchedtransformer.py +3 -7
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/reve.py +3 -2
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/signal_jepa.py +81 -3
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/sinc_shallow.py +2 -1
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/summary.csv +1 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/tfm_tokenizer.py +44 -3
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/util.py +2 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/zuna.py +9 -8
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/modules/attention.py +47 -5
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/modules/layers.py +34 -1
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/samplers/base.py +60 -61
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/training/losses.py +5 -4
- braindecode-1.8.1.dev183301950/braindecode/version.py +1 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950/braindecode.egg-info}/PKG-INFO +1 -1
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode.egg-info/SOURCES.txt +1 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/api.rst +1 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/whats_new.rst +41 -0
- braindecode-1.8.1.dev183280391/braindecode/version.py +0 -1
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/LICENSE.txt +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/MANIFEST.in +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/README.rst +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/__init__.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/augmentation/__init__.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/augmentation/base.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/augmentation/functional.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/augmentation/transforms.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/classifier.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datasets/__init__.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datasets/_notebook_viewer.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datasets/bbci.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datasets/bcicomp.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datasets/bids/__init__.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datasets/bids/datasets.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datasets/bids/format.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datasets/bids/hub.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datasets/bids/hub_format.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datasets/bids/hub_io.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datasets/bids/hub_validation.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datasets/bids/iterable.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datasets/chb_mit.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datasets/collate.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datasets/mne.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datasets/moabb.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datasets/nmt.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datasets/registry.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datasets/siena.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datasets/sleep_physio_challe_18.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datasets/sleep_physionet.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datasets/tuh.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datasets/utils.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datasets/xy.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datautil/__init__.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datautil/channel_utils.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datautil/hub_formats.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datautil/serialization.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datautil/util.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/eegneuralnet.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/functional/__init__.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/functional/_real_dft.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/functional/initialization.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/atcnet.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/attentionbasenet.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/attn_sleep.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/barista.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/base.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/bendr.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/biot.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/brainbert.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/brainomni.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/brant.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/cbramod.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/config.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/contrawr.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/csbrain.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/dance.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/deep4.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/deepsleepnet.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/dgcnn.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/diver1.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/eeg_clip.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/eegdino.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/eeginception_erp.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/eeginception_mi.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/eegitnet.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/eegminer.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/eegnet.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/eegsimpleconv.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/eegtcnet.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/emg2qwerty.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/fbcnet.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/fblightconvnet.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/fbmsnet.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/guetschel2026.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/hybrid.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/ifnet.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/labram.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/mapa.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/meta_neuromotor.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/mscformer.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/mvpformer.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/neuropose.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/neurorvq_tokenizer.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/popt.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/sccnet.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/seizure_transformer.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/sensingdynamics.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/shallow_fbcsp.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/sleep_stager_blanco_2020.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/sleep_stager_chambon_2018.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/sleepfm.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/sparcnet.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/sstdpn.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/steegformer.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/syncnet.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/tcformer.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/tcn.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/tidnet.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/tmsanet.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/tsinception.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/usleep.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/vemg2pose.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/modules/__init__.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/modules/activation.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/modules/blocks.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/modules/channels.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/modules/convolution.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/modules/dance_modules.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/modules/filter.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/modules/linear.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/modules/linear_attention.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/modules/parametrization.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/modules/popt_modules.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/modules/quantization.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/modules/stats.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/modules/util.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/modules/wrapper.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/preprocessing/__init__.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/preprocessing/eegprep_preprocess.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/preprocessing/mne_preprocess.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/preprocessing/preprocess.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/preprocessing/util.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/preprocessing/windowers.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/regressor.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/samplers/__init__.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/samplers/ssl.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/training/__init__.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/training/callbacks.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/training/scoring.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/util.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/visualization/__init__.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/visualization/activations.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/visualization/attribution.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/visualization/confusion_matrices.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/visualization/frequency.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/visualization/metrics.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/visualization/sanity.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/visualization/topology.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode.egg-info/dependency_links.txt +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode.egg-info/requires.txt +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode.egg-info/top_level.txt +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/Makefile +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/_templates/autosummary/class.rst +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/_templates/autosummary/class_in_subdir.rst +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/_templates/autosummary/function.rst +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/_templates/autosummary/function_in_subdir.rst +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/agent_docs.rst +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/cite.rst +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/conf.py +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/help.rst +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/index.rst +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/install/install.rst +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/install/install_pip.rst +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/install/install_source.rst +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/models/categorization/attention.rst +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/models/categorization/channel.rst +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/models/categorization/convolution.rst +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/models/categorization/filterbank.rst +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/models/categorization/gnn.rst +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/models/categorization/interpretable.rst +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/models/categorization/lbm.rst +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/models/categorization/recurrent.rst +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/models/categorization/spd.rst +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/models/models.rst +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/models/models_categorization.rst +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/models/models_table.rst +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/models/models_visualization.rst +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/sg_execution_times.rst +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/docs/user_guide/channel_strategies.rst +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/pyproject.toml +0 -0
- {braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/setup.cfg +0 -0
|
@@ -54,6 +54,7 @@ The following components are licensed under the MIT License:
|
|
|
54
54
|
- `docs/_static/model/seizure_transformer_arch.png`
|
|
55
55
|
- `braindecode/models/guetschel2026.py`
|
|
56
56
|
- `braindecode/models/tmsanet.py`
|
|
57
|
+
- `braindecode/models/epint.py`
|
|
57
58
|
|
|
58
59
|
The `brainomni.py` file is a derivative of `OpenTSLab/BrainOmni` (MIT), whose
|
|
59
60
|
SEANet codec derives from Meta's `facebookresearch/encodec` (MIT). The
|
{braindecode-1.8.1.dev183280391/braindecode.egg-info → braindecode-1.8.1.dev183301950}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: braindecode
|
|
3
|
-
Version: 1.8.1.
|
|
3
|
+
Version: 1.8.1.dev183301950
|
|
4
4
|
Summary: Deep learning software to decode EEG, ECG or MEG signals
|
|
5
5
|
Author-email: Robin Tibor Schirrmeister <robintibor@gmail.com>, Bruno Aristimunha Pinto <b.aristimunha@gmail.com>, Alexandre Gramfort <agramfort@meta.com>
|
|
6
6
|
Maintainer-email: Alexandre Gramfort <agramfort@meta.com>, Bruno Aristimunha Pinto <b.aristimunha@gmail.com>, Robin Tibor Schirrmeister <robintibor@gmail.com>
|
{braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/datasets/base.py
RENAMED
|
@@ -1518,7 +1518,9 @@ class BaseConcatDataset(ConcatDataset, HubDatasetMixin, Generic[T]):
|
|
|
1518
1518
|
metadata : pd.DataFrame
|
|
1519
1519
|
DataFrame containing as many rows as there are windows in the
|
|
1520
1520
|
BaseConcatDataset, with the metadata and description information
|
|
1521
|
-
for each window
|
|
1521
|
+
for each window, and an ``i_dataset`` column giving the position
|
|
1522
|
+
in ``datasets`` of the dataset (recording) each window comes from.
|
|
1523
|
+
Samplers use it to keep recordings apart.
|
|
1522
1524
|
"""
|
|
1523
1525
|
if not all(
|
|
1524
1526
|
[
|
|
@@ -1544,9 +1546,15 @@ class BaseConcatDataset(ConcatDataset, HubDatasetMixin, Generic[T]):
|
|
|
1544
1546
|
"Dataset descriptions cannot contain the reserved window "
|
|
1545
1547
|
"metadata key 'i_trial_in_dataset'."
|
|
1546
1548
|
)
|
|
1549
|
+
if "i_dataset" in df.columns or "i_dataset" in ds.description:
|
|
1550
|
+
raise ValueError(
|
|
1551
|
+
"Window metadata and dataset descriptions cannot contain the "
|
|
1552
|
+
"key 'i_dataset', which get_metadata() reserves for the "
|
|
1553
|
+
"position of the dataset each window comes from. Rename it."
|
|
1554
|
+
)
|
|
1547
1555
|
|
|
1548
1556
|
all_dfs = list()
|
|
1549
|
-
for ds in self.datasets:
|
|
1557
|
+
for i_ds, ds in enumerate(self.datasets):
|
|
1550
1558
|
if hasattr(ds, "_windows") and ds._windows is not None:
|
|
1551
1559
|
df = ds._windows.metadata
|
|
1552
1560
|
else:
|
|
@@ -1556,6 +1564,7 @@ class BaseConcatDataset(ConcatDataset, HubDatasetMixin, Generic[T]):
|
|
|
1556
1564
|
df = df.copy()
|
|
1557
1565
|
for k, v in ds.description.items():
|
|
1558
1566
|
df[k] = v
|
|
1567
|
+
df["i_dataset"] = i_ds
|
|
1559
1568
|
all_dfs.append(df)
|
|
1560
1569
|
|
|
1561
1570
|
return pd.concat(all_dfs)
|
|
@@ -91,16 +91,27 @@ def fft_conv1d(
|
|
|
91
91
|
n_fft = 2 * _next_fast_len((n_times + kernel_size) // 2)
|
|
92
92
|
xs = spectral_input(x)
|
|
93
93
|
# conv1d is a cross-correlation: a convolution with the flipped kernel
|
|
94
|
-
x_f = torch.fft.rfft(xs, n=n_fft)
|
|
94
|
+
x_f = torch.fft.rfft(xs, n=n_fft) # (batch, in, freq)
|
|
95
95
|
w_f = torch.fft.rfft(weight.to(xs).flip(-1), n=n_fft).permute(2, 1, 0)
|
|
96
96
|
# Per frequency (batch, in) @ (in, out) in complex numbers, as one real
|
|
97
|
-
# matmul (a complex one is slower on CPU)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
97
|
+
# matmul (a complex one is slower on CPU).
|
|
98
|
+
needs_grad = torch.is_grad_enabled() and (x.requires_grad or weight.requires_grad)
|
|
99
|
+
if needs_grad or x.shape[0] >= 2 * x.shape[1]:
|
|
100
|
+
# [Re x, Im x] @ [[Re w, Im w], [-Im w, Re w]] (rows of i * w): the
|
|
101
|
+
# output columns are the (Re, Im) pairs of the result, read as complex
|
|
102
|
+
# without a copy (and without a costly backward).
|
|
103
|
+
w_mat = torch.view_as_real(torch.stack([w_f, w_f * 1j], 1)).flatten(1, 2)
|
|
104
|
+
y_f = torch.view_as_real(x_f).permute(2, 0, 3, 1).flatten(2) @ w_mat.flatten(2)
|
|
105
|
+
y_f = torch.view_as_complex(y_f.unflatten(-1, [-1, 2]))
|
|
106
|
+
else:
|
|
107
|
+
# Forward only with fewer rows than twice the input channels: the
|
|
108
|
+
# doubled weight costs more than combining [Re x; Im x] @ [Re w, Im w].
|
|
109
|
+
x_f = x_f.permute(2, 0, 1)
|
|
110
|
+
p = torch.cat([x_f.real, x_f.imag], 1) @ torch.view_as_real(w_f).flatten(2)
|
|
111
|
+
p = p.unflatten(1, [2, x.shape[0]]).unflatten(3, [-1, 2])
|
|
112
|
+
y_f = torch.complex(
|
|
113
|
+
p[:, 0, :, :, 0] - p[:, 1, :, :, 1], p[:, 0, :, :, 1] + p[:, 1, :, :, 0]
|
|
114
|
+
)
|
|
104
115
|
y = torch.fft.irfft(y_f.permute(1, 2, 0), n=n_fft)
|
|
105
116
|
# "same" output t is sample t + kernel_size // 2 of the full convolution
|
|
106
117
|
y = y[..., kernel_size // 2 : kernel_size // 2 + n_times]
|
{braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/__init__.py
RENAMED
|
@@ -36,6 +36,7 @@ from .eegsimpleconv import EEGSimpleConv
|
|
|
36
36
|
from .eegsym import EEGSym
|
|
37
37
|
from .eegtcnet import EEGTCNet
|
|
38
38
|
from .emg2qwerty import EMG2QwertyNet
|
|
39
|
+
from .epint import EpiNT
|
|
39
40
|
from .fbcnet import FBCNet
|
|
40
41
|
from .fblightconvnet import FBLightConvNet
|
|
41
42
|
from .fbmsnet import FBMSNet
|
|
@@ -134,6 +135,7 @@ __all__ = [
|
|
|
134
135
|
"EEGTCNet",
|
|
135
136
|
"DGCNN",
|
|
136
137
|
"EMG2QwertyNet",
|
|
138
|
+
"EpiNT",
|
|
137
139
|
"NeuroPose",
|
|
138
140
|
"SensingDynamics",
|
|
139
141
|
"VEMG2Pose",
|
{braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/axon.py
RENAMED
|
@@ -14,6 +14,7 @@ from torch import nn
|
|
|
14
14
|
from braindecode.functional import sinusoidal_positional_encoding
|
|
15
15
|
from braindecode.models.base import EEGModuleMixin
|
|
16
16
|
from braindecode.models.util import warn_if_sfreq_differs
|
|
17
|
+
from braindecode.modules.attention import _scaled_dot_product_attention
|
|
17
18
|
from braindecode.modules.channels import _resolve
|
|
18
19
|
|
|
19
20
|
|
|
@@ -462,11 +463,33 @@ class _AxisAttention(nn.Module):
|
|
|
462
463
|
.unbind(0)
|
|
463
464
|
)
|
|
464
465
|
drop = self.att_drop_prob if self.training else 0.0
|
|
465
|
-
attended =
|
|
466
|
+
attended = _scaled_dot_product_attention(
|
|
466
467
|
query, key, value, attn_mask=mask, dropout_p=drop
|
|
467
468
|
)
|
|
468
469
|
return attended.transpose(1, 2).reshape(n_seq, length, -1)
|
|
469
470
|
|
|
471
|
+
def _attend_two_scales(
|
|
472
|
+
self, projected: torch.Tensor, band: torch.Tensor, weights: torch.Tensor
|
|
473
|
+
) -> torch.Tensor:
|
|
474
|
+
"""Banded and full attention from one score matrix, mixed per query.
|
|
475
|
+
|
|
476
|
+
``weights`` (N, L, 2) are the scale-gate weights. Both softmaxes share
|
|
477
|
+
the scores and one product with the values serves the mixture.
|
|
478
|
+
"""
|
|
479
|
+
n_seq, length, _ = projected.shape
|
|
480
|
+
query, key, value = (
|
|
481
|
+
projected.reshape(n_seq, length, 3, self.num_heads, self.head_dim)
|
|
482
|
+
.permute(2, 0, 3, 1, 4)
|
|
483
|
+
.unbind(0)
|
|
484
|
+
)
|
|
485
|
+
scores = torch.matmul(query, key.transpose(-2, -1)) * self.head_dim**-0.5
|
|
486
|
+
weights = weights.reshape(n_seq, 1, length, 2)
|
|
487
|
+
probs = weights[..., 0:1] * scores.masked_fill(~band, float("-inf")).softmax(
|
|
488
|
+
-1
|
|
489
|
+
) + weights[..., 1:2] * scores.softmax(-1)
|
|
490
|
+
attended = torch.matmul(probs, value)
|
|
491
|
+
return attended.transpose(1, 2).reshape(n_seq, length, -1)
|
|
492
|
+
|
|
470
493
|
def forward(self, x: torch.Tensor, band: Optional[torch.Tensor]) -> torch.Tensor:
|
|
471
494
|
batch, n_chans, n_patches, dim = x.shape
|
|
472
495
|
axis_weights = self.axis_gate(x) # (B, C, P, 2)
|
|
@@ -476,15 +499,26 @@ class _AxisAttention(nn.Module):
|
|
|
476
499
|
# the restricted branch is the full one; attend once unless the two
|
|
477
500
|
# branches draw their own attention dropout.
|
|
478
501
|
per_channel = self.temporal_qkv(x.reshape(batch * n_chans, n_patches, dim))
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
502
|
+
dropout = self.training and self.att_drop_prob > 0
|
|
503
|
+
if band is not None and not dropout:
|
|
504
|
+
# The scale-gate weights sum to one, so the two branches share the
|
|
505
|
+
# scores, the product with the values and temporal_out.
|
|
506
|
+
attended = self._attend_two_scales(per_channel, band, scale_weights)
|
|
507
|
+
temporal = self.temporal_out(attended).reshape(
|
|
485
508
|
batch, n_chans, n_patches, dim
|
|
486
509
|
)
|
|
487
|
-
|
|
510
|
+
else:
|
|
511
|
+
restricted = self.temporal_out(self._attend(per_channel, band)).reshape(
|
|
512
|
+
batch, n_chans, n_patches, dim
|
|
513
|
+
)
|
|
514
|
+
full = restricted
|
|
515
|
+
if dropout:
|
|
516
|
+
full = self.temporal_out(self._attend(per_channel, None)).reshape(
|
|
517
|
+
batch, n_chans, n_patches, dim
|
|
518
|
+
)
|
|
519
|
+
temporal = (
|
|
520
|
+
scale_weights[..., 0:1] * restricted + scale_weights[..., 1:2] * full
|
|
521
|
+
)
|
|
488
522
|
|
|
489
523
|
# Spatial path: one sequence of C tokens per time step.
|
|
490
524
|
per_step = self.spatial_qkv(
|
{braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/brainmodule.py
RENAMED
|
@@ -20,6 +20,7 @@ from torch.nn import functional as F
|
|
|
20
20
|
from braindecode.models.base import EEGModuleMixin
|
|
21
21
|
from braindecode.models.util import has_valid_locations, positions_from_chs_info
|
|
22
22
|
from braindecode.modules import ChannelMerger
|
|
23
|
+
from braindecode.modules.attention import _hpu_lazy
|
|
23
24
|
from braindecode.modules.layers import SubjectLayers
|
|
24
25
|
|
|
25
26
|
__all__ = ["BrainModule"]
|
|
@@ -712,7 +713,7 @@ class _ConvSequence(nn.Module):
|
|
|
712
713
|
nn.Conv1d(
|
|
713
714
|
chout, 2 * chout, 1 + 2 * glu_context, padding=glu_context
|
|
714
715
|
),
|
|
715
|
-
|
|
716
|
+
_GLU(dim=1),
|
|
716
717
|
)
|
|
717
718
|
)
|
|
718
719
|
else:
|
|
@@ -727,6 +728,17 @@ class _ConvSequence(nn.Module):
|
|
|
727
728
|
return x
|
|
728
729
|
|
|
729
730
|
|
|
731
|
+
class _GLU(nn.GLU):
|
|
732
|
+
"""``nn.GLU`` that Intel Gaudi's lazy mode can compile."""
|
|
733
|
+
|
|
734
|
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
|
735
|
+
if not torch.jit.is_scripting() and x.device.type == "hpu" and _hpu_lazy():
|
|
736
|
+
# Its graph compiler fails on ``aten.glu`` after a convolution.
|
|
737
|
+
a, b = x.chunk(2, dim=self.dim)
|
|
738
|
+
return a * torch.sigmoid(b)
|
|
739
|
+
return F.glu(x, self.dim)
|
|
740
|
+
|
|
741
|
+
|
|
730
742
|
def _pad_multiple(x: torch.Tensor, base: int) -> torch.Tensor:
|
|
731
743
|
"""Pad tensor to be a multiple of base."""
|
|
732
744
|
length = x.shape[-1]
|
{braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/codebrain.py
RENAMED
|
@@ -17,6 +17,7 @@ from torch.nn.utils.parametrizations import weight_norm
|
|
|
17
17
|
from braindecode.functional import spectral_input
|
|
18
18
|
from braindecode.functional.functions import _next_fast_len
|
|
19
19
|
from braindecode.models.base import EEGModuleMixin
|
|
20
|
+
from braindecode.modules.attention import _hpu_lazy
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
class CodeBrain(EEGModuleMixin, nn.Module):
|
|
@@ -831,10 +832,20 @@ class _ResidualGroup(nn.Module):
|
|
|
831
832
|
def forward(self, input_data: torch.Tensor) -> torch.Tensor:
|
|
832
833
|
noise = input_data
|
|
833
834
|
h = noise
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
835
|
+
if not torch.jit.is_scripting() and h.device.type == "hpu" and _hpu_lazy():
|
|
836
|
+
# Gaudi's lazy-mode graph compiler fails on the backward of the
|
|
837
|
+
# sequential skip sum (one skip_conv dedw node lands in two
|
|
838
|
+
# pipeline bundles); one n-ary stack-sum reduction compiles.
|
|
839
|
+
skip_list = []
|
|
840
|
+
for block in self.residual_blocks:
|
|
841
|
+
h, skip_n = block((h, noise))
|
|
842
|
+
skip_list.append(skip_n)
|
|
843
|
+
skip = torch.stack(skip_list, dim=0).sum(dim=0)
|
|
844
|
+
else:
|
|
845
|
+
skip = torch.zeros((), dtype=h.dtype, device=h.device)
|
|
846
|
+
for block in self.residual_blocks:
|
|
847
|
+
h, skip_n = block((h, noise))
|
|
848
|
+
skip = skip_n + skip
|
|
838
849
|
|
|
839
850
|
return skip * math.sqrt(1.0 / self.num_res_layers)
|
|
840
851
|
|
{braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/ctnet.py
RENAMED
|
@@ -378,7 +378,15 @@ class _PatchEmbeddingEEGNet(nn.Module):
|
|
|
378
378
|
Tensor
|
|
379
379
|
Embedded patches of shape (batch_size, num_patches, embedding_dim).
|
|
380
380
|
"""
|
|
381
|
-
|
|
381
|
+
layers = self.eegnet_module
|
|
382
|
+
x = layers[1](layers[0](x))
|
|
383
|
+
# The depthwise (n_chans, 1) convolution as a matmul over the channel
|
|
384
|
+
# axis: same values, a faster backward than the grouped convolution's.
|
|
385
|
+
b, f, c, t = x.shape
|
|
386
|
+
x = torch.matmul(layers[2].weight.view(f, -1, c), x).view(b, -1, 1, t)
|
|
387
|
+
for i, layer in enumerate(layers):
|
|
388
|
+
if i > 2:
|
|
389
|
+
x = layer(x)
|
|
382
390
|
x = self.projection(x)
|
|
383
391
|
return x
|
|
384
392
|
|
{braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/eegconformer.py
RENAMED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import warnings
|
|
5
5
|
|
|
6
6
|
import torch
|
|
7
|
+
import torch.nn.functional as F
|
|
7
8
|
from einops.layers.torch import Rearrange
|
|
8
9
|
from torch import Tensor, nn
|
|
9
10
|
|
|
@@ -346,7 +347,19 @@ class _PatchEmbedding(nn.Module):
|
|
|
346
347
|
)
|
|
347
348
|
|
|
348
349
|
def forward(self, x: Tensor) -> Tensor:
|
|
349
|
-
|
|
350
|
+
# Nothing runs between the temporal and the spatial convolution, so
|
|
351
|
+
# they run as one convolution with the composed weight and bias (as
|
|
352
|
+
# CombinedConv does), without the (batch, filters, chans, time)
|
|
353
|
+
# intermediate.
|
|
354
|
+
conv_time, conv_spat = self.shallownet[0], self.shallownet[1]
|
|
355
|
+
bias_time, bias_spat = conv_time.bias, conv_spat.bias
|
|
356
|
+
assert bias_time is not None and bias_spat is not None
|
|
357
|
+
weight = (conv_time.weight * conv_spat.weight.permute(1, 0, 2, 3)).sum(0)
|
|
358
|
+
bias = conv_spat.weight.sum((2, 3)) @ bias_time + bias_spat
|
|
359
|
+
x = F.conv1d(x.squeeze(1), weight, bias).unsqueeze(2)
|
|
360
|
+
for i, layer in enumerate(self.shallownet):
|
|
361
|
+
if i > 1:
|
|
362
|
+
x = layer(x)
|
|
350
363
|
x = self.projection(x)
|
|
351
364
|
return x
|
|
352
365
|
|
{braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/eegnex.py
RENAMED
|
@@ -358,10 +358,14 @@ class EEGNeX(EEGModuleMixin, nn.Module):
|
|
|
358
358
|
class _TemporalConv(nn.Conv2d):
|
|
359
359
|
"""``(1, k)`` Conv2d with "same" output length; on CPU and HPU, through
|
|
360
360
|
:func:`~braindecode.functional.fft_conv1d` where
|
|
361
|
-
:func:`~braindecode.functional.prefer_fft_conv` expects it to be faster.
|
|
361
|
+
:func:`~braindecode.functional.prefer_fft_conv` expects it to be faster.
|
|
362
|
+
On HPU only when gradients are computed: the FFT pays off in the
|
|
363
|
+
backward, and Gaudi's direct forward alone is cheaper."""
|
|
362
364
|
|
|
363
365
|
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
|
364
|
-
if not prefer_fft_conv(x, self.kernel_size[1])
|
|
366
|
+
if not prefer_fft_conv(x, self.kernel_size[1]) or (
|
|
367
|
+
x.device.type == "hpu" and not torch.is_grad_enabled()
|
|
368
|
+
):
|
|
365
369
|
return self._conv_forward(x, self.weight, self.bias)
|
|
366
370
|
b, _, h, t = x.shape # the conv1d of each of the b * h rows
|
|
367
371
|
x = x.transpose(1, 2).reshape(b * h, -1, t)
|
{braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/eegpt.py
RENAMED
|
@@ -13,6 +13,7 @@ from torch import nn
|
|
|
13
13
|
|
|
14
14
|
from braindecode.models.base import EEGModuleMixin
|
|
15
15
|
from braindecode.modules import DropPath
|
|
16
|
+
from braindecode.modules.attention import _scaled_dot_product_attention
|
|
16
17
|
from braindecode.modules.convolution import Conv1dWithConstraint
|
|
17
18
|
from braindecode.modules.linear import LinearWithConstraint
|
|
18
19
|
from braindecode.util import resolve_montage_name
|
|
@@ -949,14 +950,17 @@ class _Attention(nn.Module):
|
|
|
949
950
|
# 3. Flash Attention
|
|
950
951
|
# Use PyTorch's optimized scaled_dot_product_attention (SDPA)
|
|
951
952
|
# which internally uses FlashAttention or EfficientAttention kernels.
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
953
|
+
dropout_p = self.attn_drop.p if self.training else 0.0
|
|
954
|
+
if self.is_causal:
|
|
955
|
+
y = torch.nn.functional.scaled_dot_product_attention(
|
|
956
|
+
q, k, v, attn_mask=None, dropout_p=dropout_p, is_causal=True
|
|
957
|
+
)
|
|
958
|
+
else:
|
|
959
|
+
# Gaudi's fused kernel also in lazy mode: faster for EEGPT's
|
|
960
|
+
# 23-token sequences except on the shortest inputs (256 samples).
|
|
961
|
+
y = _scaled_dot_product_attention(
|
|
962
|
+
q, k, v, dropout_p=dropout_p, fused_in_lazy=True
|
|
963
|
+
)
|
|
960
964
|
|
|
961
965
|
# Reshape back: (batch, num_heads, seq_len, head_dim) -> (batch, seq_len, embed_dim)
|
|
962
966
|
x = y.transpose(1, 2).flatten(2)
|
{braindecode-1.8.1.dev183280391 → braindecode-1.8.1.dev183301950}/braindecode/models/eegsym.py
RENAMED
|
@@ -457,6 +457,58 @@ class _SpatialConv3d(nn.Conv3d):
|
|
|
457
457
|
return y.reshape(b, -1, z, t, y.shape[-1])
|
|
458
458
|
|
|
459
459
|
|
|
460
|
+
class _BatchNorm3d(nn.BatchNorm3d):
|
|
461
|
+
"""``nn.BatchNorm3d`` with running statistics (as built here); on HPU it
|
|
462
|
+
normalises the ``(batch, channels, -1)`` view, same statistics and
|
|
463
|
+
buffers: Gaudi's 5-D batch norm backward is 2-7x slower than its 3-D one
|
|
464
|
+
on these activations. Elsewhere the same ``batch_norm`` call as torch's."""
|
|
465
|
+
|
|
466
|
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
|
467
|
+
if self.training and self.num_batches_tracked is not None:
|
|
468
|
+
self.num_batches_tracked.add_(1)
|
|
469
|
+
y = nn.functional.batch_norm(
|
|
470
|
+
x.flatten(2) if x.device.type == "hpu" else x,
|
|
471
|
+
self.running_mean,
|
|
472
|
+
self.running_var,
|
|
473
|
+
self.weight,
|
|
474
|
+
self.bias,
|
|
475
|
+
self.training,
|
|
476
|
+
self.momentum, # type: ignore[arg-type]
|
|
477
|
+
self.eps,
|
|
478
|
+
)
|
|
479
|
+
return y.view_as(x)
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
class _TemporalConv3d(nn.Conv3d):
|
|
483
|
+
"""``nn.Conv3d`` with a ``(1, k, 1)`` kernel (padding on time only); on HPU
|
|
484
|
+
it runs as ``conv1d`` on a ``(batch * z * space, channels, time)`` copy of
|
|
485
|
+
the input, same parameters. Gaudi's conv3d along time, which is not the
|
|
486
|
+
innermost axis here, is 10-50x slower than that conv1d."""
|
|
487
|
+
|
|
488
|
+
def __init__(self, *args, **kwargs):
|
|
489
|
+
super().__init__(*args, **kwargs)
|
|
490
|
+
self.time_padding = (
|
|
491
|
+
self.padding if isinstance(self.padding, str) else self.padding[1]
|
|
492
|
+
)
|
|
493
|
+
|
|
494
|
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
|
495
|
+
if x.device.type == "hpu":
|
|
496
|
+
return self._time_last(x)
|
|
497
|
+
return self._conv_forward(x, self.weight, self.bias)
|
|
498
|
+
|
|
499
|
+
def _time_last(self, x: torch.Tensor) -> torch.Tensor:
|
|
500
|
+
b, c, z, t, s = x.shape
|
|
501
|
+
y = nn.functional.conv1d(
|
|
502
|
+
x.permute(0, 2, 4, 1, 3).reshape(b * z * s, c, t),
|
|
503
|
+
self.weight.flatten(2),
|
|
504
|
+
self.bias,
|
|
505
|
+
padding=self.time_padding,
|
|
506
|
+
groups=self.groups,
|
|
507
|
+
)
|
|
508
|
+
y = y.reshape(b, z, s, y.shape[1], y.shape[2])
|
|
509
|
+
return y.permute(0, 3, 1, 4, 2).contiguous()
|
|
510
|
+
|
|
511
|
+
|
|
460
512
|
class _InceptionBlock(nn.Module):
|
|
461
513
|
r"""Inception module used in EEGSym architecture.
|
|
462
514
|
|
|
@@ -498,13 +550,13 @@ class _InceptionBlock(nn.Module):
|
|
|
498
550
|
for scale in scales_samples:
|
|
499
551
|
self.temporal_convs.append(
|
|
500
552
|
nn.Sequential(
|
|
501
|
-
|
|
553
|
+
_TemporalConv3d(
|
|
502
554
|
in_channels=in_channels,
|
|
503
555
|
out_channels=filters_per_branch,
|
|
504
556
|
kernel_size=(1, scale, 1),
|
|
505
557
|
padding="same",
|
|
506
558
|
),
|
|
507
|
-
|
|
559
|
+
_BatchNorm3d(filters_per_branch, eps=1e-3, momentum=0.01),
|
|
508
560
|
activation,
|
|
509
561
|
nn.Dropout(drop_prob),
|
|
510
562
|
)
|
|
@@ -527,7 +579,7 @@ class _InceptionBlock(nn.Module):
|
|
|
527
579
|
groups=filters_per_branch * len(scales_samples),
|
|
528
580
|
bias=False,
|
|
529
581
|
),
|
|
530
|
-
|
|
582
|
+
_BatchNorm3d(
|
|
531
583
|
filters_per_branch * len(scales_samples),
|
|
532
584
|
eps=1e-3,
|
|
533
585
|
momentum=0.01,
|
|
@@ -598,13 +650,13 @@ class _ResidualBlock(nn.Module):
|
|
|
598
650
|
|
|
599
651
|
# Temporal convolution
|
|
600
652
|
self.temporal_conv = nn.Sequential(
|
|
601
|
-
|
|
653
|
+
_TemporalConv3d(
|
|
602
654
|
in_channels=in_channels,
|
|
603
655
|
out_channels=filters,
|
|
604
656
|
kernel_size=(1, kernel_size, 1),
|
|
605
657
|
padding="same",
|
|
606
658
|
),
|
|
607
|
-
|
|
659
|
+
_BatchNorm3d(filters, eps=1e-3, momentum=0.01),
|
|
608
660
|
activation,
|
|
609
661
|
nn.Dropout(drop_prob),
|
|
610
662
|
)
|
|
@@ -618,7 +670,7 @@ class _ResidualBlock(nn.Module):
|
|
|
618
670
|
kernel_size=(1, 1, 1),
|
|
619
671
|
bias=False,
|
|
620
672
|
),
|
|
621
|
-
|
|
673
|
+
_BatchNorm3d(filters, eps=1e-3, momentum=0.01),
|
|
622
674
|
activation,
|
|
623
675
|
nn.Dropout(drop_prob),
|
|
624
676
|
)
|
|
@@ -642,7 +694,7 @@ class _ResidualBlock(nn.Module):
|
|
|
642
694
|
groups=1,
|
|
643
695
|
bias=False,
|
|
644
696
|
),
|
|
645
|
-
|
|
697
|
+
_BatchNorm3d(filters, eps=1e-3, momentum=0.01),
|
|
646
698
|
activation,
|
|
647
699
|
nn.Dropout(drop_prob),
|
|
648
700
|
)
|
|
@@ -694,14 +746,14 @@ class _TemporalBlock(nn.Module):
|
|
|
694
746
|
super().__init__()
|
|
695
747
|
|
|
696
748
|
self.conv = nn.Sequential(
|
|
697
|
-
|
|
749
|
+
_TemporalConv3d(
|
|
698
750
|
in_channels=in_channels,
|
|
699
751
|
out_channels=filters,
|
|
700
752
|
kernel_size=(1, kernel_size, 1),
|
|
701
753
|
padding="same",
|
|
702
754
|
bias=False,
|
|
703
755
|
),
|
|
704
|
-
|
|
756
|
+
_BatchNorm3d(filters, eps=1e-3, momentum=0.01),
|
|
705
757
|
activation,
|
|
706
758
|
nn.Dropout(drop_prob),
|
|
707
759
|
)
|
|
@@ -762,7 +814,7 @@ class _ChannelMergingBlock(nn.Module):
|
|
|
762
814
|
padding=(0, 0, 0), # Valid padding
|
|
763
815
|
bias=False,
|
|
764
816
|
),
|
|
765
|
-
|
|
817
|
+
_BatchNorm3d(filters, eps=1e-3, momentum=0.01),
|
|
766
818
|
activation,
|
|
767
819
|
nn.Dropout(drop_prob),
|
|
768
820
|
)
|
|
@@ -779,7 +831,7 @@ class _ChannelMergingBlock(nn.Module):
|
|
|
779
831
|
padding=(0, 0, 0),
|
|
780
832
|
bias=False,
|
|
781
833
|
),
|
|
782
|
-
|
|
834
|
+
_BatchNorm3d(filters, eps=1e-3, momentum=0.01),
|
|
783
835
|
activation,
|
|
784
836
|
nn.Dropout(drop_prob),
|
|
785
837
|
)
|
|
@@ -837,21 +889,21 @@ class _TemporalMergingBlock(nn.Module):
|
|
|
837
889
|
|
|
838
890
|
# Residual convolution (collapses time dimension)
|
|
839
891
|
self.residual_conv = nn.Sequential(
|
|
840
|
-
|
|
892
|
+
_TemporalConv3d(
|
|
841
893
|
in_channels=in_channels,
|
|
842
894
|
out_channels=in_channels, # Same channels for residual
|
|
843
895
|
kernel_size=(1, self.temporal_kernel, 1), # (Z, Time, Space)
|
|
844
896
|
padding=(0, 0, 0), # Valid padding - reduces time to 1
|
|
845
897
|
bias=False,
|
|
846
898
|
),
|
|
847
|
-
|
|
899
|
+
_BatchNorm3d(in_channels, eps=1e-3, momentum=0.01),
|
|
848
900
|
activation,
|
|
849
901
|
nn.Dropout(drop_prob),
|
|
850
902
|
)
|
|
851
903
|
|
|
852
904
|
# Grouped convolution (collapses time dimension, doubles filters)
|
|
853
905
|
self.grouped_conv = nn.Sequential(
|
|
854
|
-
|
|
906
|
+
_TemporalConv3d(
|
|
855
907
|
in_channels=in_channels,
|
|
856
908
|
out_channels=filters, # Double the channels
|
|
857
909
|
kernel_size=(1, self.temporal_kernel, 1), # (Z, Time, Space)
|
|
@@ -859,7 +911,7 @@ class _TemporalMergingBlock(nn.Module):
|
|
|
859
911
|
padding=(0, 0, 0),
|
|
860
912
|
bias=False,
|
|
861
913
|
),
|
|
862
|
-
|
|
914
|
+
_BatchNorm3d(filters, eps=1e-3, momentum=0.01),
|
|
863
915
|
activation,
|
|
864
916
|
nn.Dropout(drop_prob),
|
|
865
917
|
)
|
|
@@ -908,7 +960,7 @@ class _OutputBlock(nn.Module):
|
|
|
908
960
|
padding=(0, 0, 0),
|
|
909
961
|
bias=False,
|
|
910
962
|
),
|
|
911
|
-
|
|
963
|
+
_BatchNorm3d(in_channels, eps=1e-3, momentum=0.01),
|
|
912
964
|
activation,
|
|
913
965
|
nn.Dropout(drop_prob),
|
|
914
966
|
)
|