Braindecode 1.8.1.dev181512403__tar.gz → 1.8.1.dev181570120__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.dev181512403/braindecode.egg-info → braindecode-1.8.1.dev181570120}/PKG-INFO +1 -1
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/base.py +3 -46
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/functional/_real_dft.py +0 -55
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/functional/functions.py +5 -13
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/barista.py +2 -2
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/codebrain.py +11 -18
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eeginception_mi.py +3 -7
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eegnex.py +1 -1
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eegpt.py +1 -3
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/labram.py +9 -19
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/luna.py +1 -3
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/patchedtransformer.py +7 -3
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/reve.py +4 -16
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/zuna.py +9 -11
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/attention.py +6 -53
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/dance_modules.py +3 -16
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/layers.py +2 -41
- braindecode-1.8.1.dev181570120/braindecode/version.py +1 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120/braindecode.egg-info}/PKG-INFO +1 -1
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/whats_new.rst +0 -17
- braindecode-1.8.1.dev181512403/braindecode/version.py +0 -1
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/LICENSE.txt +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/MANIFEST.in +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/NOTICE.txt +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/README.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/__init__.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/augmentation/__init__.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/augmentation/base.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/augmentation/functional.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/augmentation/transforms.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/classifier.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/__init__.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/_notebook_viewer.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/bbci.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/bcicomp.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/bids/__init__.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/bids/datasets.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/bids/format.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/bids/hub.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/bids/hub_format.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/bids/hub_io.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/bids/hub_validation.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/bids/iterable.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/chb_mit.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/collate.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/mne.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/moabb.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/nmt.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/registry.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/siena.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/sleep_physio_challe_18.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/sleep_physionet.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/tuh.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/utils.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/xy.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datautil/__init__.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datautil/channel_utils.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datautil/hub_formats.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datautil/serialization.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datautil/util.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/eegneuralnet.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/functional/__init__.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/functional/initialization.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/__init__.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/atcnet.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/attentionbasenet.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/attn_sleep.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/axon.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/base.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/bendr.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/biot.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/brainbert.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/brainmodule.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/brainomni.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/brant.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/cbramod.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/config.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/contrawr.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/csbrain.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/ctnet.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/dance.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/deep4.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/deepsleepnet.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/dgcnn.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/diver1.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eeg_clip.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eegconformer.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eegdino.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eeginception_erp.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eegitnet.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eegminer.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eegnet.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eegsimpleconv.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eegsym.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eegtcnet.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/emg2qwerty.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/fbcnet.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/fblightconvnet.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/fbmsnet.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/guetschel2026.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/hybrid.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/ifnet.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/mapa.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/medformer.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/meta_neuromotor.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/mirepnet.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/mscformer.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/msvtnet.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/mvpformer.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/neuropose.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/neurorvq.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/neurorvq_tokenizer.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/popt.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/sccnet.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/seizure_transformer.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/sensingdynamics.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/shallow_fbcsp.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/signal_jepa.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/sinc_shallow.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/sleep_stager_blanco_2020.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/sleep_stager_chambon_2018.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/sleepfm.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/sparcnet.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/sstdpn.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/steegformer.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/summary.csv +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/syncnet.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/tcformer.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/tcn.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/tfm_tokenizer.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/tidnet.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/tmsanet.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/tsinception.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/usleep.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/util.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/vemg2pose.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/__init__.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/activation.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/blocks.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/channels.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/convolution.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/filter.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/linear.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/linear_attention.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/parametrization.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/popt_modules.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/quantization.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/stats.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/util.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/wrapper.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/preprocessing/__init__.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/preprocessing/eegprep_preprocess.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/preprocessing/mne_preprocess.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/preprocessing/preprocess.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/preprocessing/util.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/preprocessing/windowers.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/regressor.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/samplers/__init__.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/samplers/base.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/samplers/ssl.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/training/__init__.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/training/callbacks.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/training/losses.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/training/scoring.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/util.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/visualization/__init__.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/visualization/activations.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/visualization/attribution.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/visualization/confusion_matrices.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/visualization/frequency.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/visualization/metrics.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/visualization/sanity.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/visualization/topology.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode.egg-info/SOURCES.txt +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode.egg-info/dependency_links.txt +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode.egg-info/requires.txt +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode.egg-info/top_level.txt +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/Makefile +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/_templates/autosummary/class.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/_templates/autosummary/class_in_subdir.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/_templates/autosummary/function.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/_templates/autosummary/function_in_subdir.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/agent_docs.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/api.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/cite.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/conf.py +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/help.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/index.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/install/install.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/install/install_pip.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/install/install_source.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/models/categorization/attention.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/models/categorization/channel.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/models/categorization/convolution.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/models/categorization/filterbank.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/models/categorization/gnn.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/models/categorization/interpretable.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/models/categorization/lbm.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/models/categorization/recurrent.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/models/categorization/spd.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/models/models.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/models/models_categorization.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/models/models_table.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/models/models_visualization.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/sg_execution_times.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/user_guide/channel_strategies.rst +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/pyproject.toml +0 -0
- {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/setup.cfg +0 -0
{braindecode-1.8.1.dev181512403/braindecode.egg-info → braindecode-1.8.1.dev181570120}/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.dev181570120
|
|
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.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/base.py
RENAMED
|
@@ -279,7 +279,7 @@ def _compact_fif_tags(inst):
|
|
|
279
279
|
return inst
|
|
280
280
|
|
|
281
281
|
|
|
282
|
-
def _read_fif_window(raw, start, stop
|
|
282
|
+
def _read_fif_window(raw, start, stop):
|
|
283
283
|
"""Samples ``start:stop`` of a lazy FIF raw, copied from the file in one go.
|
|
284
284
|
|
|
285
285
|
mne reads, casts and calibrates the FIF data buffers of a range one at a
|
|
@@ -290,10 +290,6 @@ def _read_fif_window(raw, start, stop, willneed=False):
|
|
|
290
290
|
times ``raw._cals``), so the values equal ``raw._getitem``'s. Returns None
|
|
291
291
|
(the caller uses mne) unless ``raw`` is a lazy, single-file, uncompressed
|
|
292
292
|
FIF raw of float32 buffers without projector, compensation or gaps.
|
|
293
|
-
|
|
294
|
-
With ``willneed=True`` nothing is read and None is returned: the OS is
|
|
295
|
-
only asked to start reading the window's bytes into the page cache in the
|
|
296
|
-
background (``posix_fadvise(POSIX_FADV_WILLNEED)``).
|
|
297
293
|
"""
|
|
298
294
|
if (
|
|
299
295
|
not isinstance(raw, mne.io.Raw)
|
|
@@ -320,18 +316,6 @@ def _read_fif_window(raw, start, stop, willneed=False):
|
|
|
320
316
|
if not len(rows) or (rows[:, 1] != FIFF.FIFFT_FLOAT).any():
|
|
321
317
|
return None
|
|
322
318
|
size, pos = rows[:, 2].tolist(), rows[:, 4].tolist()
|
|
323
|
-
if willneed: # only a hint: any error is left to the read itself
|
|
324
|
-
try:
|
|
325
|
-
with open(fname, "rb") as f:
|
|
326
|
-
os.posix_fadvise(
|
|
327
|
-
f.fileno(),
|
|
328
|
-
pos[0],
|
|
329
|
-
pos[-1] + 16 + size[-1] - pos[0],
|
|
330
|
-
os.POSIX_FADV_WILLNEED,
|
|
331
|
-
)
|
|
332
|
-
except OSError:
|
|
333
|
-
pass
|
|
334
|
-
return None
|
|
335
319
|
# mmap: no copy through a 4 MB read buffer, and a cold file is read around
|
|
336
320
|
# the window by the kernel (as mne's 4 MB reads did), not window by window
|
|
337
321
|
with open(fname, "rb") as f, mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as m:
|
|
@@ -1378,8 +1362,7 @@ class BaseConcatDataset(ConcatDataset, HubDatasetMixin, Generic[T]):
|
|
|
1378
1362
|
def __len__(self):
|
|
1379
1363
|
return self._ensure_cumulative_sizes()[-1]
|
|
1380
1364
|
|
|
1381
|
-
def
|
|
1382
|
-
"""The dataset that holds item ``idx`` and the item's index in it."""
|
|
1365
|
+
def _get_single_item(self, idx: int):
|
|
1383
1366
|
if idx < 0:
|
|
1384
1367
|
if -idx > len(self):
|
|
1385
1368
|
raise ValueError(
|
|
@@ -1393,33 +1376,7 @@ class BaseConcatDataset(ConcatDataset, HubDatasetMixin, Generic[T]):
|
|
|
1393
1376
|
sample_idx = idx
|
|
1394
1377
|
else:
|
|
1395
1378
|
sample_idx = idx - cumulative_sizes[dataset_idx - 1]
|
|
1396
|
-
return self.datasets[dataset_idx]
|
|
1397
|
-
|
|
1398
|
-
def _get_single_item(self, idx: int):
|
|
1399
|
-
ds, i = self._locate(idx)
|
|
1400
|
-
return ds[i]
|
|
1401
|
-
|
|
1402
|
-
def __getitems__(self, indices):
|
|
1403
|
-
"""Items ``indices``, as ``[self[i] for i in indices]``.
|
|
1404
|
-
|
|
1405
|
-
A :class:`~torch.utils.data.DataLoader` fetches each batch through
|
|
1406
|
-
this. The lazy FIF windows of the batch are first requested from the
|
|
1407
|
-
OS all at once (``posix_fadvise(POSIX_FADV_WILLNEED)``, where it
|
|
1408
|
-
exists), so their reads from disk overlap instead of running one after
|
|
1409
|
-
another: on a network file system a batch read from cold files then
|
|
1410
|
-
costs about one round trip, not one per window.
|
|
1411
|
-
"""
|
|
1412
|
-
# ponytail: advises the whole batch at once; chunk it if a batch's
|
|
1413
|
-
# windows ever outgrow the page cache
|
|
1414
|
-
if hasattr(os, "posix_fadvise"):
|
|
1415
|
-
for idx in indices:
|
|
1416
|
-
if not isinstance(idx, (int, np.integer)):
|
|
1417
|
-
continue # e.g. a SequenceSampler tuple: read, not advised
|
|
1418
|
-
ds, i = self._locate(idx)
|
|
1419
|
-
if isinstance(ds, EEGWindowsDataset) and ds._zarr_data is None:
|
|
1420
|
-
_, start, stop = ds.crop_inds[i].tolist()
|
|
1421
|
-
_read_fif_window(ds.raw, start, stop, willneed=True)
|
|
1422
|
-
return [self[idx] for idx in indices]
|
|
1379
|
+
return self.datasets[dataset_idx][sample_idx]
|
|
1423
1380
|
|
|
1424
1381
|
def __getitem__(self, idx: int | list):
|
|
1425
1382
|
"""
|
|
@@ -12,10 +12,8 @@ never downcast, so callers wrap the numerically sensitive parts with
|
|
|
12
12
|
#
|
|
13
13
|
# License: BSD (3-clause)
|
|
14
14
|
import functools
|
|
15
|
-
from typing import Optional
|
|
16
15
|
|
|
17
16
|
import torch
|
|
18
|
-
from torch import nn
|
|
19
17
|
|
|
20
18
|
|
|
21
19
|
def needs_real_dft(x: torch.Tensor) -> bool:
|
|
@@ -138,56 +136,3 @@ def hilbert_freq_real(x: torch.Tensor, forward_fourier: bool) -> torch.Tensor:
|
|
|
138
136
|
return torch.stack((out_real, out_imag), dim=-1)
|
|
139
137
|
|
|
140
138
|
return compute(x)
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
@torch.jit.unused
|
|
144
|
-
def fft_conv1d_real(
|
|
145
|
-
x: torch.Tensor, weight: torch.Tensor, bias: Optional[torch.Tensor]
|
|
146
|
-
) -> torch.Tensor:
|
|
147
|
-
"""Real-valued equivalent of :func:`braindecode.functional.fft_conv1d`.
|
|
148
|
-
|
|
149
|
-
Overlap-save: the input is cut into blocks of ``n`` samples (the power of
|
|
150
|
-
two ``>= 2 * kernel_size``) that advance by ``n - kernel_size + 1`` outputs,
|
|
151
|
-
each block's DFT is a matmul against the cosine/sine basis, and per
|
|
152
|
-
frequency the complex product with the kernels, summed over the input
|
|
153
|
-
channels, is one real matmul.
|
|
154
|
-
"""
|
|
155
|
-
|
|
156
|
-
@fp32_island
|
|
157
|
-
def compute(x, weight):
|
|
158
|
-
n_times, kernel_size = x.shape[-1], weight.shape[-1]
|
|
159
|
-
n = 1 << (2 * kernel_size - 1).bit_length()
|
|
160
|
-
hop = n - kernel_size + 1
|
|
161
|
-
n_blocks = -(-n_times // hop)
|
|
162
|
-
n_freqs = n // 2 + 1
|
|
163
|
-
# "same" alignment: torch pads the extra zero of an even kernel on the right
|
|
164
|
-
left = (kernel_size - 1) // 2
|
|
165
|
-
x = nn.functional.pad(x, (left, (n_blocks + 1) * hop - n_times - left))
|
|
166
|
-
hops = x.unflatten(-1, (n_blocks + 1, hop))
|
|
167
|
-
# block i = hop i + the first kernel_size - 1 samples of hop i + 1
|
|
168
|
-
blocks = torch.cat([hops[:, :, :-1], hops[:, :, 1:, : kernel_size - 1]], -1)
|
|
169
|
-
cosine, sine = real_dft_basis(n, device=x.device, dtype=x.dtype)
|
|
170
|
-
basis = torch.cat([cosine, -sine]).transpose(0, 1) # -> [Re | Im] of rfft
|
|
171
|
-
x_f = blocks @ basis # (batch, in, blocks, 2 * n_freqs)
|
|
172
|
-
w_f = nn.functional.pad(weight.to(x), (0, n - kernel_size)) @ basis
|
|
173
|
-
w_re, w_im = w_f[..., :n_freqs], w_f[..., n_freqs:]
|
|
174
|
-
# conv1d is a cross-correlation: x_f * conj(w_f), summed over the input
|
|
175
|
-
# channels. Per frequency [Re x, Im x] @ [[Re w, -Im w], [Im w, Re w]].
|
|
176
|
-
w_f = torch.cat([torch.cat([w_re, -w_im]), torch.cat([w_im, w_re])], 1)
|
|
177
|
-
x_f = x_f.unflatten(-1, (2, n_freqs)).permute(4, 0, 2, 3, 1).flatten(1, 2)
|
|
178
|
-
y_f = torch.bmm(x_f.flatten(2), w_f.permute(2, 1, 0)) # (freq, ., 2 * out)
|
|
179
|
-
y_f = y_f.unflatten(1, (x.shape[0], n_blocks)).unflatten(-1, (2, -1))
|
|
180
|
-
y_f = y_f.permute(1, 4, 2, 3, 0).flatten(
|
|
181
|
-
-2
|
|
182
|
-
) # (batch, out, blocks, 2 * n_freqs)
|
|
183
|
-
# inverse DFT of the first `hop` samples, the ones without wrap-around
|
|
184
|
-
scale = torch.full((n_freqs, 1), 2.0 / n, dtype=x.dtype, device=x.device)
|
|
185
|
-
scale[0] = 1.0 / n
|
|
186
|
-
scale[-1] = 1.0 / n # Nyquist (n is even)
|
|
187
|
-
inverse = torch.cat([scale * cosine[:, :hop], -scale * sine[:, :hop]])
|
|
188
|
-
return (y_f @ inverse).flatten(-2)[..., :n_times]
|
|
189
|
-
|
|
190
|
-
y = compute(x, weight)
|
|
191
|
-
if bias is not None:
|
|
192
|
-
y = y + bias.to(y).unsqueeze(-1)
|
|
193
|
-
return y.to(x)
|
|
@@ -62,10 +62,9 @@ def fft_conv1d(
|
|
|
62
62
|
|
|
63
63
|
Equal to the direct convolution up to float rounding: the FFT is long
|
|
64
64
|
enough for a linear (not circular) convolution. Its cost barely grows with
|
|
65
|
-
the kernel size, so it is faster than the direct one for long kernels
|
|
66
|
-
(see :func:`prefer_fft_conv`). float16/bfloat16 inputs are computed in
|
|
67
|
-
float32 (:func:`spectral_input`) and cast back.
|
|
68
|
-
complex dtype) the DFTs are real matmuls over overlapping blocks.
|
|
65
|
+
the kernel size, so it is faster than the direct one for long kernels on
|
|
66
|
+
CPU (see :func:`prefer_fft_conv`). float16/bfloat16 inputs are computed in
|
|
67
|
+
float32 (:func:`spectral_input`) and cast back.
|
|
69
68
|
|
|
70
69
|
Parameters
|
|
71
70
|
----------
|
|
@@ -83,8 +82,6 @@ def fft_conv1d(
|
|
|
83
82
|
``x``. For an even ``kernel_size`` it is aligned like torch's
|
|
84
83
|
``padding="same"`` (the extra zero padded on the right).
|
|
85
84
|
"""
|
|
86
|
-
if _real_dft.needs_real_dft(x):
|
|
87
|
-
return _real_dft.fft_conv1d_real(x, weight, bias)
|
|
88
85
|
n_times, kernel_size = x.shape[-1], weight.shape[-1]
|
|
89
86
|
# >= n_times + kernel_size - 1 (no circular wrap-around), even and
|
|
90
87
|
# 5-smooth: the fast cases of a real FFT
|
|
@@ -118,11 +115,8 @@ def prefer_fft_conv(x: torch.Tensor, kernel_size: int) -> bool:
|
|
|
118
115
|
and from ``batch_size * kernel_size >= 600`` if also
|
|
119
116
|
``in_channels * kernel_size >= 120``: with one or two input channels a
|
|
120
117
|
float32 direct convolution stays cheaper up to k = 85 / 31 (13 long
|
|
121
|
-
temporal convolutions of the model zoo, 22 channels x batch 32).
|
|
122
|
-
|
|
123
|
-
kernel_size`` and the FFT about a fixed few milliseconds in eager mode: the
|
|
124
|
-
FFT wins from 8 input channels and ``batch_size * n_times * kernel_size >=
|
|
125
|
-
8e6``. GPUs keep the direct convolution.
|
|
118
|
+
temporal convolutions of the model zoo, 22 channels x batch 32). GPUs and
|
|
119
|
+
HPUs (no complex dtype) keep the direct convolution.
|
|
126
120
|
|
|
127
121
|
Parameters
|
|
128
122
|
----------
|
|
@@ -131,8 +125,6 @@ def prefer_fft_conv(x: torch.Tensor, kernel_size: int) -> bool:
|
|
|
131
125
|
kernel_size : int
|
|
132
126
|
Kernel length in samples.
|
|
133
127
|
"""
|
|
134
|
-
if x.device.type == "hpu":
|
|
135
|
-
return x.shape[1] >= 8 and x.shape[0] * x.shape[-1] * kernel_size >= 8e6
|
|
136
128
|
return x.device.type == "cpu" and (
|
|
137
129
|
x.element_size() == 2
|
|
138
130
|
or (x.shape[0] * kernel_size >= 600 and x.shape[1] * kernel_size >= 120)
|
{braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/barista.py
RENAMED
|
@@ -7,13 +7,13 @@ from __future__ import annotations
|
|
|
7
7
|
from typing import Optional
|
|
8
8
|
|
|
9
9
|
import torch
|
|
10
|
+
import torch.nn.functional as F
|
|
10
11
|
from einops.layers.torch import Rearrange
|
|
11
12
|
from torch import nn
|
|
12
13
|
|
|
13
14
|
from braindecode.models.base import EEGModuleMixin
|
|
14
15
|
from braindecode.models.util import extract_channel_locations_from_chs_info
|
|
15
16
|
from braindecode.modules import GatedLinearUnit, PatchTokenizer
|
|
16
|
-
from braindecode.modules.attention import _scaled_dot_product_attention
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class BaRISTA(EEGModuleMixin, nn.Module, license="other"):
|
|
@@ -689,7 +689,7 @@ class _RotarySelfAttention(nn.Module):
|
|
|
689
689
|
|
|
690
690
|
# Dropout falls on the attention output rather than on the weights,
|
|
691
691
|
# through dropout_p, because the reference disables the latter outright.
|
|
692
|
-
attention =
|
|
692
|
+
attention = F.scaled_dot_product_attention(query, key, value)
|
|
693
693
|
attention = self.dropout(attention)
|
|
694
694
|
attention = self.merge_heads(attention)
|
|
695
695
|
return self.o_proj(attention)
|
{braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/codebrain.py
RENAMED
|
@@ -703,15 +703,18 @@ class _ResidualBlock(nn.Module):
|
|
|
703
703
|
# Sliding-window attention branch
|
|
704
704
|
# (batch, 2*res_channels, seq_len) -> (batch, seq_len, 2*res_channels)
|
|
705
705
|
h_attn = h_ssm.transpose(1, 2)
|
|
706
|
-
if
|
|
706
|
+
if (
|
|
707
|
+
self.swa_window_size == 1
|
|
708
|
+
and not self.training
|
|
709
|
+
and not torch.is_grad_enabled()
|
|
710
|
+
and h_attn.device.type == "cpu"
|
|
711
|
+
):
|
|
707
712
|
# A one-wide window keeps only the diagonal: the softmax weights are
|
|
708
|
-
# exactly 1 and 0, so the attention returns its value projection
|
|
709
|
-
#
|
|
710
|
-
#
|
|
711
|
-
#
|
|
712
|
-
#
|
|
713
|
-
# outputs and gradients are unchanged bit for bit, and so is the
|
|
714
|
-
# RNG stream. (On Gaudi the full attention was faster.)
|
|
713
|
+
# exactly 1 and 0, so the attention returns its value projection.
|
|
714
|
+
# Same projection calls as nn.MultiheadAttention (on its (seq,
|
|
715
|
+
# batch, embed) view), so the output is unchanged bit for bit. (In
|
|
716
|
+
# training the weights carry dropout; on Gaudi the full attention
|
|
717
|
+
# was faster.)
|
|
715
718
|
# ponytail: the unused query/key projections are computed too, to
|
|
716
719
|
# keep the rounding; in_proj_weight[2E:] alone is ~2x less GEMM.
|
|
717
720
|
embed_dim = self.attention.embed_dim
|
|
@@ -719,16 +722,6 @@ class _ResidualBlock(nn.Module):
|
|
|
719
722
|
value = F.linear(
|
|
720
723
|
seq_first, self.attention.in_proj_weight, self.attention.in_proj_bias
|
|
721
724
|
)[..., 2 * embed_dim :]
|
|
722
|
-
p = self.attention.dropout
|
|
723
|
-
if self.training and p > 0.0:
|
|
724
|
-
n_rows = seq_first.shape[1] * self.attention.num_heads
|
|
725
|
-
keep = (
|
|
726
|
-
value.new_empty(n_rows, seq_len, seq_len)
|
|
727
|
-
.bernoulli_(1 - p)
|
|
728
|
-
.diagonal(dim1=1, dim2=2)
|
|
729
|
-
.div(1 - p)
|
|
730
|
-
)
|
|
731
|
-
value = value.reshape(seq_len, n_rows, -1) * keep.t().unsqueeze(-1)
|
|
732
725
|
h_attn = (
|
|
733
726
|
self.attention.out_proj(value.reshape(-1, embed_dim))
|
|
734
727
|
.view(seq_first.shape)
|
|
@@ -60,7 +60,7 @@ class EEGInceptionMI(EEGModuleMixin, nn.Module):
|
|
|
60
60
|
(:func:`~braindecode.functional.fft_conv1d`: same parameters, equal up
|
|
61
61
|
to float rounding) instead of a direct convolution. ``None`` (default)
|
|
62
62
|
decides per input with :func:`~braindecode.functional.prefer_fft_conv`
|
|
63
|
-
(FFT on CPU
|
|
63
|
+
(FFT on CPU where it was faster in benchmarks, direct on GPU and HPU).
|
|
64
64
|
|
|
65
65
|
References
|
|
66
66
|
----------
|
|
@@ -340,12 +340,8 @@ class _InceptionModuleMI(nn.Module):
|
|
|
340
340
|
X1 = torch.cat([conv(X1) for conv in self.conv_list], 1)
|
|
341
341
|
|
|
342
342
|
# channels_last: same values, but torch's CPU max pool then vectorises
|
|
343
|
-
# over channels instead of looping over them.
|
|
344
|
-
|
|
345
|
-
X2 = X
|
|
346
|
-
if X.device.type == "cpu":
|
|
347
|
-
X2 = X.contiguous(memory_format=torch.channels_last)
|
|
348
|
-
X2 = self.pooling(X2)
|
|
343
|
+
# over channels instead of looping over them.
|
|
344
|
+
X2 = self.pooling(X.contiguous(memory_format=torch.channels_last))
|
|
349
345
|
# An even kernel_unit pools n_times + 1 samples: drop the last one.
|
|
350
346
|
X2 = self.pooling_conv(X2.contiguous())[..., : X.shape[-1]]
|
|
351
347
|
|
{braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eegnex.py
RENAMED
|
@@ -356,7 +356,7 @@ class EEGNeX(EEGModuleMixin, nn.Module):
|
|
|
356
356
|
|
|
357
357
|
|
|
358
358
|
class _TemporalConv(nn.Conv2d):
|
|
359
|
-
"""``(1, k)`` Conv2d with "same" output length; on CPU
|
|
359
|
+
"""``(1, k)`` Conv2d with "same" output length; on CPU, through
|
|
360
360
|
:func:`~braindecode.functional.fft_conv1d` where
|
|
361
361
|
:func:`~braindecode.functional.prefer_fft_conv` expects it to be faster."""
|
|
362
362
|
|
{braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eegpt.py
RENAMED
|
@@ -908,9 +908,7 @@ class _Attention(nn.Module):
|
|
|
908
908
|
# Reshape to (3, batch, num_heads, seq_len, head_dim)
|
|
909
909
|
qkv = qkv.reshape(qkv.shape[0], qkv.shape[1], 3, self.num_heads, -1)
|
|
910
910
|
qkv = qkv.permute(2, 0, 3, 1, 4)
|
|
911
|
-
|
|
912
|
-
# zero-filled copies of the whole qkv tensor and sums them.
|
|
913
|
-
q, k, v = qkv.unbind(0) # batch, num_heads, seq_len, head_dim
|
|
911
|
+
q, k, v = qkv[0], qkv[1], qkv[2] # batch, num_heads, seq_len, head_dim
|
|
914
912
|
|
|
915
913
|
# 1. Rotary Positional Embeddings (RoPE)
|
|
916
914
|
# Unlike standard absolute positional encodings, RoPE rotates the
|
{braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/labram.py
RENAMED
|
@@ -19,7 +19,6 @@ from torch.nn.init import trunc_normal_
|
|
|
19
19
|
from braindecode.functional import rescale_parameter
|
|
20
20
|
from braindecode.models.base import EEGModuleMixin
|
|
21
21
|
from braindecode.modules import MLP, DropPath
|
|
22
|
-
from braindecode.modules.attention import _hpu_eager_fused_sdpa
|
|
23
22
|
from braindecode.modules.blocks import PatchTokenizer
|
|
24
23
|
|
|
25
24
|
# -----------------------------------------------------------------------------
|
|
@@ -1430,24 +1429,17 @@ class _Attention(nn.Module):
|
|
|
1430
1429
|
relative_position_bias.permute(2, 0, 1).contiguous().unsqueeze(0)
|
|
1431
1430
|
) # 1, nH, Wh*Ww, Wh*Ww
|
|
1432
1431
|
|
|
1433
|
-
# Fused kernel, same math. Not
|
|
1434
|
-
#
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1432
|
+
# Fused kernel, same math. Not on Gaudi (Labram trains ~12 % slower there)
|
|
1433
|
+
# nor with attention dropout in training (it would draw other masks).
|
|
1434
|
+
if (
|
|
1435
|
+
not return_attention
|
|
1436
|
+
and q.device.type != "hpu"
|
|
1437
|
+
and (self.attn_drop.p == 0.0 or not self.training)
|
|
1438
|
+
):
|
|
1439
|
+
x = nn.functional.scaled_dot_product_attention(
|
|
1441
1440
|
q, k, v, attn_mask=attn_mask, scale=self.scale
|
|
1442
1441
|
)
|
|
1443
|
-
|
|
1444
|
-
fused
|
|
1445
|
-
and attn_mask is None
|
|
1446
|
-
and not torch.jit.is_scripting()
|
|
1447
|
-
and (q.dtype == torch.float32 or q.dtype == torch.bfloat16)
|
|
1448
|
-
):
|
|
1449
|
-
out = _hpu_eager_fused_sdpa(q, k, v, self.scale)
|
|
1450
|
-
if out is None:
|
|
1442
|
+
else:
|
|
1451
1443
|
attn = (q * self.scale) @ k.transpose(-2, -1)
|
|
1452
1444
|
if attn_mask is not None:
|
|
1453
1445
|
attn = attn + attn_mask
|
|
@@ -1455,8 +1447,6 @@ class _Attention(nn.Module):
|
|
|
1455
1447
|
if return_attention:
|
|
1456
1448
|
return attn
|
|
1457
1449
|
x = attn @ v
|
|
1458
|
-
else:
|
|
1459
|
-
x = out
|
|
1460
1450
|
x = x.transpose(1, 2).reshape(B, N, -1)
|
|
1461
1451
|
|
|
1462
1452
|
x = self.proj(x)
|
{braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/luna.py
RENAMED
|
@@ -601,9 +601,7 @@ class _RotarySelfAttentionBlock(nn.Module):
|
|
|
601
601
|
.reshape(B, N, 3, self.num_heads, C // self.num_heads)
|
|
602
602
|
.permute(2, 0, 3, 1, 4)
|
|
603
603
|
) # (K, B, H, N, D)
|
|
604
|
-
|
|
605
|
-
# zero-filled copies of the whole qkv tensor and sums them.
|
|
606
|
-
q, k, v = qkv.unbind(0)
|
|
604
|
+
q, k, v = qkv[0], qkv[1], qkv[2]
|
|
607
605
|
q = self._rotate_queries_or_keys(q)
|
|
608
606
|
k = self._rotate_queries_or_keys(k)
|
|
609
607
|
attn = F.scaled_dot_product_attention(
|
|
@@ -12,7 +12,6 @@ import torch.nn as nn
|
|
|
12
12
|
import torch.nn.functional as F
|
|
13
13
|
|
|
14
14
|
from braindecode.models.base import EEGModuleMixin
|
|
15
|
-
from braindecode.modules.attention import _scaled_dot_product_attention
|
|
16
15
|
|
|
17
16
|
|
|
18
17
|
class PBT(EEGModuleMixin, nn.Module):
|
|
@@ -412,8 +411,13 @@ class _MHSA(nn.Module):
|
|
|
412
411
|
k = k.view(B, T, self.n_head, C // self.n_head).transpose(1, 2)
|
|
413
412
|
v = v.view(B, T, self.n_head, C // self.n_head).transpose(1, 2)
|
|
414
413
|
|
|
415
|
-
y =
|
|
416
|
-
q,
|
|
414
|
+
y = torch.nn.functional.scaled_dot_product_attention(
|
|
415
|
+
q,
|
|
416
|
+
k,
|
|
417
|
+
v,
|
|
418
|
+
attn_mask=None,
|
|
419
|
+
dropout_p=self.drop_prob if self.training else 0.0,
|
|
420
|
+
is_causal=False,
|
|
417
421
|
)
|
|
418
422
|
|
|
419
423
|
# re-assemble heads -> (B, T, C)
|
{braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/reve.py
RENAMED
|
@@ -15,10 +15,9 @@ import torch
|
|
|
15
15
|
import torch.nn.functional as F
|
|
16
16
|
from mne.datasets.utils import _get_path
|
|
17
17
|
from torch import nn
|
|
18
|
+
from torch.nn import RMSNorm
|
|
18
19
|
|
|
19
20
|
from braindecode.models.base import EEGModuleMixin
|
|
20
|
-
from braindecode.modules.attention import _scaled_dot_product_attention
|
|
21
|
-
from braindecode.modules.layers import RMSNorm
|
|
22
21
|
|
|
23
22
|
logger = logging.getLogger(__name__)
|
|
24
23
|
|
|
@@ -440,8 +439,7 @@ class REVE(EEGModuleMixin, nn.Module):
|
|
|
440
439
|
raise ValueError(
|
|
441
440
|
"No positions provided and no default positions available. Please provide channel positions."
|
|
442
441
|
)
|
|
443
|
-
|
|
444
|
-
pos = self.default_pos.unsqueeze(0).to(eeg.device)
|
|
442
|
+
pos = self.default_pos.expand(batch_size, -1, -1).to(eeg.device)
|
|
445
443
|
|
|
446
444
|
pos = FourierEmb4D.add_time_patch(pos, n_patches)
|
|
447
445
|
# Positions stay in float32 for the Fourier features; the embedding
|
|
@@ -520,7 +518,6 @@ class GEGLU(nn.Module):
|
|
|
520
518
|
class FeedForward(nn.Module):
|
|
521
519
|
def __init__(self, dim: int, hidden_dim: int, geglu: bool):
|
|
522
520
|
super().__init__()
|
|
523
|
-
self.geglu = geglu
|
|
524
521
|
self.net = nn.Sequential(
|
|
525
522
|
RMSNorm(dim, eps=1e-6),
|
|
526
523
|
nn.Linear(dim, hidden_dim * 2 if geglu else hidden_dim, bias=False),
|
|
@@ -529,15 +526,7 @@ class FeedForward(nn.Module):
|
|
|
529
526
|
)
|
|
530
527
|
|
|
531
528
|
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
|
532
|
-
|
|
533
|
-
return self.net(x)
|
|
534
|
-
# GEGLU halves as two matmuls on the weight's row halves: contiguous
|
|
535
|
-
# outputs instead of strided views of one output (copied on HPU).
|
|
536
|
-
x = self.net[0](x)
|
|
537
|
-
weight = self.net[1].weight
|
|
538
|
-
half = weight.shape[0] // 2
|
|
539
|
-
x, gates = F.linear(x, weight[:half]), F.linear(x, weight[half:])
|
|
540
|
-
return self.net[3](F.gelu(gates) * x)
|
|
529
|
+
return self.net(x)
|
|
541
530
|
|
|
542
531
|
|
|
543
532
|
#################################################################################
|
|
@@ -565,8 +554,7 @@ class Attention(nn.Module):
|
|
|
565
554
|
q = q.unflatten(-1, (self.heads, -1)).transpose(1, 2)
|
|
566
555
|
k = k.unflatten(-1, (self.heads, -1)).transpose(1, 2)
|
|
567
556
|
v = v.unflatten(-1, (self.heads, -1)).transpose(1, 2)
|
|
568
|
-
|
|
569
|
-
out = _scaled_dot_product_attention(q, k, v, fused_in_lazy=True)
|
|
557
|
+
out = F.scaled_dot_product_attention(q, k, v)
|
|
570
558
|
return self.to_out(out.transpose(1, 2).flatten(2))
|
|
571
559
|
|
|
572
560
|
|
{braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/zuna.py
RENAMED
|
@@ -12,12 +12,11 @@ import torch
|
|
|
12
12
|
from einops import rearrange
|
|
13
13
|
from einops.layers.torch import Rearrange
|
|
14
14
|
from torch import nn
|
|
15
|
-
from torch.nn import RMSNorm
|
|
15
|
+
from torch.nn import RMSNorm, functional
|
|
16
16
|
|
|
17
17
|
from braindecode.models.base import EEGModuleMixin
|
|
18
18
|
from braindecode.models.util import extract_channel_locations_from_chs_info
|
|
19
19
|
from braindecode.modules import PatchTokenizer
|
|
20
|
-
from braindecode.modules.attention import _scaled_dot_product_attention
|
|
21
20
|
|
|
22
21
|
|
|
23
22
|
class ZUNA(EEGModuleMixin, nn.Module, license="apache-2.0"):
|
|
@@ -404,16 +403,18 @@ class _RotaryPositionEmbedding(nn.Module):
|
|
|
404
403
|
|
|
405
404
|
batch_size, sequence_length, num_heads, head_dim = query.shape
|
|
406
405
|
work = torch.promote_types(query.dtype, torch.float32)
|
|
407
|
-
# Each (real, imaginary) pair (a, b) rotates to (-b, a): swap the pair
|
|
408
|
-
# here; the sign is in ``rotary_sine`` (see _ZUNAEncoder).
|
|
409
406
|
query_pairs = query.to(work).reshape(
|
|
410
407
|
batch_size, sequence_length, num_heads, head_dim // 2, 2
|
|
411
408
|
)
|
|
412
409
|
key_pairs = key.to(work).reshape(
|
|
413
410
|
batch_size, sequence_length, num_heads, head_dim // 2, 2
|
|
414
411
|
)
|
|
415
|
-
rotated_query = self.merge_rotary_pairs(
|
|
416
|
-
|
|
412
|
+
rotated_query = self.merge_rotary_pairs(
|
|
413
|
+
torch.stack((-query_pairs[..., 1], query_pairs[..., 0]), dim=-1)
|
|
414
|
+
)
|
|
415
|
+
rotated_key = self.merge_rotary_pairs(
|
|
416
|
+
torch.stack((-key_pairs[..., 1], key_pairs[..., 0]), dim=-1)
|
|
417
|
+
)
|
|
417
418
|
|
|
418
419
|
query = (query.to(work) * rotary_cosine + rotated_query * rotary_sine).type_as(
|
|
419
420
|
query
|
|
@@ -464,7 +465,7 @@ class _Attention(nn.Module):
|
|
|
464
465
|
value = self.wv(input_tensor).reshape(attention_shape)
|
|
465
466
|
query, key = self.rotary_embedding(query, key, rotary_cosine, rotary_sine)
|
|
466
467
|
|
|
467
|
-
attention_output =
|
|
468
|
+
attention_output = functional.scaled_dot_product_attention(
|
|
468
469
|
query.transpose(1, 2),
|
|
469
470
|
key.transpose(1, 2),
|
|
470
471
|
value.transpose(1, 2),
|
|
@@ -605,12 +606,9 @@ class _ZUNAEncoder(nn.Module):
|
|
|
605
606
|
rotary_frequencies.cos(),
|
|
606
607
|
persistent=False,
|
|
607
608
|
)
|
|
608
|
-
# Sine with the pair rotation's sign folded in: -sin on the real, +sin
|
|
609
|
-
# on the imaginary component of every pair (exact, saves a negation).
|
|
610
|
-
pair_sign = torch.tensor([-1.0, 1.0]).repeat(rotary_frequencies.shape[-1] // 2)
|
|
611
609
|
self.register_buffer(
|
|
612
610
|
"rotary_sine",
|
|
613
|
-
rotary_frequencies.sin()
|
|
611
|
+
rotary_frequencies.sin(),
|
|
614
612
|
persistent=False,
|
|
615
613
|
)
|
|
616
614
|
|
{braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/attention.py
RENAMED
|
@@ -834,57 +834,6 @@ class CATLite(nn.Module):
|
|
|
834
834
|
return channel_score * x
|
|
835
835
|
|
|
836
836
|
|
|
837
|
-
@torch.jit.unused
|
|
838
|
-
def _hpu_eager_fused_sdpa(
|
|
839
|
-
query: Tensor,
|
|
840
|
-
key: Tensor,
|
|
841
|
-
value: Tensor,
|
|
842
|
-
scale: Optional[float] = None,
|
|
843
|
-
fused_in_lazy: bool = False,
|
|
844
|
-
) -> Optional[Tensor]:
|
|
845
|
-
# Lazy mode: None, the graph compiler already fuses torch's SDPA there
|
|
846
|
-
# (unless the caller measured the fused kernel faster for its shapes).
|
|
847
|
-
from habana_frameworks.torch.utils.internal import is_lazy
|
|
848
|
-
|
|
849
|
-
if is_lazy() and not fused_in_lazy:
|
|
850
|
-
return None
|
|
851
|
-
from habana_frameworks.torch.hpex.kernels import FusedSDPA
|
|
852
|
-
|
|
853
|
-
return FusedSDPA.apply(query, key, value, None, 0.0, False, scale, "None", False)
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
def _scaled_dot_product_attention(
|
|
857
|
-
query: Tensor,
|
|
858
|
-
key: Tensor,
|
|
859
|
-
value: Tensor,
|
|
860
|
-
attn_mask: Optional[Tensor] = None,
|
|
861
|
-
dropout_p: float = 0.0,
|
|
862
|
-
fused_in_lazy: bool = False,
|
|
863
|
-
) -> Tensor:
|
|
864
|
-
"""``F.scaled_dot_product_attention``; Gaudi's fused kernel on HPU.
|
|
865
|
-
|
|
866
|
-
In HPU eager mode, torch's SDPA runs op by op (the full
|
|
867
|
-
``(batch, heads, seq, seq)`` scores in device memory), 2-3.5x slower than
|
|
868
|
-
the bridge's fused kernel on long sequences. The fused kernel is used
|
|
869
|
-
without a mask or dropout (its dropout would draw other masks). In lazy
|
|
870
|
-
mode only with ``fused_in_lazy=True``: the graph compiler fuses torch's
|
|
871
|
-
SDPA too, faster on long sequences, slower on short ones.
|
|
872
|
-
"""
|
|
873
|
-
if (
|
|
874
|
-
not torch.jit.is_scripting()
|
|
875
|
-
and query.device.type == "hpu"
|
|
876
|
-
and attn_mask is None
|
|
877
|
-
and dropout_p == 0.0
|
|
878
|
-
and (query.dtype == torch.float32 or query.dtype == torch.bfloat16)
|
|
879
|
-
):
|
|
880
|
-
out = _hpu_eager_fused_sdpa(query, key, value, fused_in_lazy=fused_in_lazy)
|
|
881
|
-
if out is not None:
|
|
882
|
-
return out
|
|
883
|
-
return F.scaled_dot_product_attention(
|
|
884
|
-
query, key, value, attn_mask=attn_mask, dropout_p=dropout_p
|
|
885
|
-
)
|
|
886
|
-
|
|
887
|
-
|
|
888
837
|
class MultiHeadAttention(nn.Module):
|
|
889
838
|
"""Multi-head self-attention block.
|
|
890
839
|
|
|
@@ -958,8 +907,12 @@ class MultiHeadAttention(nn.Module):
|
|
|
958
907
|
dp = self.att_drop if self.training else 0.0
|
|
959
908
|
if self.scale is not None:
|
|
960
909
|
queries = queries * (self.scale * self.head_dim**0.5)
|
|
961
|
-
out =
|
|
962
|
-
queries,
|
|
910
|
+
out = F.scaled_dot_product_attention(
|
|
911
|
+
queries,
|
|
912
|
+
keys,
|
|
913
|
+
values,
|
|
914
|
+
attn_mask=mask,
|
|
915
|
+
dropout_p=dp,
|
|
963
916
|
)
|
|
964
917
|
|
|
965
918
|
out = self.rearrange_unstack(out)
|
|
@@ -10,11 +10,11 @@ import math
|
|
|
10
10
|
from typing import Dict, Optional
|
|
11
11
|
|
|
12
12
|
import torch
|
|
13
|
+
import torch.nn.functional as F
|
|
13
14
|
from torch import nn
|
|
14
15
|
|
|
15
16
|
from braindecode.functional import sinusoidal_positional_encoding
|
|
16
17
|
from braindecode.modules.activation import GatedLinearUnit
|
|
17
|
-
from braindecode.modules.attention import _scaled_dot_product_attention
|
|
18
18
|
from braindecode.modules.layers import ChannelMerger
|
|
19
19
|
|
|
20
20
|
|
|
@@ -28,19 +28,7 @@ class _ConvBlock(nn.Module):
|
|
|
28
28
|
self.act = None if last else activation()
|
|
29
29
|
|
|
30
30
|
def forward(self, x):
|
|
31
|
-
|
|
32
|
-
# zero padding: drop them (the same sum without its zero terms, fewer
|
|
33
|
-
# multiply-adds at long dilations).
|
|
34
|
-
d = self.conv.dilation[0]
|
|
35
|
-
half = self.conv.kernel_size[0] // 2
|
|
36
|
-
reach = (x.shape[-1] - 1) // d
|
|
37
|
-
if reach < half:
|
|
38
|
-
weight = self.conv.weight[:, :, half - reach : half + reach + 1]
|
|
39
|
-
x = nn.functional.conv1d(
|
|
40
|
-
x, weight, self.conv.bias, padding=reach * d, dilation=d
|
|
41
|
-
)
|
|
42
|
-
else:
|
|
43
|
-
x = self.conv(x)
|
|
31
|
+
x = self.conv(x)
|
|
44
32
|
if self.act is not None:
|
|
45
33
|
x = self.act(x)
|
|
46
34
|
return x
|
|
@@ -189,8 +177,7 @@ class _Attention(nn.Module):
|
|
|
189
177
|
q = q.unflatten(-1, (h, -1)).transpose(1, 2)
|
|
190
178
|
k = k.unflatten(-1, (h, -1)).transpose(1, 2)
|
|
191
179
|
v = v.unflatten(-1, (h, -1)).transpose(1, 2)
|
|
192
|
-
|
|
193
|
-
out = _scaled_dot_product_attention(q, k, v)
|
|
180
|
+
out = F.scaled_dot_product_attention(q, k, v, scale=self.scale)
|
|
194
181
|
# (b, h, n, d) -> (b, n, h * d)
|
|
195
182
|
return self.to_out(out.transpose(1, 2).flatten(2))
|
|
196
183
|
|