braindecode 1.3.2.dev179983996__tar.gz → 1.3.2.dev182544824__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.3.2.dev179983996/braindecode.egg-info → braindecode-1.3.2.dev182544824}/PKG-INFO +3 -3
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datasets/bids/hub.py +7 -2
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/__init__.py +2 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/base.py +147 -91
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/cbramod.py +19 -5
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/config.py +29 -29
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/eegsym.py +1 -1
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/luna.py +8 -7
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/patchedtransformer.py +5 -3
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/reve.py +23 -3
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/shallow_fbcsp.py +16 -8
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/sstdpn.py +1 -1
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/util.py +133 -2
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/modules/__init__.py +2 -1
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/modules/activation.py +20 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/preprocessing/mne_preprocess.py +2 -1
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/util.py +34 -4
- braindecode-1.3.2.dev182544824/braindecode/version.py +1 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824/braindecode.egg-info}/PKG-INFO +3 -3
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode.egg-info/requires.txt +2 -2
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/docs/api.rst +10 -9
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/docs/conf.py +18 -6
- braindecode-1.3.2.dev182544824/docs/models/categorization/spd.rst +103 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/docs/models/models_categorization.rst +58 -57
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/docs/whats_new.rst +40 -6
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/pyproject.toml +11 -2
- braindecode-1.3.2.dev179983996/braindecode/version.py +0 -1
- braindecode-1.3.2.dev179983996/docs/models/categorization/spd.rst +0 -35
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/LICENSE.txt +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/MANIFEST.in +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/NOTICE.txt +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/README.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/__init__.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/augmentation/__init__.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/augmentation/base.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/augmentation/functional.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/augmentation/transforms.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/classifier.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datasets/__init__.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datasets/base.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datasets/bbci.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datasets/bcicomp.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datasets/bids/__init__.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datasets/bids/datasets.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datasets/bids/format.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datasets/bids/hub_format.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datasets/bids/hub_io.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datasets/bids/hub_validation.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datasets/bids/iterable.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datasets/chb_mit.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datasets/mne.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datasets/moabb.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datasets/nmt.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datasets/registry.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datasets/siena.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datasets/sleep_physio_challe_18.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datasets/sleep_physionet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datasets/tuh.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datasets/utils.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datasets/xy.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datautil/__init__.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datautil/channel_utils.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datautil/hub_formats.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datautil/serialization.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datautil/util.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/eegneuralnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/functional/__init__.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/functional/functions.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/functional/initialization.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/atcnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/attentionbasenet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/attn_sleep.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/bendr.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/biot.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/brainmodule.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/contrawr.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/ctnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/deep4.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/deepsleepnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/dgcnn.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/eegconformer.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/eeginception_erp.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/eeginception_mi.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/eegitnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/eegminer.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/eegnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/eegnex.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/eegpt.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/eegsimpleconv.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/eegtcnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/fbcnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/fblightconvnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/fbmsnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/hybrid.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/ifnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/labram.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/medformer.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/msvtnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/sccnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/signal_jepa.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/sinc_shallow.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/sleep_stager_blanco_2020.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/sleep_stager_chambon_2018.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/sparcnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/summary.csv +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/syncnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/tcn.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/tidnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/tsinception.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/usleep.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/modules/attention.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/modules/blocks.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/modules/convolution.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/modules/filter.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/modules/layers.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/modules/linear.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/modules/parametrization.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/modules/stats.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/modules/util.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/modules/wrapper.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/preprocessing/__init__.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/preprocessing/eegprep_preprocess.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/preprocessing/preprocess.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/preprocessing/util.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/preprocessing/windowers.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/regressor.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/samplers/__init__.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/samplers/base.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/samplers/ssl.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/training/__init__.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/training/callbacks.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/training/losses.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/training/scoring.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/visualization/__init__.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/visualization/confusion_matrices.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/visualization/gradients.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode.egg-info/SOURCES.txt +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode.egg-info/dependency_links.txt +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode.egg-info/top_level.txt +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/docs/Makefile +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/docs/_templates/autosummary/class.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/docs/_templates/autosummary/class_in_subdir.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/docs/_templates/autosummary/function.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/docs/_templates/autosummary/function_in_subdir.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/docs/cite.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/docs/help.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/docs/index.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/docs/install/install.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/docs/install/install_pip.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/docs/install/install_source.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/docs/models/categorization/attention.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/docs/models/categorization/channel.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/docs/models/categorization/convolution.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/docs/models/categorization/filterbank.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/docs/models/categorization/gnn.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/docs/models/categorization/interpretable.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/docs/models/categorization/lbm.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/docs/models/categorization/recurrent.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/docs/models/models.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/docs/models/models_table.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/docs/models/models_visualization.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/docs/sg_execution_times.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/setup.cfg +0 -0
{braindecode-1.3.2.dev179983996/braindecode.egg-info → braindecode-1.3.2.dev182544824}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: braindecode
|
|
3
|
-
Version: 1.3.2.
|
|
3
|
+
Version: 1.3.2.dev182544824
|
|
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>
|
|
@@ -22,7 +22,7 @@ Requires-Python: >=3.11
|
|
|
22
22
|
Description-Content-Type: text/x-rst
|
|
23
23
|
License-File: LICENSE.txt
|
|
24
24
|
License-File: NOTICE.txt
|
|
25
|
-
Requires-Dist: torch>=2.
|
|
25
|
+
Requires-Dist: torch>=2.0
|
|
26
26
|
Requires-Dist: torchaudio>=2.0
|
|
27
27
|
Requires-Dist: mne>=1.11.0
|
|
28
28
|
Requires-Dist: pandas<3.0.0
|
|
@@ -35,7 +35,7 @@ Requires-Dist: wfdb
|
|
|
35
35
|
Requires-Dist: linear_attention_transformer
|
|
36
36
|
Requires-Dist: docstring_inheritance
|
|
37
37
|
Requires-Dist: rotary_embedding_torch
|
|
38
|
-
Requires-Dist:
|
|
38
|
+
Requires-Dist: pydantic>=2.0
|
|
39
39
|
Provides-Extra: moabb
|
|
40
40
|
Requires-Dist: moabb>=1.4.3; extra == "moabb"
|
|
41
41
|
Provides-Extra: eegprep
|
{braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/datasets/bids/hub.py
RENAMED
|
@@ -845,11 +845,16 @@ class HubDatasetMixin:
|
|
|
845
845
|
|
|
846
846
|
# Convert to MNE objects and create dataset
|
|
847
847
|
info = Info.from_json_dict(info_dict)
|
|
848
|
+
targets = metadata["target"].values
|
|
849
|
+
if np.issubdtype(targets.dtype, np.integer):
|
|
850
|
+
event_ids = targets
|
|
851
|
+
else:
|
|
852
|
+
event_ids = np.ones(len(metadata), dtype=int)
|
|
848
853
|
events = np.column_stack(
|
|
849
854
|
[
|
|
850
|
-
metadata["i_start_in_trial"].values,
|
|
855
|
+
metadata["i_start_in_trial"].values.astype(int),
|
|
851
856
|
np.zeros(len(metadata), dtype=int),
|
|
852
|
-
|
|
857
|
+
event_ids,
|
|
853
858
|
]
|
|
854
859
|
)
|
|
855
860
|
epochs = mne.EpochsArray(data, info, events=events, metadata=metadata)
|
{braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/__init__.py
RENAMED
|
@@ -55,6 +55,7 @@ from .tsinception import TSception
|
|
|
55
55
|
from .usleep import USleep
|
|
56
56
|
from .util import (
|
|
57
57
|
_init_models_dict,
|
|
58
|
+
build_model_config,
|
|
58
59
|
extract_channel_locations_from_chs_info,
|
|
59
60
|
models_mandatory_parameters,
|
|
60
61
|
)
|
|
@@ -118,6 +119,7 @@ __all__ = [
|
|
|
118
119
|
"TIDNet",
|
|
119
120
|
"TSception",
|
|
120
121
|
"USleep",
|
|
122
|
+
"build_model_config",
|
|
121
123
|
"_init_models_dict",
|
|
122
124
|
"models_mandatory_parameters",
|
|
123
125
|
]
|
{braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/base.py
RENAMED
|
@@ -17,6 +17,13 @@ from docstring_inheritance import NumpyDocstringInheritanceInitMeta
|
|
|
17
17
|
from mne.utils import _soft_import
|
|
18
18
|
from torchinfo import ModelStatistics, summary
|
|
19
19
|
|
|
20
|
+
from braindecode.models.util import (
|
|
21
|
+
_EEG_PARAMS,
|
|
22
|
+
_IMPORT_ADAPTER,
|
|
23
|
+
build_model_config,
|
|
24
|
+
resolve_type_kwargs,
|
|
25
|
+
track_model_init_kwargs,
|
|
26
|
+
)
|
|
20
27
|
from braindecode.version import __version__
|
|
21
28
|
|
|
22
29
|
huggingface_hub = _soft_import(
|
|
@@ -86,61 +93,69 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=NumpyDocstringInheritanceInitMeta)
|
|
|
86
93
|
-----
|
|
87
94
|
If some input signal-related parameters are not specified,
|
|
88
95
|
there will be an attempt to infer them from the other parameters.
|
|
96
|
+
"""
|
|
89
97
|
|
|
98
|
+
#: Template for model-specific Hub integration notes appended by
|
|
99
|
+
#: ``__init_subclass__``. ``{name}`` is replaced with the concrete
|
|
100
|
+
#: model class name.
|
|
101
|
+
_HUB_NOTES_TEMPLATE = """
|
|
90
102
|
.. rubric:: Hugging Face Hub integration
|
|
91
103
|
|
|
92
104
|
When the optional ``huggingface_hub`` package is installed, all models
|
|
93
105
|
automatically gain the ability to be pushed to and loaded from the
|
|
94
106
|
Hugging Face Hub. Install with::
|
|
95
107
|
|
|
96
|
-
pip install braindecode[
|
|
108
|
+
pip install braindecode[hub]
|
|
97
109
|
|
|
98
110
|
**Pushing a model to the Hub:**
|
|
99
111
|
|
|
100
|
-
.. code-block::
|
|
112
|
+
.. code-block::
|
|
101
113
|
|
|
102
|
-
from braindecode.models import
|
|
114
|
+
from braindecode.models import {name}
|
|
103
115
|
|
|
104
116
|
# Train your model
|
|
105
|
-
model =
|
|
117
|
+
model = {name}(n_chans=22, n_outputs=4, n_times=1000)
|
|
106
118
|
# ... training code ...
|
|
107
119
|
|
|
108
120
|
# Push to the Hub
|
|
109
121
|
model.push_to_hub(
|
|
110
|
-
repo_id="username/my-
|
|
122
|
+
repo_id="username/my-{name_lower}-model",
|
|
123
|
+
commit_message="Initial model upload",
|
|
111
124
|
)
|
|
112
125
|
|
|
113
126
|
**Loading a model from the Hub:**
|
|
114
127
|
|
|
115
|
-
.. code-block::
|
|
128
|
+
.. code-block::
|
|
116
129
|
|
|
117
|
-
from braindecode.models import
|
|
130
|
+
from braindecode.models import {name}
|
|
118
131
|
|
|
119
132
|
# Load pretrained model
|
|
120
|
-
model =
|
|
133
|
+
model = {name}.from_pretrained("username/my-{name_lower}-model")
|
|
121
134
|
|
|
122
135
|
The integration automatically handles EEG-specific parameters (n_chans,
|
|
123
136
|
n_times, sfreq, chs_info, etc.) by saving them in a config file alongside
|
|
124
137
|
the model weights. This ensures that loaded models are correctly configured
|
|
125
138
|
for their original data specifications.
|
|
126
139
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
parameters (e.g., dropout rates, activation functions, number of filters)
|
|
131
|
-
are not preserved and will use their default values when loading from the Hub.
|
|
132
|
-
|
|
133
|
-
To use non-default model parameters, specify them explicitly when calling
|
|
134
|
-
:func:`from_pretrained()`::
|
|
135
|
-
|
|
136
|
-
model = EEGNet.from_pretrained("user/model", dropout=0.3, activation='relu')
|
|
137
|
-
|
|
138
|
-
Full parameter serialization will be addressed in a future update.
|
|
140
|
+
All model parameters (both EEG-specific and model-specific such as
|
|
141
|
+
dropout rates, activation functions, number of filters) are automatically
|
|
142
|
+
saved to the Hub and restored when loading.
|
|
139
143
|
"""
|
|
140
144
|
|
|
141
145
|
def __init_subclass__(cls, **kwargs):
|
|
146
|
+
# Append model-specific Hub integration notes to the docstring.
|
|
147
|
+
# This runs after the metaclass, so we concatenate rather than
|
|
148
|
+
# override any existing Notes section in the subclass.
|
|
149
|
+
if cls.__doc__ is not None:
|
|
150
|
+
hub_notes = cls._HUB_NOTES_TEMPLATE.format(
|
|
151
|
+
name=cls.__name__,
|
|
152
|
+
name_lower=cls.__name__.lower(),
|
|
153
|
+
)
|
|
154
|
+
cls.__doc__ = cls.__doc__.rstrip() + "\n" + hub_notes
|
|
155
|
+
|
|
142
156
|
if not HAS_HF_HUB:
|
|
143
157
|
super().__init_subclass__(**kwargs)
|
|
158
|
+
track_model_init_kwargs(cls)
|
|
144
159
|
return
|
|
145
160
|
|
|
146
161
|
base_tags = ["braindecode", cls.__name__]
|
|
@@ -157,6 +172,19 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=NumpyDocstringInheritanceInitMeta)
|
|
|
157
172
|
repo_url = kwargs.pop("repo_url", "https://braindecode.org")
|
|
158
173
|
library_name = kwargs.pop("library_name", "braindecode")
|
|
159
174
|
license = kwargs.pop("license", "bsd-3-clause")
|
|
175
|
+
|
|
176
|
+
# Register a coder so that type[nn.Module] parameters
|
|
177
|
+
# (e.g. activation=nn.ELU) are serialized as importable
|
|
178
|
+
# strings in config.json and decoded back on load.
|
|
179
|
+
coders = kwargs.pop("coders", None) or {}
|
|
180
|
+
coders.setdefault(
|
|
181
|
+
type,
|
|
182
|
+
(
|
|
183
|
+
lambda t: f"{t.__module__}.{t.__qualname__}",
|
|
184
|
+
lambda data: _IMPORT_ADAPTER.validate_python(data),
|
|
185
|
+
),
|
|
186
|
+
)
|
|
187
|
+
|
|
160
188
|
# TODO: model_card_template can be added in the future for custom model cards
|
|
161
189
|
super().__init_subclass__(
|
|
162
190
|
tags=tags,
|
|
@@ -164,8 +192,10 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=NumpyDocstringInheritanceInitMeta)
|
|
|
164
192
|
repo_url=repo_url,
|
|
165
193
|
library_name=library_name,
|
|
166
194
|
license=license,
|
|
195
|
+
coders=coders,
|
|
167
196
|
**kwargs,
|
|
168
197
|
)
|
|
198
|
+
track_model_init_kwargs(cls)
|
|
169
199
|
|
|
170
200
|
def __init__(
|
|
171
201
|
self,
|
|
@@ -205,6 +235,17 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=NumpyDocstringInheritanceInitMeta)
|
|
|
205
235
|
self._n_times = n_times # type: ignore[assignment]
|
|
206
236
|
self._sfreq = sfreq # type: ignore[assignment]
|
|
207
237
|
|
|
238
|
+
# Back-fill instance attributes from _hub_mixin_config for any
|
|
239
|
+
# params the subclass didn't store on self. Skip EEG params
|
|
240
|
+
# (stored as self._*) and descriptors (properties).
|
|
241
|
+
for key, val in getattr(self, "_hub_mixin_config", {}).items():
|
|
242
|
+
if key in _EEG_PARAMS:
|
|
243
|
+
continue
|
|
244
|
+
if hasattr(getattr(type(self), key, None), "__get__"):
|
|
245
|
+
continue
|
|
246
|
+
if not hasattr(self, key):
|
|
247
|
+
setattr(self, key, val)
|
|
248
|
+
|
|
208
249
|
super().__init__()
|
|
209
250
|
|
|
210
251
|
@property
|
|
@@ -315,6 +356,76 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=NumpyDocstringInheritanceInitMeta)
|
|
|
315
356
|
raise ValueError(msg) from exc
|
|
316
357
|
raise exc
|
|
317
358
|
|
|
359
|
+
def get_config(self) -> dict:
|
|
360
|
+
"""Return a JSON-serializable dict of all ``__init__`` parameters.
|
|
361
|
+
|
|
362
|
+
The returned dictionary can be saved to a JSON file and later
|
|
363
|
+
used with :meth:`from_config` to reconstruct the model (without
|
|
364
|
+
weights). It is also used internally by :meth:`push_to_hub` to
|
|
365
|
+
persist the full model configuration.
|
|
366
|
+
|
|
367
|
+
Returns
|
|
368
|
+
-------
|
|
369
|
+
dict
|
|
370
|
+
All ``__init__`` parameters, JSON-serializable.
|
|
371
|
+
``type[nn.Module]`` parameters (e.g. ``activation``) are
|
|
372
|
+
encoded as importable dotted-path strings.
|
|
373
|
+
|
|
374
|
+
Examples
|
|
375
|
+
--------
|
|
376
|
+
>>> import json
|
|
377
|
+
>>> from braindecode.models import EEGNet
|
|
378
|
+
>>> model = EEGNet(n_chans=22, n_times=1000, n_outputs=4, F1=16)
|
|
379
|
+
>>> config = model.get_config()
|
|
380
|
+
>>> config["F1"]
|
|
381
|
+
16
|
|
382
|
+
>>> # Save to disk
|
|
383
|
+
>>> with open("config.json", "w") as f:
|
|
384
|
+
... json.dump(config, f)
|
|
385
|
+
|
|
386
|
+
.. versionadded:: 1.4
|
|
387
|
+
"""
|
|
388
|
+
return build_model_config(self)
|
|
389
|
+
|
|
390
|
+
@classmethod
|
|
391
|
+
def from_config(cls, config: dict) -> "EEGModuleMixin":
|
|
392
|
+
"""Create a model instance from a configuration dict.
|
|
393
|
+
|
|
394
|
+
This is the inverse of :meth:`get_config`. Weights are **not**
|
|
395
|
+
loaded -- use :meth:`from_pretrained` for that.
|
|
396
|
+
|
|
397
|
+
Parameters
|
|
398
|
+
----------
|
|
399
|
+
config : dict
|
|
400
|
+
Configuration dict as returned by :meth:`get_config`.
|
|
401
|
+
|
|
402
|
+
Returns
|
|
403
|
+
-------
|
|
404
|
+
EEGModuleMixin
|
|
405
|
+
A new model instance.
|
|
406
|
+
|
|
407
|
+
Examples
|
|
408
|
+
--------
|
|
409
|
+
>>> import json
|
|
410
|
+
>>> from braindecode.models import EEGNet
|
|
411
|
+
>>> model = EEGNet(n_chans=22, n_times=1000, n_outputs=4, F1=16)
|
|
412
|
+
>>> config = model.get_config()
|
|
413
|
+
>>> # Reconstruct (without weights)
|
|
414
|
+
>>> model2 = EEGNet.from_config(config)
|
|
415
|
+
>>> model2.F1
|
|
416
|
+
16
|
|
417
|
+
>>> # Or from a JSON file
|
|
418
|
+
>>> with open("config.json") as f:
|
|
419
|
+
... config = json.load(f)
|
|
420
|
+
>>> model3 = EEGNet.from_config(config)
|
|
421
|
+
|
|
422
|
+
.. versionadded:: 1.4
|
|
423
|
+
"""
|
|
424
|
+
config = dict(config) # shallow copy
|
|
425
|
+
config.pop("braindecode_version", None)
|
|
426
|
+
resolve_type_kwargs(cls, config)
|
|
427
|
+
return cls(**config)
|
|
428
|
+
|
|
318
429
|
mapping: Optional[Dict[str, str]] = None
|
|
319
430
|
|
|
320
431
|
def load_state_dict(self, state_dict, *args, **kwargs):
|
|
@@ -419,54 +530,22 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=NumpyDocstringInheritanceInitMeta)
|
|
|
419
530
|
|
|
420
531
|
@staticmethod
|
|
421
532
|
def _serialize_chs_info(chs_info):
|
|
422
|
-
"""
|
|
423
|
-
Serialize MNE channel info to JSON-compatible format.
|
|
424
|
-
|
|
425
|
-
Parameters
|
|
426
|
-
----------
|
|
427
|
-
chs_info : list of dict or None
|
|
428
|
-
Channel information from MNE Info object.
|
|
429
|
-
|
|
430
|
-
Returns
|
|
431
|
-
-------
|
|
432
|
-
list of dict or None
|
|
433
|
-
Serialized channel information that can be saved to JSON.
|
|
434
|
-
"""
|
|
533
|
+
"""Serialize MNE channel info (``info["chs"]``) to JSON-compatible dicts."""
|
|
435
534
|
if chs_info is None:
|
|
436
535
|
return None
|
|
437
|
-
|
|
536
|
+
_INT_FIELDS = ("kind", "coil_type", "unit")
|
|
537
|
+
_FLOAT_FIELDS = ("cal", "range")
|
|
438
538
|
serialized = []
|
|
439
539
|
for ch in chs_info:
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
kind_val if isinstance(kind_val, str) else int(kind_val)
|
|
450
|
-
)
|
|
451
|
-
|
|
452
|
-
# Add numeric fields with safe conversion
|
|
453
|
-
coil_type = ch.get("coil_type")
|
|
454
|
-
if coil_type is not None:
|
|
455
|
-
ch_dict["coil_type"] = int(coil_type)
|
|
456
|
-
|
|
457
|
-
unit = ch.get("unit")
|
|
458
|
-
if unit is not None:
|
|
459
|
-
ch_dict["unit"] = int(unit)
|
|
460
|
-
|
|
461
|
-
cal = ch.get("cal")
|
|
462
|
-
if cal is not None:
|
|
463
|
-
ch_dict["cal"] = float(cal)
|
|
464
|
-
|
|
465
|
-
range_val = ch.get("range")
|
|
466
|
-
if range_val is not None:
|
|
467
|
-
ch_dict["range"] = float(range_val)
|
|
468
|
-
|
|
469
|
-
# Serialize location array if present
|
|
540
|
+
ch_dict = {"ch_name": ch.get("ch_name", "")}
|
|
541
|
+
for key in _INT_FIELDS:
|
|
542
|
+
val = ch.get(key)
|
|
543
|
+
if val is not None:
|
|
544
|
+
ch_dict[key] = val if isinstance(val, str) else int(val)
|
|
545
|
+
for key in _FLOAT_FIELDS:
|
|
546
|
+
val = ch.get(key)
|
|
547
|
+
if val is not None:
|
|
548
|
+
ch_dict[key] = float(val)
|
|
470
549
|
if "loc" in ch and ch["loc"] is not None:
|
|
471
550
|
ch_dict["loc"] = (
|
|
472
551
|
ch["loc"].tolist()
|
|
@@ -474,35 +553,19 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=NumpyDocstringInheritanceInitMeta)
|
|
|
474
553
|
else list(ch["loc"])
|
|
475
554
|
)
|
|
476
555
|
serialized.append(ch_dict)
|
|
477
|
-
|
|
478
556
|
return serialized
|
|
479
557
|
|
|
480
558
|
@staticmethod
|
|
481
559
|
def _deserialize_chs_info(chs_info_dict):
|
|
482
|
-
"""
|
|
483
|
-
Deserialize channel info from JSON-compatible format to MNE-like structure.
|
|
484
|
-
|
|
485
|
-
Parameters
|
|
486
|
-
----------
|
|
487
|
-
chs_info_dict : list of dict or None
|
|
488
|
-
Serialized channel information.
|
|
489
|
-
|
|
490
|
-
Returns
|
|
491
|
-
-------
|
|
492
|
-
list of dict or None
|
|
493
|
-
Deserialized channel information compatible with MNE.
|
|
494
|
-
"""
|
|
560
|
+
"""Deserialize JSON channel dicts back to MNE-compatible format."""
|
|
495
561
|
if chs_info_dict is None:
|
|
496
562
|
return None
|
|
497
|
-
|
|
498
563
|
deserialized = []
|
|
499
564
|
for ch_dict in chs_info_dict:
|
|
500
565
|
ch = ch_dict.copy()
|
|
501
|
-
# Convert location back to numpy array if present
|
|
502
566
|
if "loc" in ch and ch["loc"] is not None:
|
|
503
567
|
ch["loc"] = np.array(ch["loc"])
|
|
504
568
|
deserialized.append(ch)
|
|
505
|
-
|
|
506
569
|
return deserialized
|
|
507
570
|
|
|
508
571
|
def _save_pretrained(self, save_directory):
|
|
@@ -522,16 +585,8 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=NumpyDocstringInheritanceInitMeta)
|
|
|
522
585
|
|
|
523
586
|
save_directory = Path(save_directory)
|
|
524
587
|
|
|
525
|
-
|
|
526
|
-
config =
|
|
527
|
-
"n_outputs": self._n_outputs,
|
|
528
|
-
"n_chans": self._n_chans,
|
|
529
|
-
"n_times": self._n_times,
|
|
530
|
-
"input_window_seconds": self._input_window_seconds,
|
|
531
|
-
"sfreq": self._sfreq,
|
|
532
|
-
"chs_info": self._serialize_chs_info(self._chs_info),
|
|
533
|
-
"braindecode_version": __version__,
|
|
534
|
-
}
|
|
588
|
+
config = build_model_config(self)
|
|
589
|
+
config["braindecode_version"] = __version__
|
|
535
590
|
|
|
536
591
|
# Save to config.json
|
|
537
592
|
config_path = save_directory / "config.json"
|
|
@@ -570,6 +625,7 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=NumpyDocstringInheritanceInitMeta)
|
|
|
570
625
|
**model_kwargs,
|
|
571
626
|
):
|
|
572
627
|
model_kwargs.pop("braindecode_version", None)
|
|
628
|
+
resolve_type_kwargs(cls, model_kwargs)
|
|
573
629
|
return super()._from_pretrained( # type: ignore
|
|
574
630
|
model_id=model_id,
|
|
575
631
|
revision=revision,
|
{braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/cbramod.py
RENAMED
|
@@ -207,11 +207,25 @@ class CBraMod(EEGModuleMixin, nn.Module):
|
|
|
207
207
|
|
|
208
208
|
self._weights_init()
|
|
209
209
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
210
|
+
try:
|
|
211
|
+
n_times = self.n_times
|
|
212
|
+
n_chans = self.n_chans
|
|
213
|
+
except ValueError:
|
|
214
|
+
n_times = None
|
|
215
|
+
n_chans = None
|
|
216
|
+
|
|
217
|
+
if return_encoder_output:
|
|
218
|
+
self.final_layer = nn.Identity()
|
|
219
|
+
elif n_times is not None and n_chans is not None:
|
|
220
|
+
n_patch = n_times // patch_size
|
|
221
|
+
flat_dim = n_chans * n_patch * emb_dim
|
|
222
|
+
self.final_layer = nn.Sequential(
|
|
223
|
+
nn.Flatten(), nn.Linear(flat_dim, self.n_outputs)
|
|
224
|
+
)
|
|
225
|
+
else:
|
|
226
|
+
self.final_layer = nn.Sequential(
|
|
227
|
+
nn.Flatten(), nn.LazyLinear(self.n_outputs)
|
|
228
|
+
)
|
|
215
229
|
|
|
216
230
|
def _weights_init(self):
|
|
217
231
|
for m in self.modules():
|
{braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/config.py
RENAMED
|
@@ -4,13 +4,16 @@ from types import UnionType
|
|
|
4
4
|
from typing import Annotated, Any, Literal, Union, get_args, get_origin
|
|
5
5
|
|
|
6
6
|
import numpy as np
|
|
7
|
-
|
|
7
|
+
import pydantic
|
|
8
8
|
from typing_extensions import TypedDict
|
|
9
9
|
|
|
10
10
|
from braindecode.models.base import EEGModuleMixin
|
|
11
|
-
from braindecode.models.util import
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
from braindecode.models.util import (
|
|
12
|
+
SigArgName,
|
|
13
|
+
_init_models_dict,
|
|
14
|
+
models_dict,
|
|
15
|
+
models_mandatory_parameters,
|
|
16
|
+
)
|
|
14
17
|
|
|
15
18
|
try:
|
|
16
19
|
from numpydantic import NDArray, Shape
|
|
@@ -57,8 +60,12 @@ SIGNAL_ARGS_TYPES = {
|
|
|
57
60
|
}
|
|
58
61
|
|
|
59
62
|
|
|
60
|
-
class BaseBraindecodeModelConfig(pydantic.BaseModel):
|
|
63
|
+
class BaseBraindecodeModelConfig(pydantic.BaseModel):
|
|
64
|
+
"""Base class for braindecode model pydantic configs."""
|
|
65
|
+
|
|
61
66
|
def create_instance(self) -> EEGModuleMixin:
|
|
67
|
+
if self.model_name_ not in models_dict:
|
|
68
|
+
_init_models_dict()
|
|
62
69
|
model_cls = models_dict[self.model_name_]
|
|
63
70
|
kwargs = self.model_dump(mode="python", exclude={"model_name_"})
|
|
64
71
|
if kwargs.get("n_chans") is not None and kwargs.get("chs_info") is not None:
|
|
@@ -90,13 +97,6 @@ def make_model_config(
|
|
|
90
97
|
type
|
|
91
98
|
A pydantic BaseModel subclass representing the model config.
|
|
92
99
|
"""
|
|
93
|
-
if not pydantic:
|
|
94
|
-
raise ImportError(
|
|
95
|
-
"pydantic is required to use make_model_config. "
|
|
96
|
-
"Please install braindecode[typing]."
|
|
97
|
-
)
|
|
98
|
-
|
|
99
|
-
# ironically, we need to ignore the type here to have the soft dependency.
|
|
100
100
|
|
|
101
101
|
@pydantic.model_validator(mode="before")
|
|
102
102
|
def validate_signal_params(cls, data: Any):
|
|
@@ -207,23 +207,23 @@ def make_model_config(
|
|
|
207
207
|
# and define __all__ based on generated classes
|
|
208
208
|
__all__ = ["make_model_config"]
|
|
209
209
|
|
|
210
|
-
if not
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
210
|
+
if not models_dict:
|
|
211
|
+
_init_models_dict()
|
|
212
|
+
|
|
213
|
+
models_configs: list[type[BaseBraindecodeModelConfig]] = []
|
|
214
|
+
for model_name, req, _ in models_mandatory_parameters:
|
|
215
|
+
model_cls = models_dict[model_name]
|
|
216
|
+
model_cfg = make_model_config(model_cls, req)
|
|
217
|
+
globals()[model_cfg.__name__] = model_cfg
|
|
218
|
+
__all__.append(model_cfg.__name__)
|
|
219
|
+
models_configs.append(model_cfg)
|
|
220
|
+
|
|
221
|
+
BraindecodeModelConfig = Annotated[ # type: ignore[valid-type]
|
|
222
|
+
Union[tuple(models_configs)],
|
|
223
|
+
pydantic.Field(
|
|
224
|
+
discriminator="model_name_", description="Braindecode model configuration"
|
|
225
|
+
),
|
|
226
|
+
]
|
|
227
227
|
|
|
228
228
|
# # Example usage:
|
|
229
229
|
#
|
{braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/eegsym.py
RENAMED
|
@@ -112,7 +112,7 @@ class EEGSym(EEGModuleMixin, nn.Module):
|
|
|
112
112
|
corresponding to different frequency characteristics.
|
|
113
113
|
|
|
114
114
|
Notes
|
|
115
|
-
|
|
115
|
+
-----
|
|
116
116
|
* EEGSym achieved competitive accuracies across five large MI datasets [eegsym2022]_.
|
|
117
117
|
* The model maintained high accuracy using a reduced set of electrodes (8 or 16 channels)
|
|
118
118
|
[eegsym2022]_.
|
{braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/luna.py
RENAMED
|
@@ -7,6 +7,7 @@ Retrieved from https://openreview.net/forum?id=uazfjnFL0G
|
|
|
7
7
|
|
|
8
8
|
Original Authors: Berkay Döner, Thorir Mar Ingolfsson
|
|
9
9
|
Braindecode Adaptation: Bruno Aristimunha
|
|
10
|
+
Contributions: Sarthak Tayal <sarthaktayal2@gmail.com>
|
|
10
11
|
|
|
11
12
|
the LICENSE Of this file is APACHE-2.0.
|
|
12
13
|
"""
|
|
@@ -82,11 +83,8 @@ class LUNA(EEGModuleMixin, nn.Module):
|
|
|
82
83
|
|
|
83
84
|
# Load pre-trained encoder weights
|
|
84
85
|
state_dict = load_file(model_path)
|
|
85
|
-
#
|
|
86
|
-
|
|
87
|
-
mapping["cross_attn.temparature"] = "cross_attn.temperature"
|
|
88
|
-
mapped_state_dict = {mapping.get(k, k): v for k, v in state_dict.items()}
|
|
89
|
-
model.load_state_dict(mapped_state_dict, strict=False)
|
|
86
|
+
# load_state_dict applies model.mapping automatically
|
|
87
|
+
model.load_state_dict(state_dict, strict=False)
|
|
90
88
|
|
|
91
89
|
To push your own trained model to the Hub:
|
|
92
90
|
|
|
@@ -170,6 +168,7 @@ class LUNA(EEGModuleMixin, nn.Module):
|
|
|
170
168
|
"channel_location_embedder.0.fc2.bias": "channel_location_embedder.fc2.bias",
|
|
171
169
|
"channel_location_embedder.0.norm.weight": "channel_location_embedder.norm.weight",
|
|
172
170
|
"channel_location_embedder.0.norm.bias": "channel_location_embedder.norm.bias",
|
|
171
|
+
"cross_attn.temparature": "cross_attn.temperature", # typo in pretrained weights
|
|
173
172
|
}
|
|
174
173
|
|
|
175
174
|
# Model parameters
|
|
@@ -315,8 +314,10 @@ class LUNA(EEGModuleMixin, nn.Module):
|
|
|
315
314
|
channel_locations_emb = self.channel_location_embedder(channel_locations)
|
|
316
315
|
|
|
317
316
|
x_tokenized = rearrange(x_masked, "B (C t) D -> (B t) C D", C=num_channels)
|
|
318
|
-
channel_locations_emb =
|
|
319
|
-
|
|
317
|
+
channel_locations_emb = (
|
|
318
|
+
channel_locations_emb.repeat_interleave( # was repeat(), wrong dim ordering
|
|
319
|
+
num_patches_per_channel, dim=0
|
|
320
|
+
)
|
|
320
321
|
)
|
|
321
322
|
x_tokenized = x_tokenized + channel_locations_emb
|
|
322
323
|
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
from __future__ import annotations
|
|
5
5
|
|
|
6
6
|
import math
|
|
7
|
+
import warnings
|
|
7
8
|
from typing import Optional, Tuple
|
|
8
9
|
|
|
9
10
|
import torch
|
|
@@ -496,9 +497,10 @@ class _TransformerEncoderLayer(nn.Module):
|
|
|
496
497
|
|
|
497
498
|
if dim_feedforward is None:
|
|
498
499
|
dim_feedforward = 4 * embed_dim
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
"
|
|
500
|
+
warnings.warn(
|
|
501
|
+
"dim_feedforward is set to 4*embed_dim, the default in "
|
|
502
|
+
"Vaswani et al. (Attention is all you need)",
|
|
503
|
+
stacklevel=2,
|
|
502
504
|
)
|
|
503
505
|
|
|
504
506
|
self.layer_norm_att = _LayerNorm(embed_dim, bias=bias)
|
{braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev182544824}/braindecode/models/reve.py
RENAMED
|
@@ -16,7 +16,16 @@ import torch
|
|
|
16
16
|
import torch.nn.functional as F
|
|
17
17
|
from einops import rearrange
|
|
18
18
|
from torch import nn
|
|
19
|
-
|
|
19
|
+
|
|
20
|
+
# Safe import for older PyTorch versions (Support for Intel-based Macs)
|
|
21
|
+
try:
|
|
22
|
+
from torch.nn.attention import SDPBackend, sdpa_kernel
|
|
23
|
+
|
|
24
|
+
HAS_SDPA = True
|
|
25
|
+
except ImportError:
|
|
26
|
+
HAS_SDPA = False
|
|
27
|
+
SDPBackend = None
|
|
28
|
+
sdpa_kernel = None
|
|
20
29
|
|
|
21
30
|
from braindecode.models.base import EEGModuleMixin
|
|
22
31
|
|
|
@@ -530,11 +539,22 @@ class FeedForward(nn.Module):
|
|
|
530
539
|
|
|
531
540
|
|
|
532
541
|
class ClassicalAttention(nn.Module):
|
|
533
|
-
def __init__(self, heads: int, use_sdpa: bool =
|
|
542
|
+
def __init__(self, heads: int, use_sdpa: bool | None = None):
|
|
534
543
|
super().__init__()
|
|
535
|
-
self.use_sdpa = use_sdpa
|
|
536
544
|
self.heads = heads
|
|
537
545
|
|
|
546
|
+
if use_sdpa is None:
|
|
547
|
+
self.use_sdpa = HAS_SDPA
|
|
548
|
+
elif use_sdpa is True and not HAS_SDPA:
|
|
549
|
+
logger.warning(
|
|
550
|
+
"SDPA (Scaled Dot Product Attention) was requested, but it is not "
|
|
551
|
+
"available in your current PyTorch version. Falling back to naive "
|
|
552
|
+
"implementation. Please upgrade to PyTorch >= 2.2 for SDPA support."
|
|
553
|
+
)
|
|
554
|
+
self.use_sdpa = False
|
|
555
|
+
else:
|
|
556
|
+
self.use_sdpa = use_sdpa
|
|
557
|
+
|
|
538
558
|
def forward(self, qkv: torch.Tensor) -> torch.Tensor:
|
|
539
559
|
# Split concatenated QKV into separate tensors
|
|
540
560
|
# qkv shape: (batch, seq_len, 3 * heads * head_dim)
|