braindecode 1.8.1.dev169698056__tar.gz → 1.8.1.dev169869285__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.dev169698056/braindecode.egg-info → braindecode-1.8.1.dev169869285}/PKG-INFO +1 -1
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/functional/__init__.py +19 -1
- braindecode-1.8.1.dev169869285/braindecode/functional/attention.py +152 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/functional/functions.py +106 -1
- braindecode-1.8.1.dev169869285/braindecode/functional/initialization.py +139 -0
- braindecode-1.8.1.dev169869285/braindecode/functional/patches.py +105 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/atcnet.py +10 -14
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/attn_sleep.py +9 -13
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/axon.py +11 -4
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/barista.py +27 -26
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/base.py +53 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/bendr.py +20 -12
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/brainbert.py +9 -8
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/brainmodule.py +1 -1
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/brainomni.py +23 -16
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/brant.py +3 -3
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/cbramod.py +12 -11
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/codebrain.py +1 -1
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/csbrain.py +14 -7
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/ctnet.py +3 -30
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/dance.py +6 -11
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/deep4.py +6 -2
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/diver1.py +11 -8
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/duin.py +23 -14
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/eegconformer.py +3 -15
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/eegdino.py +12 -48
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/eeginception_erp.py +4 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/eegminer.py +4 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/eegnet.py +4 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/eegpt.py +21 -270
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/epint.py +26 -10
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/ifnet.py +20 -24
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/labram.py +7 -32
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/luna.py +25 -72
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/mapa.py +22 -14
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/medformer.py +12 -6
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/mirepnet.py +3 -12
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/mscformer.py +3 -31
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/mvpformer.py +18 -10
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/neuropose.py +18 -18
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/neurorvq.py +8 -12
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/neurorvq_tokenizer.py +7 -3
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/patchedtransformer.py +37 -22
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/popt.py +2 -8
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/reve.py +10 -10
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/sensingdynamics.py +18 -19
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/shallow_fbcsp.py +6 -2
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/signal_jepa.py +24 -12
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/sleepfm.py +3 -3
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/sparcnet.py +14 -10
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/steegformer.py +18 -30
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/tcformer.py +37 -37
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/tidnet.py +13 -4
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/tmsanet.py +9 -9
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/util.py +19 -3
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/vemg2pose.py +20 -22
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/zuna.py +2 -2
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/__init__.py +8 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/attention.py +102 -84
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/blocks.py +42 -61
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/dance_modules.py +5 -3
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/layers.py +47 -0
- braindecode-1.8.1.dev169869285/braindecode/version.py +1 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285/braindecode.egg-info}/PKG-INFO +1 -1
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode.egg-info/SOURCES.txt +2 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/api.rst +13 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/whats_new.rst +16 -0
- braindecode-1.8.1.dev169698056/braindecode/functional/initialization.py +0 -52
- braindecode-1.8.1.dev169698056/braindecode/version.py +0 -1
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/LICENSE.txt +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/MANIFEST.in +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/NOTICE.txt +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/README.rst +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/__init__.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/augmentation/__init__.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/augmentation/base.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/augmentation/functional.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/augmentation/transforms.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/classifier.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/__init__.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/_notebook_viewer.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/base.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/bbci.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/bcicomp.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/bids/__init__.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/bids/datasets.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/bids/hub.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/bids/hub_format.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/bids/hub_io.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/bids/hub_validation.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/bids/iterable.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/chb_mit.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/collate.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/mne.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/moabb.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/nmt.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/registry.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/siena.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/sleep_physio_challe_18.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/sleep_physionet.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/tuh.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/utils.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/xy.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datautil/__init__.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datautil/channel_utils.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datautil/hub_formats.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datautil/serialization.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datautil/util.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/eegneuralnet.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/functional/_real_dft.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/__init__.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/attentionbasenet.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/biot.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/config.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/contrawr.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/deepsleepnet.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/dgcnn.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/eeg_clip.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/eeginception_mi.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/eegitnet.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/eegnex.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/eegsimpleconv.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/eegsym.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/eegtcnet.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/emg2qwerty.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/fbcnet.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/fblightconvnet.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/fbmsnet.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/gcnsnet.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/guetschel2026.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/hybrid.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/meta_neuromotor.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/msvtnet.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/sccnet.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/seizure_transformer.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/sinc_shallow.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/sleep_stager_blanco_2020.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/sleep_stager_chambon_2018.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/sstdpn.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/summary.csv +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/syncnet.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/tcn.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/tfm_tokenizer.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/tsinception.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/usleep.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/activation.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/channels.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/convolution.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/filter.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/linear.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/linear_attention.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/parametrization.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/quantization.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/stats.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/util.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/wrapper.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/preprocessing/__init__.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/preprocessing/eegprep_preprocess.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/preprocessing/mne_preprocess.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/preprocessing/preprocess.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/preprocessing/util.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/preprocessing/windowers.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/regressor.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/samplers/__init__.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/samplers/base.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/samplers/ssl.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/training/__init__.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/training/callbacks.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/training/losses.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/training/scoring.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/util.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/visualization/__init__.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/visualization/activations.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/visualization/attribution.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/visualization/confusion_matrices.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/visualization/frequency.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/visualization/metrics.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/visualization/sanity.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/visualization/topology.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode.egg-info/dependency_links.txt +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode.egg-info/requires.txt +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode.egg-info/top_level.txt +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/Makefile +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/_templates/autosummary/class.rst +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/_templates/autosummary/class_in_subdir.rst +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/_templates/autosummary/function.rst +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/_templates/autosummary/function_in_subdir.rst +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/agent_docs.rst +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/cite.rst +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/conf.py +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/help.rst +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/index.rst +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/install/install.rst +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/install/install_pip.rst +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/install/install_source.rst +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/models/categorization/attention.rst +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/models/categorization/channel.rst +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/models/categorization/convolution.rst +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/models/categorization/filterbank.rst +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/models/categorization/gnn.rst +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/models/categorization/interpretable.rst +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/models/categorization/lbm.rst +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/models/categorization/recurrent.rst +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/models/categorization/spd.rst +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/models/models.rst +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/models/models_categorization.rst +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/models/models_table.rst +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/models/models_visualization.rst +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/sg_execution_times.rst +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/user_guide/channel_strategies.rst +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/pyproject.toml +0 -0
- {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/setup.cfg +0 -0
{braindecode-1.8.1.dev169698056/braindecode.egg-info → braindecode-1.8.1.dev169869285}/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.dev169869285
|
|
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.dev169698056 → braindecode-1.8.1.dev169869285}/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,
|
|
@@ -17,10 +22,16 @@ from .functions import (
|
|
|
17
22
|
square,
|
|
18
23
|
wavelet_decomposition,
|
|
19
24
|
)
|
|
20
|
-
from .initialization import
|
|
25
|
+
from .initialization import (
|
|
26
|
+
glorot_weight_zero_bias,
|
|
27
|
+
init_weights_,
|
|
28
|
+
rescale_parameter,
|
|
29
|
+
)
|
|
30
|
+
from .patches import pad_or_crop_to_patches, patch_count
|
|
21
31
|
|
|
22
32
|
__all__ = [
|
|
23
33
|
"_get_gaussian_kernel1d",
|
|
34
|
+
"apply_rotary",
|
|
24
35
|
"daubechies_filters",
|
|
25
36
|
"drop_path",
|
|
26
37
|
"dwt_max_level",
|
|
@@ -28,15 +39,22 @@ __all__ = [
|
|
|
28
39
|
"hilbert_freq",
|
|
29
40
|
"identity",
|
|
30
41
|
"iou_1d",
|
|
42
|
+
"pad_or_crop_to_patches",
|
|
31
43
|
"pairwise_iou_1d",
|
|
44
|
+
"patch_count",
|
|
32
45
|
"plv_time",
|
|
33
46
|
"prefer_fft_conv",
|
|
47
|
+
"rotary_angles",
|
|
48
|
+
"rotary_frequencies",
|
|
49
|
+
"rotate_half",
|
|
34
50
|
"rotate_pairs",
|
|
35
51
|
"safe_log",
|
|
52
|
+
"scaled_dot_product_attention",
|
|
36
53
|
"sinusoidal_positional_encoding",
|
|
37
54
|
"spectral_input",
|
|
38
55
|
"square",
|
|
39
56
|
"wavelet_decomposition",
|
|
40
57
|
"glorot_weight_zero_bias",
|
|
41
58
|
"rescale_parameter",
|
|
59
|
+
"init_weights_",
|
|
42
60
|
]
|
|
@@ -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,139 @@
|
|
|
1
|
+
import math
|
|
2
|
+
|
|
3
|
+
import torch
|
|
4
|
+
from torch import nn
|
|
5
|
+
from torch.nn.utils import parametrize
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def glorot_weight_zero_bias(model):
|
|
9
|
+
"""Set the weights of BatchNorm layers to one and all biases to zero.
|
|
10
|
+
|
|
11
|
+
Despite its name, this function does not apply the Glorot (Xavier)
|
|
12
|
+
initialization: other weights keep the initialization of their layer
|
|
13
|
+
(PyTorch's default, or Xavier uniform for the max-norm constrained layers
|
|
14
|
+
such as :class:`braindecode.modules.Conv2dWithConstraint`). The name is
|
|
15
|
+
kept for backward compatibility.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
model : Module
|
|
20
|
+
"""
|
|
21
|
+
for module in model.modules():
|
|
22
|
+
# ``weight``/``bias`` can be None (e.g. BatchNorm with affine=False)
|
|
23
|
+
weight = getattr(module, "weight", None)
|
|
24
|
+
if isinstance(weight, torch.Tensor) and "BatchNorm" in type(module).__name__:
|
|
25
|
+
nn.init.constant_(weight, 1)
|
|
26
|
+
bias = getattr(module, "bias", None)
|
|
27
|
+
if isinstance(bias, torch.Tensor):
|
|
28
|
+
nn.init.constant_(bias, 0)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def rescale_parameter(param, layer_id):
|
|
32
|
+
r"""Recaling the l-th transformer layer.
|
|
33
|
+
|
|
34
|
+
Rescales the parameter tensor by the inverse square root of the layer id.
|
|
35
|
+
Made inplace. :math:`\frac{1}{\sqrt{2 \cdot \text{layer\_id}}}` [Beit2022]
|
|
36
|
+
|
|
37
|
+
In the labram, this is used to rescale the output matrices
|
|
38
|
+
(i.e., the last linear projection within each sub-layer) of the
|
|
39
|
+
self-attention module.
|
|
40
|
+
|
|
41
|
+
Parameters
|
|
42
|
+
----------
|
|
43
|
+
param: :class:`torch.Tensor`
|
|
44
|
+
tensor to be rescaled
|
|
45
|
+
layer_id: int
|
|
46
|
+
layer id in the neural network
|
|
47
|
+
|
|
48
|
+
References
|
|
49
|
+
----------
|
|
50
|
+
[Beit2022] Hangbo Bao, Li Dong, Songhao Piao, Furu We (2022). BEIT: BERT
|
|
51
|
+
Pre-Training of Image Transformers.
|
|
52
|
+
"""
|
|
53
|
+
param.div_(math.sqrt(2.0 * layer_id))
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def init_weights_(
|
|
57
|
+
module,
|
|
58
|
+
weights=None,
|
|
59
|
+
norms=(nn.LayerNorm,),
|
|
60
|
+
init_parametrized_original=False,
|
|
61
|
+
):
|
|
62
|
+
"""Initialize one module by layer type; apply to a model with ``model.apply``.
|
|
63
|
+
|
|
64
|
+
The first entry of ``weights`` whose type matches ``module`` gives its rule,
|
|
65
|
+
as in an ``if``/``elif`` chain; modules of a type in ``norms`` get a unit
|
|
66
|
+
weight and a zero bias; nothing else is touched. The default is the
|
|
67
|
+
timm/ViT scheme (truncated-normal ``nn.Linear`` weights with std 0.02,
|
|
68
|
+
unit/zero ``nn.LayerNorm``). Models pass their own rules to reproduce their
|
|
69
|
+
reference initialization exactly.
|
|
70
|
+
|
|
71
|
+
Parameters
|
|
72
|
+
----------
|
|
73
|
+
module : torch.nn.Module
|
|
74
|
+
weights : dict or None
|
|
75
|
+
``{layer type or tuple of types: rule}``. A rule is a function applied
|
|
76
|
+
to the ``weight`` (the ``bias`` is then set to zero), or a pair
|
|
77
|
+
``(weight_fn, bias_fn)`` where either may be ``None`` to leave that
|
|
78
|
+
tensor as it is. For a layer without a ``weight`` attribute (e.g.
|
|
79
|
+
``nn.LSTM``) the functions apply to every parameter whose name contains
|
|
80
|
+
``"weight"`` / ``"bias"``. ``None`` uses
|
|
81
|
+
``{nn.Linear: partial(nn.init.trunc_normal_, std=0.02)}``.
|
|
82
|
+
norms : tuple of type
|
|
83
|
+
Normalization layer types set to weight 1 and bias 0 (missing affine
|
|
84
|
+
parameters are skipped). ``()`` leaves normalization layers alone.
|
|
85
|
+
init_parametrized_original : bool
|
|
86
|
+
For a layer whose ``weight`` is parametrized (e.g. max-norm), initialize
|
|
87
|
+
the unconstrained ``parametrizations.weight.original`` instead of the
|
|
88
|
+
computed ``weight``.
|
|
89
|
+
|
|
90
|
+
Examples
|
|
91
|
+
--------
|
|
92
|
+
>>> from functools import partial
|
|
93
|
+
>>> from torch import nn
|
|
94
|
+
>>> model = nn.Sequential(nn.Linear(4, 4), nn.LayerNorm(4))
|
|
95
|
+
>>> _ = model.apply(init_weights_) # timm/ViT default
|
|
96
|
+
>>> kaiming = partial(nn.init.kaiming_normal_, mode="fan_out")
|
|
97
|
+
>>> rule = {nn.Linear: (kaiming, None)} # keep the default bias
|
|
98
|
+
>>> _ = model.apply(partial(init_weights_, weights=rule, norms=()))
|
|
99
|
+
"""
|
|
100
|
+
if weights is None:
|
|
101
|
+
weights = {nn.Linear: _trunc_normal_002}
|
|
102
|
+
for types, rule in weights.items():
|
|
103
|
+
if isinstance(module, types):
|
|
104
|
+
weight_fn, bias_fn = (
|
|
105
|
+
rule if isinstance(rule, tuple) else (rule, nn.init.zeros_)
|
|
106
|
+
)
|
|
107
|
+
if not hasattr(module, "weight"): # e.g. nn.LSTM: weight_ih_l0, ...
|
|
108
|
+
for name, param in module.named_parameters(recurse=False):
|
|
109
|
+
fn = (
|
|
110
|
+
weight_fn
|
|
111
|
+
if "weight" in name
|
|
112
|
+
else bias_fn
|
|
113
|
+
if "bias" in name
|
|
114
|
+
else None
|
|
115
|
+
)
|
|
116
|
+
if fn is not None:
|
|
117
|
+
fn(param)
|
|
118
|
+
return
|
|
119
|
+
if isinstance(module.weight, nn.parameter.UninitializedParameter):
|
|
120
|
+
return # lazy layer: initialized when it gets its shape
|
|
121
|
+
if weight_fn is not None:
|
|
122
|
+
weight = module.weight
|
|
123
|
+
if init_parametrized_original and parametrize.is_parametrized(
|
|
124
|
+
module, "weight"
|
|
125
|
+
):
|
|
126
|
+
weight = module.parametrizations.weight.original
|
|
127
|
+
weight_fn(weight)
|
|
128
|
+
if bias_fn is not None and getattr(module, "bias", None) is not None:
|
|
129
|
+
bias_fn(module.bias)
|
|
130
|
+
return
|
|
131
|
+
if norms and isinstance(module, norms):
|
|
132
|
+
if getattr(module, "weight", None) is not None:
|
|
133
|
+
nn.init.ones_(module.weight)
|
|
134
|
+
if getattr(module, "bias", None) is not None:
|
|
135
|
+
nn.init.zeros_(module.bias)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def _trunc_normal_002(tensor):
|
|
139
|
+
return nn.init.trunc_normal_(tensor, std=0.02)
|
|
@@ -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.dev169698056 → braindecode-1.8.1.dev169869285}/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,
|
|
@@ -826,6 +826,12 @@ class _TCNResidualBlock(nn.Module):
|
|
|
826
826
|
# (reshaping_conv may be nn.Identity, which the helper skips).
|
|
827
827
|
_register_max_norm(conv_max_norm, self.conv1, self.conv2, self.reshaping_conv)
|
|
828
828
|
|
|
829
|
+
def reset_parameters(self) -> None:
|
|
830
|
+
"""Initialize this block's weights (the constructor initializes each
|
|
831
|
+
convolution as it builds it)."""
|
|
832
|
+
nn.init.kaiming_uniform_(self.conv1.weight)
|
|
833
|
+
nn.init.kaiming_uniform_(self.conv2.weight)
|
|
834
|
+
|
|
829
835
|
def forward(self, X):
|
|
830
836
|
# Dimension: (batch_size, F2, Tw)
|
|
831
837
|
# ----- Double dilated convolutions -----
|
|
@@ -928,20 +934,10 @@ class _MHA(nn.Module):
|
|
|
928
934
|
K_ = torch.cat(K.split(self.head_dim, -1), 0) # (B', S, D')
|
|
929
935
|
V_ = torch.cat(V.split(self.head_dim, -1), 0) # (B', S, D')
|
|
930
936
|
|
|
931
|
-
#
|
|
932
|
-
#
|
|
933
|
-
W = torch.softmax(
|
|
934
|
-
Q_.bmm(K_.transpose(-2, -1)) / math.sqrt(self.head_dim),
|
|
935
|
-
-1, # (B', D', S)
|
|
936
|
-
) # (B', N, M)
|
|
937
|
-
|
|
938
|
-
# Multihead output (batch_size, seq_len, dim):
|
|
939
|
-
# weighted sum of V where a value gets more weight if its corresponding
|
|
940
|
-
# 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.
|
|
941
939
|
H = torch.cat(
|
|
942
|
-
(
|
|
943
|
-
batch_size, 0
|
|
944
|
-
), # [(B, S, D')] * num_heads
|
|
940
|
+
scaled_dot_product_attention(Q_, K_, V_, exact=True).split(batch_size, 0),
|
|
945
941
|
-1,
|
|
946
942
|
) # (B, S, D)
|
|
947
943
|
|