braindecode 1.8.1.dev173644701__tar.gz → 1.8.1.dev173738593__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.dev173644701/braindecode.egg-info → braindecode-1.8.1.dev173738593}/PKG-INFO +2 -1
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/functional/__init__.py +13 -0
- braindecode-1.8.1.dev173738593/braindecode/functional/attention.py +152 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/functional/functions.py +106 -1
- braindecode-1.8.1.dev173738593/braindecode/functional/patches.py +105 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/atcnet.py +4 -14
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/attn_sleep.py +9 -13
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/axon.py +5 -3
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/barista.py +17 -18
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/biot.py +6 -56
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/brainbert.py +9 -8
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/brainmodule.py +1 -1
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/brainomni.py +4 -5
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/brant.py +3 -3
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/codebrain.py +1 -1
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/csbrain.py +3 -3
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/ctnet.py +15 -55
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/diver1.py +11 -8
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/duin.py +7 -3
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/eegdino.py +16 -66
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/eegpt.py +19 -338
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/epint.py +11 -6
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/ifnet.py +20 -24
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/labram.py +1 -1
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/luna.py +35 -91
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/medformer.py +11 -20
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/mscformer.py +16 -60
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/neurorvq.py +39 -61
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/neurorvq_tokenizer.py +5 -5
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/patchedtransformer.py +2 -3
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/popt.py +2 -8
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/reve.py +10 -10
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/signal_jepa.py +12 -13
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/sleepfm.py +3 -3
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/tcformer.py +22 -24
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/tmsanet.py +9 -9
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/util.py +19 -3
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/zuna.py +2 -2
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/modules/__init__.py +10 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/modules/attention.py +102 -84
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/modules/blocks.py +42 -61
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/modules/dance_modules.py +5 -3
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/modules/layers.py +134 -2
- braindecode-1.8.1.dev173738593/braindecode/version.py +1 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593/braindecode.egg-info}/PKG-INFO +2 -1
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode.egg-info/SOURCES.txt +2 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode.egg-info/requires.txt +1 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/api.rst +13 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/whats_new.rst +14 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/pyproject.toml +6 -0
- braindecode-1.8.1.dev173644701/braindecode/version.py +0 -1
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/LICENSE.txt +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/MANIFEST.in +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/NOTICE.txt +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/README.rst +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/__init__.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/augmentation/__init__.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/augmentation/base.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/augmentation/functional.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/augmentation/transforms.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/classifier.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datasets/__init__.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datasets/_notebook_viewer.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datasets/base.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datasets/bbci.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datasets/bcicomp.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datasets/bids/__init__.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datasets/bids/datasets.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datasets/bids/hub.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datasets/bids/hub_format.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datasets/bids/hub_io.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datasets/bids/hub_validation.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datasets/bids/iterable.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datasets/chb_mit.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datasets/collate.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datasets/mne.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datasets/moabb.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datasets/nmt.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datasets/registry.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datasets/siena.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datasets/sleep_physio_challe_18.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datasets/sleep_physionet.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datasets/tuh.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datasets/utils.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datasets/xy.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datautil/__init__.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datautil/channel_utils.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datautil/hub_formats.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datautil/serialization.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/datautil/util.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/eegneuralnet.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/functional/_real_dft.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/functional/initialization.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/__init__.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/attentionbasenet.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/base.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/bendr.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/cbramod.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/config.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/contrawr.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/dance.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/deep4.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/deepsleepnet.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/dgcnn.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/eeg_clip.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/eegconformer.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/eeginception_erp.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/eeginception_mi.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/eegitnet.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/eegminer.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/eegnet.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/eegnex.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/eegsimpleconv.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/eegsym.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/eegtcnet.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/emg2qwerty.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/fbcnet.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/fblightconvnet.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/fbmsnet.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/gcnsnet.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/guetschel2026.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/hybrid.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/mapa.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/meta_neuromotor.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/mirepnet.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/msvtnet.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/mvpformer.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/neuropose.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/sccnet.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/seizure_transformer.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/sensingdynamics.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/shallow_fbcsp.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/sinc_shallow.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/sleep_stager_blanco_2020.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/sleep_stager_chambon_2018.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/sparcnet.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/sstdpn.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/steegformer.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/summary.csv +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/syncnet.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/tcn.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/tfm_tokenizer.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/tidnet.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/tsinception.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/usleep.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/vemg2pose.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/modules/activation.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/modules/channels.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/modules/convolution.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/modules/filter.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/modules/linear.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/modules/linear_attention.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/modules/parametrization.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/modules/quantization.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/modules/stats.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/modules/util.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/modules/wrapper.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/preprocessing/__init__.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/preprocessing/eegprep_preprocess.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/preprocessing/mne_preprocess.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/preprocessing/preprocess.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/preprocessing/util.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/preprocessing/windowers.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/regressor.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/samplers/__init__.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/samplers/base.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/samplers/ssl.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/training/__init__.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/training/callbacks.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/training/losses.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/training/scoring.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/util.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/visualization/__init__.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/visualization/activations.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/visualization/attribution.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/visualization/confusion_matrices.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/visualization/frequency.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/visualization/metrics.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/visualization/sanity.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/visualization/topology.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode.egg-info/dependency_links.txt +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode.egg-info/top_level.txt +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/Makefile +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/_templates/autosummary/class.rst +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/_templates/autosummary/class_in_subdir.rst +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/_templates/autosummary/function.rst +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/_templates/autosummary/function_in_subdir.rst +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/agent_docs.rst +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/cite.rst +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/conf.py +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/help.rst +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/index.rst +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/install/install.rst +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/install/install_pip.rst +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/install/install_source.rst +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/models/categorization/attention.rst +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/models/categorization/channel.rst +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/models/categorization/convolution.rst +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/models/categorization/filterbank.rst +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/models/categorization/gnn.rst +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/models/categorization/interpretable.rst +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/models/categorization/lbm.rst +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/models/categorization/recurrent.rst +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/models/categorization/spd.rst +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/models/models.rst +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/models/models_categorization.rst +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/models/models_table.rst +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/models/models_visualization.rst +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/sg_execution_times.rst +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/docs/user_guide/channel_strategies.rst +0 -0
- {braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/setup.cfg +0 -0
{braindecode-1.8.1.dev173644701/braindecode.egg-info → braindecode-1.8.1.dev173738593}/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.dev173738593
|
|
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>
|
|
@@ -50,6 +50,7 @@ Provides-Extra: tests
|
|
|
50
50
|
Requires-Dist: pytest<9.1; extra == "tests"
|
|
51
51
|
Requires-Dist: pytest-cov; extra == "tests"
|
|
52
52
|
Requires-Dist: pytest-xdist>=3.8.0; extra == "tests"
|
|
53
|
+
Requires-Dist: pytest-timeout; extra == "tests"
|
|
53
54
|
Requires-Dist: codecov; extra == "tests"
|
|
54
55
|
Requires-Dist: pytest_cases; extra == "tests"
|
|
55
56
|
Requires-Dist: mypy; extra == "tests"
|
{braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/functional/__init__.py
RENAMED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
from .attention import scaled_dot_product_attention
|
|
1
2
|
from .functions import (
|
|
2
3
|
_get_gaussian_kernel1d,
|
|
4
|
+
apply_rotary,
|
|
3
5
|
daubechies_filters,
|
|
4
6
|
drop_path,
|
|
5
7
|
dwt_max_level,
|
|
@@ -10,6 +12,9 @@ from .functions import (
|
|
|
10
12
|
pairwise_iou_1d,
|
|
11
13
|
plv_time,
|
|
12
14
|
prefer_fft_conv,
|
|
15
|
+
rotary_angles,
|
|
16
|
+
rotary_frequencies,
|
|
17
|
+
rotate_half,
|
|
13
18
|
rotate_pairs,
|
|
14
19
|
safe_log,
|
|
15
20
|
sinusoidal_positional_encoding,
|
|
@@ -22,9 +27,11 @@ from .initialization import (
|
|
|
22
27
|
init_weights_,
|
|
23
28
|
rescale_parameter,
|
|
24
29
|
)
|
|
30
|
+
from .patches import pad_or_crop_to_patches, patch_count
|
|
25
31
|
|
|
26
32
|
__all__ = [
|
|
27
33
|
"_get_gaussian_kernel1d",
|
|
34
|
+
"apply_rotary",
|
|
28
35
|
"daubechies_filters",
|
|
29
36
|
"drop_path",
|
|
30
37
|
"dwt_max_level",
|
|
@@ -32,11 +39,17 @@ __all__ = [
|
|
|
32
39
|
"hilbert_freq",
|
|
33
40
|
"identity",
|
|
34
41
|
"iou_1d",
|
|
42
|
+
"pad_or_crop_to_patches",
|
|
35
43
|
"pairwise_iou_1d",
|
|
44
|
+
"patch_count",
|
|
36
45
|
"plv_time",
|
|
37
46
|
"prefer_fft_conv",
|
|
47
|
+
"rotary_angles",
|
|
48
|
+
"rotary_frequencies",
|
|
49
|
+
"rotate_half",
|
|
38
50
|
"rotate_pairs",
|
|
39
51
|
"safe_log",
|
|
52
|
+
"scaled_dot_product_attention",
|
|
40
53
|
"sinusoidal_positional_encoding",
|
|
41
54
|
"spectral_input",
|
|
42
55
|
"square",
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"""Scaled dot-product attention with the device-specific paths in one place."""
|
|
2
|
+
|
|
3
|
+
# Authors: Bruno Aristimunha <b.aristimunha@gmail.com>
|
|
4
|
+
#
|
|
5
|
+
# License: BSD (3-clause)
|
|
6
|
+
|
|
7
|
+
import math
|
|
8
|
+
from typing import Optional
|
|
9
|
+
|
|
10
|
+
import torch
|
|
11
|
+
import torch.nn.functional as F
|
|
12
|
+
from torch import Tensor
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@torch.jit.unused
|
|
16
|
+
def _hpu_eager_fused_sdpa(
|
|
17
|
+
query: Tensor,
|
|
18
|
+
key: Tensor,
|
|
19
|
+
value: Tensor,
|
|
20
|
+
scale: Optional[float] = None,
|
|
21
|
+
fused_in_lazy: bool = False,
|
|
22
|
+
) -> Optional[Tensor]:
|
|
23
|
+
# Lazy mode: None, the graph compiler already fuses torch's SDPA there
|
|
24
|
+
# (unless the caller measured the fused kernel faster for its shapes).
|
|
25
|
+
from habana_frameworks.torch.utils.internal import is_lazy
|
|
26
|
+
|
|
27
|
+
if is_lazy() and not fused_in_lazy:
|
|
28
|
+
return None
|
|
29
|
+
from habana_frameworks.torch.hpex.kernels import FusedSDPA
|
|
30
|
+
|
|
31
|
+
# Strided q/k/v views (heads split off a projection) give wrong outputs and
|
|
32
|
+
# gradients at some shapes; contiguous copies give the right result.
|
|
33
|
+
query, key, value = query.contiguous(), key.contiguous(), value.contiguous()
|
|
34
|
+
return FusedSDPA.apply(query, key, value, None, 0.0, False, scale, "None", False)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@torch.jit.unused
|
|
38
|
+
def _hpu_lazy() -> bool:
|
|
39
|
+
from habana_frameworks.torch.utils.internal import is_lazy
|
|
40
|
+
|
|
41
|
+
return is_lazy()
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _sdpa_math_dropout(
|
|
45
|
+
query: Tensor,
|
|
46
|
+
key: Tensor,
|
|
47
|
+
value: Tensor,
|
|
48
|
+
dropout_p: float,
|
|
49
|
+
scale: Optional[float] = None,
|
|
50
|
+
) -> Tensor:
|
|
51
|
+
# torch's math path for SDPA with dropout, op for op, without the pass of
|
|
52
|
+
# ``_safe_softmax`` that zeroes fully masked rows (none without a mask):
|
|
53
|
+
# same values, same dropout draws.
|
|
54
|
+
if scale is None:
|
|
55
|
+
scale = 1.0 / math.sqrt(query.size(-1))
|
|
56
|
+
half = math.sqrt(scale)
|
|
57
|
+
attn = torch.matmul(query * half, key.transpose(-2, -1) * half)
|
|
58
|
+
attn = F.dropout(attn.softmax(-1), dropout_p, True)
|
|
59
|
+
return torch.matmul(attn, value)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def scaled_dot_product_attention(
|
|
63
|
+
query: Tensor,
|
|
64
|
+
key: Tensor,
|
|
65
|
+
value: Tensor,
|
|
66
|
+
attn_mask: Optional[Tensor] = None,
|
|
67
|
+
dropout_p: float = 0.0,
|
|
68
|
+
scale: Optional[float] = None,
|
|
69
|
+
fused_in_lazy: bool = False,
|
|
70
|
+
exact: bool = False,
|
|
71
|
+
) -> Tensor:
|
|
72
|
+
"""``F.scaled_dot_product_attention``; Gaudi's fused kernel on HPU.
|
|
73
|
+
|
|
74
|
+
Parameters
|
|
75
|
+
----------
|
|
76
|
+
query, key, value : torch.Tensor
|
|
77
|
+
Shape ``(..., seq, head_dim)``; ``key``/``value`` may have another
|
|
78
|
+
sequence length.
|
|
79
|
+
attn_mask : torch.Tensor, optional
|
|
80
|
+
Boolean (``True`` takes part) or additive mask, as in torch.
|
|
81
|
+
dropout_p : float, default=0.0
|
|
82
|
+
Dropout on the attention weights; pass ``0.0`` in eval mode.
|
|
83
|
+
scale : float, optional
|
|
84
|
+
Score scale; ``None`` is ``1 / sqrt(head_dim)``.
|
|
85
|
+
fused_in_lazy : bool, default=False
|
|
86
|
+
Use Gaudi's fused kernel in HPU lazy mode too.
|
|
87
|
+
exact : bool, default=False
|
|
88
|
+
Run the textbook op order instead of torch's kernels:
|
|
89
|
+
``softmax((q @ k^T) / sqrt(d)) @ v``, or ``softmax((q @ k^T) * scale) @ v``
|
|
90
|
+
when ``scale`` is given, with dropout on the weights. Bit-identical to
|
|
91
|
+
a hand-written attention; torch's kernels round differently (its math
|
|
92
|
+
path scales ``q`` and ``k`` by ``sqrt(scale)`` each before the matmul,
|
|
93
|
+
its fused CPU kernel runs a blocked softmax), about 1e-6 apart.
|
|
94
|
+
|
|
95
|
+
Returns
|
|
96
|
+
-------
|
|
97
|
+
torch.Tensor
|
|
98
|
+
Shape ``(..., seq, head_dim)``.
|
|
99
|
+
|
|
100
|
+
In HPU eager mode, torch's SDPA runs op by op (the full
|
|
101
|
+
``(batch, heads, seq, seq)`` scores in device memory), 2-3.5x slower than
|
|
102
|
+
the bridge's fused kernel on long sequences. The fused kernel is used
|
|
103
|
+
without a mask or dropout (its dropout would draw other masks). In lazy
|
|
104
|
+
mode only with ``fused_in_lazy=True``: the graph compiler fuses torch's
|
|
105
|
+
SDPA too, faster on long sequences, slower on short ones.
|
|
106
|
+
"""
|
|
107
|
+
if exact:
|
|
108
|
+
scores = torch.matmul(query, key.transpose(-2, -1))
|
|
109
|
+
if scale is None:
|
|
110
|
+
scores = scores / math.sqrt(query.size(-1))
|
|
111
|
+
else:
|
|
112
|
+
scores = scores * scale
|
|
113
|
+
if attn_mask is not None:
|
|
114
|
+
if attn_mask.dtype == torch.bool:
|
|
115
|
+
scores = scores.masked_fill(~attn_mask, float("-inf"))
|
|
116
|
+
else:
|
|
117
|
+
scores = scores + attn_mask
|
|
118
|
+
weights = scores.softmax(dim=-1)
|
|
119
|
+
if dropout_p > 0.0:
|
|
120
|
+
weights = F.dropout(weights, dropout_p, True)
|
|
121
|
+
return torch.matmul(weights, value)
|
|
122
|
+
if (
|
|
123
|
+
not torch.jit.is_scripting()
|
|
124
|
+
and query.device.type == "hpu"
|
|
125
|
+
and attn_mask is None
|
|
126
|
+
and dropout_p == 0.0
|
|
127
|
+
and (query.dtype == torch.float32 or query.dtype == torch.bfloat16)
|
|
128
|
+
):
|
|
129
|
+
out = _hpu_eager_fused_sdpa(
|
|
130
|
+
query, key, value, scale=scale, fused_in_lazy=fused_in_lazy
|
|
131
|
+
)
|
|
132
|
+
if out is not None:
|
|
133
|
+
return out
|
|
134
|
+
if (
|
|
135
|
+
not torch.jit.is_scripting()
|
|
136
|
+
and dropout_p > 0.0
|
|
137
|
+
and attn_mask is None
|
|
138
|
+
and (query.dtype == torch.float32 or query.dtype == torch.float64)
|
|
139
|
+
and (
|
|
140
|
+
query.device.type == "cpu"
|
|
141
|
+
or (query.device.type == "hpu" and not _hpu_lazy())
|
|
142
|
+
)
|
|
143
|
+
):
|
|
144
|
+
# CPU and HPU eager run SDPA with dropout through the math path.
|
|
145
|
+
return _sdpa_math_dropout(query, key, value, dropout_p, scale)
|
|
146
|
+
if scale is None: # torch 2.0's signature has no ``scale``
|
|
147
|
+
return F.scaled_dot_product_attention(
|
|
148
|
+
query, key, value, attn_mask=attn_mask, dropout_p=dropout_p
|
|
149
|
+
)
|
|
150
|
+
return F.scaled_dot_product_attention(
|
|
151
|
+
query, key, value, attn_mask=attn_mask, dropout_p=dropout_p, scale=scale
|
|
152
|
+
)
|
|
@@ -588,6 +588,7 @@ def sinusoidal_positional_encoding(
|
|
|
588
588
|
dim: int,
|
|
589
589
|
device: torch.device | None = None,
|
|
590
590
|
dtype: torch.dtype = torch.float32,
|
|
591
|
+
base: float = 10000.0,
|
|
591
592
|
) -> torch.Tensor:
|
|
592
593
|
r"""Fixed sine/cosine positional-encoding table of shape ``(n_positions, dim)``.
|
|
593
594
|
|
|
@@ -609,6 +610,9 @@ def sinusoidal_positional_encoding(
|
|
|
609
610
|
Device of the table (default: CPU), for tables built inside ``forward``.
|
|
610
611
|
dtype : torch.dtype
|
|
611
612
|
Floating dtype the table is computed in.
|
|
613
|
+
base : float, default=10000.0
|
|
614
|
+
Longest wavelength, the ``10000`` of Vaswani et al.; SignalJEPA uses the
|
|
615
|
+
largest number of time samples it encodes.
|
|
612
616
|
|
|
613
617
|
Returns
|
|
614
618
|
-------
|
|
@@ -620,7 +624,7 @@ def sinusoidal_positional_encoding(
|
|
|
620
624
|
position = torch.arange(n_positions, device=device).unsqueeze(1).to(dtype)
|
|
621
625
|
div_term = torch.exp(
|
|
622
626
|
torch.arange(0, dim_even, 2, device=device).to(dtype)
|
|
623
|
-
* (-math.log(
|
|
627
|
+
* (-math.log(base) / dim_even)
|
|
624
628
|
)
|
|
625
629
|
pe = torch.zeros(n_positions, dim_even, device=device, dtype=dtype)
|
|
626
630
|
pe[:, 0::2] = torch.sin(position * div_term)
|
|
@@ -646,3 +650,104 @@ def rotate_pairs(x: torch.Tensor) -> torch.Tensor:
|
|
|
646
650
|
"""
|
|
647
651
|
pairs = x.unflatten(-1, (-1, 2))
|
|
648
652
|
return torch.stack((-pairs[..., 1], pairs[..., 0]), dim=-1).flatten(-2)
|
|
653
|
+
|
|
654
|
+
|
|
655
|
+
def rotate_half(x: torch.Tensor) -> torch.Tensor:
|
|
656
|
+
"""Rotate the two feature halves from ``(a, b)`` to ``(-b, a)``.
|
|
657
|
+
|
|
658
|
+
The half-split layout of GPT-NeoX / LLaMA rotary embeddings; see
|
|
659
|
+
:func:`rotate_pairs` for the interleaved layout.
|
|
660
|
+
|
|
661
|
+
Parameters
|
|
662
|
+
----------
|
|
663
|
+
x : torch.Tensor
|
|
664
|
+
Tensor of shape ``(..., features)`` with an even final dimension.
|
|
665
|
+
|
|
666
|
+
Returns
|
|
667
|
+
-------
|
|
668
|
+
torch.Tensor
|
|
669
|
+
Same shape, device and dtype as ``x``.
|
|
670
|
+
"""
|
|
671
|
+
first, second = x.chunk(2, dim=-1)
|
|
672
|
+
return torch.cat((-second, first), dim=-1)
|
|
673
|
+
|
|
674
|
+
|
|
675
|
+
def rotary_frequencies(
|
|
676
|
+
head_dim: int,
|
|
677
|
+
base: float = 10000.0,
|
|
678
|
+
device: Optional[torch.device] = None,
|
|
679
|
+
dtype: torch.dtype = torch.float32,
|
|
680
|
+
) -> torch.Tensor:
|
|
681
|
+
"""Inverse frequencies of a rotary embedding, ``1 / base ** (2 i / head_dim)``.
|
|
682
|
+
|
|
683
|
+
Parameters
|
|
684
|
+
----------
|
|
685
|
+
head_dim : int
|
|
686
|
+
Even feature dimension that is rotated.
|
|
687
|
+
base : float, default=10000.0
|
|
688
|
+
Base period (``theta``).
|
|
689
|
+
device : torch.device, optional
|
|
690
|
+
dtype : torch.dtype, default=torch.float32
|
|
691
|
+
Precision of the table; the angles inherit it.
|
|
692
|
+
|
|
693
|
+
Returns
|
|
694
|
+
-------
|
|
695
|
+
torch.Tensor
|
|
696
|
+
Shape ``(head_dim // 2,)``.
|
|
697
|
+
"""
|
|
698
|
+
exponent = torch.arange(0, head_dim, 2, device=device, dtype=dtype) / head_dim
|
|
699
|
+
return 1.0 / (base**exponent)
|
|
700
|
+
|
|
701
|
+
|
|
702
|
+
def rotary_angles(
|
|
703
|
+
positions: torch.Tensor, inv_freq: torch.Tensor, interleaved: bool = True
|
|
704
|
+
) -> torch.Tensor:
|
|
705
|
+
"""Rotation angles of each position, laid out to match the feature layout.
|
|
706
|
+
|
|
707
|
+
Parameters
|
|
708
|
+
----------
|
|
709
|
+
positions : torch.Tensor
|
|
710
|
+
Shape ``(...,)``; same dtype as ``inv_freq`` for exact angles.
|
|
711
|
+
inv_freq : torch.Tensor
|
|
712
|
+
Shape ``(head_dim // 2,)``, from :func:`rotary_frequencies`.
|
|
713
|
+
interleaved : bool, default=True
|
|
714
|
+
``True`` repeats each angle for its adjacent pair (:func:`rotate_pairs`);
|
|
715
|
+
``False`` concatenates the angles twice (:func:`rotate_half`).
|
|
716
|
+
|
|
717
|
+
Returns
|
|
718
|
+
-------
|
|
719
|
+
torch.Tensor
|
|
720
|
+
Shape ``(..., head_dim)``; pass ``.cos()`` and ``.sin()`` to
|
|
721
|
+
:func:`apply_rotary`.
|
|
722
|
+
"""
|
|
723
|
+
angles = positions.unsqueeze(-1) * inv_freq
|
|
724
|
+
if interleaved:
|
|
725
|
+
return angles.repeat_interleave(2, dim=-1)
|
|
726
|
+
return torch.cat((angles, angles), dim=-1)
|
|
727
|
+
|
|
728
|
+
|
|
729
|
+
def apply_rotary(
|
|
730
|
+
x: torch.Tensor, cos: torch.Tensor, sin: torch.Tensor, interleaved: bool = True
|
|
731
|
+
) -> torch.Tensor:
|
|
732
|
+
"""Rotate ``x`` by the angles whose cosine and sine are given.
|
|
733
|
+
|
|
734
|
+
``x * cos + rotate(x) * sin``, where ``rotate`` is :func:`rotate_pairs`
|
|
735
|
+
(``interleaved=True``) or :func:`rotate_half`. ``cos`` and ``sin`` must
|
|
736
|
+
broadcast to ``x``; casting is left to the caller.
|
|
737
|
+
|
|
738
|
+
Parameters
|
|
739
|
+
----------
|
|
740
|
+
x : torch.Tensor
|
|
741
|
+
Shape ``(..., head_dim)``.
|
|
742
|
+
cos, sin : torch.Tensor
|
|
743
|
+
From :func:`rotary_angles`.
|
|
744
|
+
interleaved : bool, default=True
|
|
745
|
+
Feature layout, as in :func:`rotary_angles`.
|
|
746
|
+
|
|
747
|
+
Returns
|
|
748
|
+
-------
|
|
749
|
+
torch.Tensor
|
|
750
|
+
Same shape as ``x``.
|
|
751
|
+
"""
|
|
752
|
+
rotated = rotate_pairs(x) if interleaved else rotate_half(x)
|
|
753
|
+
return x * cos + rotated * sin
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"""Cutting a time axis into patches: how many, and padding or cropping to fit."""
|
|
2
|
+
|
|
3
|
+
# Authors: Bruno Aristimunha <b.aristimunha@gmail.com>
|
|
4
|
+
#
|
|
5
|
+
# License: BSD (3-clause)
|
|
6
|
+
|
|
7
|
+
import torch
|
|
8
|
+
import torch.nn.functional as F
|
|
9
|
+
|
|
10
|
+
_ON_NON_DIVISIBLE = ("pad", "crop", "error")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _check_on_non_divisible(on_non_divisible: str) -> None:
|
|
14
|
+
"""Raise a ``ValueError`` for an unknown ``on_non_divisible`` value."""
|
|
15
|
+
if on_non_divisible not in _ON_NON_DIVISIBLE:
|
|
16
|
+
raise ValueError(
|
|
17
|
+
"on_non_divisible must be 'pad', 'crop', or 'error', "
|
|
18
|
+
f"got {on_non_divisible!r}."
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def patch_count(
|
|
23
|
+
n_times: int, patch_size: int, on_non_divisible: str = "pad", step: int = 0
|
|
24
|
+
) -> int:
|
|
25
|
+
"""Number of patches cut from ``n_times`` samples.
|
|
26
|
+
|
|
27
|
+
Parameters
|
|
28
|
+
----------
|
|
29
|
+
n_times : int
|
|
30
|
+
Length of the axis that is patched.
|
|
31
|
+
patch_size : int
|
|
32
|
+
Samples per patch.
|
|
33
|
+
on_non_divisible : {"pad", "crop", "error"}, default="pad"
|
|
34
|
+
A last, incomplete patch is zero-padded (``"pad"``), dropped
|
|
35
|
+
(``"crop"``) or raises a ``ValueError``.
|
|
36
|
+
step : int, default=0
|
|
37
|
+
Distance between patch starts; ``0`` means ``patch_size``
|
|
38
|
+
(non-overlapping).
|
|
39
|
+
|
|
40
|
+
Returns
|
|
41
|
+
-------
|
|
42
|
+
int
|
|
43
|
+
Number of patches.
|
|
44
|
+
"""
|
|
45
|
+
if step <= 0:
|
|
46
|
+
step = patch_size
|
|
47
|
+
if n_times < 1:
|
|
48
|
+
raise ValueError(f"n_times must be positive, got {n_times}.")
|
|
49
|
+
if n_times < patch_size:
|
|
50
|
+
if on_non_divisible == "pad":
|
|
51
|
+
return 1
|
|
52
|
+
if on_non_divisible == "crop":
|
|
53
|
+
raise ValueError(
|
|
54
|
+
f"Need at least one full patch of {patch_size} samples, got {n_times}."
|
|
55
|
+
)
|
|
56
|
+
elif (n_times - patch_size) % step == 0:
|
|
57
|
+
return (n_times - patch_size) // step + 1
|
|
58
|
+
elif on_non_divisible != "error":
|
|
59
|
+
return (n_times - patch_size) // step + 1 + (on_non_divisible == "pad")
|
|
60
|
+
raise ValueError(
|
|
61
|
+
f"Time dimension ({n_times}) is not divisible by patch_size ({patch_size})"
|
|
62
|
+
+ ("." if step == patch_size else f" with patch step {step}.")
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def pad_or_crop_to_patches(
|
|
67
|
+
x: torch.Tensor,
|
|
68
|
+
patch_size: int,
|
|
69
|
+
on_non_divisible: str = "pad",
|
|
70
|
+
step: int = 0,
|
|
71
|
+
min_patches: int = 1,
|
|
72
|
+
center: bool = False,
|
|
73
|
+
) -> torch.Tensor:
|
|
74
|
+
"""Right zero-pad or crop the last axis so the patches tile it.
|
|
75
|
+
|
|
76
|
+
A tiled axis is returned as is. An axis short of ``min_patches`` patches is
|
|
77
|
+
zero-padded up to that many, with half the missing ones (whole steps)
|
|
78
|
+
before it if ``center``.
|
|
79
|
+
|
|
80
|
+
Parameters
|
|
81
|
+
----------
|
|
82
|
+
x : torch.Tensor
|
|
83
|
+
Shape ``(..., n_times)``.
|
|
84
|
+
patch_size, on_non_divisible, step
|
|
85
|
+
As in :func:`patch_count`.
|
|
86
|
+
min_patches : int, default=1
|
|
87
|
+
Least number of patches on the returned axis.
|
|
88
|
+
center : bool, default=False
|
|
89
|
+
Pad half the missing patches on the left.
|
|
90
|
+
|
|
91
|
+
Returns
|
|
92
|
+
-------
|
|
93
|
+
torch.Tensor
|
|
94
|
+
Shape ``(..., patch_size + (n_patches - 1) * step)``.
|
|
95
|
+
"""
|
|
96
|
+
n_patches = patch_count(x.shape[-1], patch_size, on_non_divisible, step)
|
|
97
|
+
step = step if step > 0 else patch_size
|
|
98
|
+
left = 0
|
|
99
|
+
if n_patches < min_patches:
|
|
100
|
+
left = (min_patches - n_patches) // 2 * step if center else 0
|
|
101
|
+
n_patches = min_patches
|
|
102
|
+
target = patch_size + (n_patches - 1) * step
|
|
103
|
+
if target > x.shape[-1]:
|
|
104
|
+
return F.pad(x, (left, target - x.shape[-1] - left))
|
|
105
|
+
return x[..., :target]
|
{braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/atcnet.py
RENAMED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# Authors: Cedric Rommel <cedric.rommel@inria.fr>
|
|
2
2
|
#
|
|
3
3
|
# License: BSD (3-clause)
|
|
4
|
-
import math
|
|
5
4
|
from typing import Optional
|
|
6
5
|
|
|
7
6
|
import torch
|
|
@@ -10,6 +9,7 @@ from mne.utils import warn
|
|
|
10
9
|
from torch import nn
|
|
11
10
|
from torch.nn.utils.parametrize import is_parametrized, register_parametrization
|
|
12
11
|
|
|
12
|
+
from braindecode.functional import scaled_dot_product_attention
|
|
13
13
|
from braindecode.models.base import EEGModuleMixin
|
|
14
14
|
from braindecode.modules import (
|
|
15
15
|
CausalConv1d,
|
|
@@ -934,20 +934,10 @@ class _MHA(nn.Module):
|
|
|
934
934
|
K_ = torch.cat(K.split(self.head_dim, -1), 0) # (B', S, D')
|
|
935
935
|
V_ = torch.cat(V.split(self.head_dim, -1), 0) # (B', S, D')
|
|
936
936
|
|
|
937
|
-
#
|
|
938
|
-
#
|
|
939
|
-
W = torch.softmax(
|
|
940
|
-
Q_.bmm(K_.transpose(-2, -1)) / math.sqrt(self.head_dim),
|
|
941
|
-
-1, # (B', D', S)
|
|
942
|
-
) # (B', N, M)
|
|
943
|
-
|
|
944
|
-
# Multihead output (batch_size, seq_len, dim):
|
|
945
|
-
# weighted sum of V where a value gets more weight if its corresponding
|
|
946
|
-
# key has larger dot product with the query.
|
|
937
|
+
# Multihead output (batch_size, seq_len, dim): softmax(Q K^T / sqrt(d)) V
|
|
938
|
+
# per head, heads merged back along the feature axis.
|
|
947
939
|
H = torch.cat(
|
|
948
|
-
(
|
|
949
|
-
batch_size, 0
|
|
950
|
-
), # [(B, S, D')] * num_heads
|
|
940
|
+
scaled_dot_product_attention(Q_, K_, V_, exact=True).split(batch_size, 0),
|
|
951
941
|
-1,
|
|
952
942
|
) # (B, S, D)
|
|
953
943
|
|
{braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/attn_sleep.py
RENAMED
|
@@ -27,15 +27,14 @@
|
|
|
27
27
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
28
28
|
# SOFTWARE.
|
|
29
29
|
|
|
30
|
-
import math
|
|
31
30
|
import warnings
|
|
32
31
|
from copy import deepcopy
|
|
33
32
|
from numbers import Integral
|
|
34
33
|
|
|
35
34
|
import torch
|
|
36
|
-
import torch.nn.functional as F
|
|
37
35
|
from torch import nn
|
|
38
36
|
|
|
37
|
+
from braindecode.functional import scaled_dot_product_attention
|
|
39
38
|
from braindecode.models.base import EEGModuleMixin
|
|
40
39
|
from braindecode.modules import CausalConv1d
|
|
41
40
|
|
|
@@ -411,14 +410,6 @@ class _MRCNN(nn.Module):
|
|
|
411
410
|
##########################################################################################
|
|
412
411
|
|
|
413
412
|
|
|
414
|
-
def _attention(query: torch.Tensor, key: torch.Tensor) -> torch.Tensor:
|
|
415
|
-
"""Scaled dot product attention weights."""
|
|
416
|
-
# d_k - dimension of the query and key vectors
|
|
417
|
-
d_k = query.size(-1)
|
|
418
|
-
scores = torch.matmul(query, key.transpose(-2, -1)) / math.sqrt(d_k)
|
|
419
|
-
return F.softmax(scores, dim=-1) # attention weights
|
|
420
|
-
|
|
421
|
-
|
|
422
413
|
class _MultiHeadedAttention(nn.Module):
|
|
423
414
|
def __init__(self, h, d_model, after_reduced_cnn_size, dropout=0.1):
|
|
424
415
|
"""Take in model size and number of heads."""
|
|
@@ -464,9 +455,14 @@ class _MultiHeadedAttention(nn.Module):
|
|
|
464
455
|
.transpose(1, 2)
|
|
465
456
|
)
|
|
466
457
|
|
|
467
|
-
#
|
|
468
|
-
|
|
469
|
-
|
|
458
|
+
# exact: the reference op order, same outputs as its hand-written attention
|
|
459
|
+
x = scaled_dot_product_attention(
|
|
460
|
+
query,
|
|
461
|
+
key,
|
|
462
|
+
value,
|
|
463
|
+
dropout_p=self.dropout.p if self.training else 0.0,
|
|
464
|
+
exact=True,
|
|
465
|
+
)
|
|
470
466
|
|
|
471
467
|
# merge heads and project
|
|
472
468
|
x = x.transpose(1, 2).contiguous().view(nbatches, -1, self.h * self.d_per_head)
|
{braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/axon.py
RENAMED
|
@@ -11,10 +11,12 @@ import torch
|
|
|
11
11
|
import torch.nn.functional as F
|
|
12
12
|
from torch import nn
|
|
13
13
|
|
|
14
|
-
from braindecode.functional import
|
|
14
|
+
from braindecode.functional import (
|
|
15
|
+
scaled_dot_product_attention,
|
|
16
|
+
sinusoidal_positional_encoding,
|
|
17
|
+
)
|
|
15
18
|
from braindecode.models.base import EEGModuleMixin
|
|
16
19
|
from braindecode.models.util import warn_if_sfreq_differs
|
|
17
|
-
from braindecode.modules.attention import _scaled_dot_product_attention
|
|
18
20
|
from braindecode.modules.channels import _resolve
|
|
19
21
|
|
|
20
22
|
|
|
@@ -468,7 +470,7 @@ class _AxisAttention(nn.Module):
|
|
|
468
470
|
.unbind(0)
|
|
469
471
|
)
|
|
470
472
|
drop = self.att_drop_prob if self.training else 0.0
|
|
471
|
-
attended =
|
|
473
|
+
attended = scaled_dot_product_attention(
|
|
472
474
|
query, key, value, attn_mask=mask, dropout_p=drop
|
|
473
475
|
)
|
|
474
476
|
return attended.transpose(1, 2).reshape(n_seq, length, -1)
|
{braindecode-1.8.1.dev173644701 → braindecode-1.8.1.dev173738593}/braindecode/models/barista.py
RENAMED
|
@@ -11,12 +11,18 @@ import torch
|
|
|
11
11
|
from einops.layers.torch import Rearrange
|
|
12
12
|
from torch import nn
|
|
13
13
|
|
|
14
|
-
from braindecode.functional import
|
|
14
|
+
from braindecode.functional import (
|
|
15
|
+
apply_rotary,
|
|
16
|
+
init_weights_,
|
|
17
|
+
patch_count,
|
|
18
|
+
rotary_angles,
|
|
19
|
+
rotary_frequencies,
|
|
20
|
+
scaled_dot_product_attention,
|
|
21
|
+
)
|
|
22
|
+
from braindecode.functional.patches import _check_on_non_divisible
|
|
15
23
|
from braindecode.models.base import EEGModuleMixin
|
|
16
24
|
from braindecode.models.util import extract_channel_locations_from_chs_info
|
|
17
25
|
from braindecode.modules import GatedLinearUnit, PatchTokenizer
|
|
18
|
-
from braindecode.modules.attention import _scaled_dot_product_attention
|
|
19
|
-
from braindecode.modules.blocks import _check_on_non_divisible, _patch_count
|
|
20
26
|
|
|
21
27
|
# Weight initialization of the reference implementation.
|
|
22
28
|
_init_weights = partial(
|
|
@@ -287,7 +293,7 @@ class BaRISTA(EEGModuleMixin, nn.Module, license="other"):
|
|
|
287
293
|
# ceil(n_times / patch_size) with "pad"; floor with "crop" (the
|
|
288
294
|
# reference: trailing samples dropped, raises below one patch); exact
|
|
289
295
|
# with "error" (raises otherwise). The learned pooling is sized to it.
|
|
290
|
-
self.n_patches =
|
|
296
|
+
self.n_patches = patch_count(self.n_times, patch_size, on_non_divisible)
|
|
291
297
|
|
|
292
298
|
self.patch_tokenizer = PatchTokenizer(
|
|
293
299
|
patch_size=patch_size,
|
|
@@ -609,7 +615,7 @@ class _Transformer(nn.Module):
|
|
|
609
615
|
):
|
|
610
616
|
super().__init__()
|
|
611
617
|
head_dim = d_model // num_heads
|
|
612
|
-
inv_freq =
|
|
618
|
+
inv_freq = rotary_frequencies(head_dim)
|
|
613
619
|
self.inv_freq: torch.Tensor
|
|
614
620
|
self.register_buffer("inv_freq", inv_freq, persistent=False)
|
|
615
621
|
self.layers = nn.ModuleList(
|
|
@@ -633,8 +639,8 @@ class _Transformer(nn.Module):
|
|
|
633
639
|
positions = torch.arange(
|
|
634
640
|
n_patches, device=self.inv_freq.device, dtype=self.inv_freq.dtype
|
|
635
641
|
)
|
|
636
|
-
angles =
|
|
637
|
-
angles =
|
|
642
|
+
angles = rotary_angles(positions, self.inv_freq, interleaved=False)
|
|
643
|
+
angles = angles.repeat_interleave(n_chans, dim=0)
|
|
638
644
|
cos = angles.cos()[None, None]
|
|
639
645
|
sin = angles.sin()[None, None]
|
|
640
646
|
for layer in self.layers:
|
|
@@ -698,20 +704,13 @@ class _RotarySelfAttention(nn.Module):
|
|
|
698
704
|
key = self.split_heads(key)
|
|
699
705
|
value = self.split_heads(value)
|
|
700
706
|
|
|
701
|
-
|
|
702
|
-
|
|
707
|
+
cos, sin = cos.to(query.dtype), sin.to(query.dtype)
|
|
708
|
+
query = apply_rotary(query, cos, sin, interleaved=False)
|
|
709
|
+
key = apply_rotary(key, cos, sin, interleaved=False)
|
|
703
710
|
|
|
704
711
|
# Dropout falls on the attention output rather than on the weights,
|
|
705
712
|
# through dropout_p, because the reference disables the latter outright.
|
|
706
|
-
attention =
|
|
713
|
+
attention = scaled_dot_product_attention(query, key, value)
|
|
707
714
|
attention = self.dropout(attention)
|
|
708
715
|
attention = self.merge_heads(attention)
|
|
709
716
|
return self.o_proj(attention)
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
def _apply_rotary(
|
|
713
|
-
x: torch.Tensor, cos: torch.Tensor, sin: torch.Tensor
|
|
714
|
-
) -> torch.Tensor:
|
|
715
|
-
"""Apply the reference's half-split (not interleaved) rotary embedding."""
|
|
716
|
-
first, second = x.chunk(2, dim=-1)
|
|
717
|
-
return x * cos.to(x.dtype) + torch.cat((-second, first), dim=-1) * sin.to(x.dtype)
|