Braindecode 1.3.2.dev179983996__tar.gz → 1.3.2.dev181313884__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.dev181313884}/PKG-INFO +3 -3
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datasets/bids/hub.py +7 -2
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/__init__.py +2 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/base.py +244 -93
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/bendr.py +17 -6
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/biot.py +23 -5
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/cbramod.py +28 -6
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/config.py +29 -29
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/eegpt.py +15 -2
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/eegsym.py +1 -1
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/labram.py +15 -1
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/luna.py +8 -7
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/patchedtransformer.py +5 -3
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/reve.py +59 -23
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/shallow_fbcsp.py +16 -8
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/signal_jepa.py +52 -13
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/sstdpn.py +1 -1
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/util.py +133 -2
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/modules/__init__.py +2 -1
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/modules/activation.py +20 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/preprocessing/mne_preprocess.py +2 -1
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/util.py +34 -4
- braindecode-1.3.2.dev181313884/braindecode/version.py +1 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884/braindecode.egg-info}/PKG-INFO +3 -3
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode.egg-info/requires.txt +2 -2
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/docs/api.rst +10 -9
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/docs/conf.py +18 -13
- braindecode-1.3.2.dev181313884/docs/models/categorization/spd.rst +103 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/docs/models/models_categorization.rst +58 -57
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/docs/whats_new.rst +66 -6
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/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.dev181313884}/LICENSE.txt +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/MANIFEST.in +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/NOTICE.txt +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/README.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/__init__.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/augmentation/__init__.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/augmentation/base.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/augmentation/functional.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/augmentation/transforms.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/classifier.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datasets/__init__.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datasets/base.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datasets/bbci.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datasets/bcicomp.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datasets/bids/__init__.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datasets/bids/datasets.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datasets/bids/format.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datasets/bids/hub_format.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datasets/bids/hub_io.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datasets/bids/hub_validation.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datasets/bids/iterable.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datasets/chb_mit.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datasets/mne.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datasets/moabb.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datasets/nmt.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datasets/registry.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datasets/siena.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datasets/sleep_physio_challe_18.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datasets/sleep_physionet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datasets/tuh.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datasets/utils.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datasets/xy.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datautil/__init__.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datautil/channel_utils.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datautil/hub_formats.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datautil/serialization.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/datautil/util.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/eegneuralnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/functional/__init__.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/functional/functions.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/functional/initialization.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/atcnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/attentionbasenet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/attn_sleep.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/brainmodule.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/contrawr.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/ctnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/deep4.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/deepsleepnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/dgcnn.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/eegconformer.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/eeginception_erp.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/eeginception_mi.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/eegitnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/eegminer.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/eegnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/eegnex.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/eegsimpleconv.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/eegtcnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/fbcnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/fblightconvnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/fbmsnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/hybrid.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/ifnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/medformer.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/msvtnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/sccnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/sinc_shallow.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/sleep_stager_blanco_2020.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/sleep_stager_chambon_2018.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/sparcnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/summary.csv +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/syncnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/tcn.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/tidnet.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/tsinception.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/usleep.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/modules/attention.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/modules/blocks.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/modules/convolution.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/modules/filter.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/modules/layers.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/modules/linear.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/modules/parametrization.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/modules/stats.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/modules/util.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/modules/wrapper.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/preprocessing/__init__.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/preprocessing/eegprep_preprocess.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/preprocessing/preprocess.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/preprocessing/util.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/preprocessing/windowers.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/regressor.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/samplers/__init__.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/samplers/base.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/samplers/ssl.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/training/__init__.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/training/callbacks.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/training/losses.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/training/scoring.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/visualization/__init__.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/visualization/confusion_matrices.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/visualization/gradients.py +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode.egg-info/SOURCES.txt +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode.egg-info/dependency_links.txt +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode.egg-info/top_level.txt +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/docs/Makefile +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/docs/_templates/autosummary/class.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/docs/_templates/autosummary/class_in_subdir.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/docs/_templates/autosummary/function.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/docs/_templates/autosummary/function_in_subdir.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/docs/cite.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/docs/help.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/docs/index.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/docs/install/install.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/docs/install/install_pip.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/docs/install/install_source.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/docs/models/categorization/attention.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/docs/models/categorization/channel.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/docs/models/categorization/convolution.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/docs/models/categorization/filterbank.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/docs/models/categorization/gnn.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/docs/models/categorization/interpretable.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/docs/models/categorization/lbm.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/docs/models/categorization/recurrent.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/docs/models/models.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/docs/models/models_table.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/docs/models/models_visualization.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/docs/sg_execution_times.rst +0 -0
- {braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/setup.cfg +0 -0
{braindecode-1.3.2.dev179983996/braindecode.egg-info → braindecode-1.3.2.dev181313884}/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.dev181313884
|
|
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.dev181313884}/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.dev181313884}/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.dev181313884}/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(
|
|
@@ -52,7 +59,25 @@ def deprecated_args(obj, *old_new_args):
|
|
|
52
59
|
return out_args
|
|
53
60
|
|
|
54
61
|
|
|
55
|
-
class
|
|
62
|
+
class _BraindecodeDocstringMeta(NumpyDocstringInheritanceInitMeta):
|
|
63
|
+
"""Defer ``__init__`` wrapping until after docstring inheritance.
|
|
64
|
+
|
|
65
|
+
``NumpyDocstringInheritanceInitMeta`` uses ``inspect.unwrap()``
|
|
66
|
+
internally, which bypasses ``@wraps`` wrappers. By wrapping
|
|
67
|
+
``__init__`` *after* docstring processing, the metaclass sees the
|
|
68
|
+
unwrapped function and correctly inherits ``cls.__doc__``.
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
def __init__(cls, class_name, class_bases, class_dict):
|
|
72
|
+
super().__init__(class_name, class_bases, class_dict)
|
|
73
|
+
# Only wrap subclass __init__s, not EEGModuleMixin itself.
|
|
74
|
+
# Wrapping the mixin would cause super().__init__() calls to
|
|
75
|
+
# overwrite _braindecode_init_kwargs captured by the subclass.
|
|
76
|
+
if any(isinstance(b, _BraindecodeDocstringMeta) for b in class_bases):
|
|
77
|
+
track_model_init_kwargs(cls)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class EEGModuleMixin(_BaseHubMixin, metaclass=_BraindecodeDocstringMeta):
|
|
56
81
|
"""
|
|
57
82
|
Mixin class for all EEG models in braindecode.
|
|
58
83
|
|
|
@@ -86,59 +111,66 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=NumpyDocstringInheritanceInitMeta)
|
|
|
86
111
|
-----
|
|
87
112
|
If some input signal-related parameters are not specified,
|
|
88
113
|
there will be an attempt to infer them from the other parameters.
|
|
114
|
+
"""
|
|
89
115
|
|
|
116
|
+
#: Template for model-specific Hub integration notes appended by
|
|
117
|
+
#: ``__init_subclass__``. ``{name}`` is replaced with the concrete
|
|
118
|
+
#: model class name.
|
|
119
|
+
_HUB_NOTES_TEMPLATE = """
|
|
90
120
|
.. rubric:: Hugging Face Hub integration
|
|
91
121
|
|
|
92
122
|
When the optional ``huggingface_hub`` package is installed, all models
|
|
93
123
|
automatically gain the ability to be pushed to and loaded from the
|
|
94
124
|
Hugging Face Hub. Install with::
|
|
95
125
|
|
|
96
|
-
pip install braindecode[
|
|
126
|
+
pip install braindecode[hub]
|
|
97
127
|
|
|
98
128
|
**Pushing a model to the Hub:**
|
|
99
129
|
|
|
100
|
-
.. code-block::
|
|
130
|
+
.. code-block::
|
|
101
131
|
|
|
102
|
-
from braindecode.models import
|
|
132
|
+
from braindecode.models import {name}
|
|
103
133
|
|
|
104
134
|
# Train your model
|
|
105
|
-
model =
|
|
135
|
+
model = {name}(n_chans=22, n_outputs=4, n_times=1000)
|
|
106
136
|
# ... training code ...
|
|
107
137
|
|
|
108
138
|
# Push to the Hub
|
|
109
139
|
model.push_to_hub(
|
|
110
|
-
repo_id="username/my-
|
|
140
|
+
repo_id="username/my-{name_lower}-model",
|
|
141
|
+
commit_message="Initial model upload",
|
|
111
142
|
)
|
|
112
143
|
|
|
113
144
|
**Loading a model from the Hub:**
|
|
114
145
|
|
|
115
|
-
.. code-block::
|
|
146
|
+
.. code-block::
|
|
116
147
|
|
|
117
|
-
from braindecode.models import
|
|
148
|
+
from braindecode.models import {name}
|
|
118
149
|
|
|
119
150
|
# Load pretrained model
|
|
120
|
-
model =
|
|
151
|
+
model = {name}.from_pretrained("username/my-{name_lower}-model")
|
|
121
152
|
|
|
122
153
|
The integration automatically handles EEG-specific parameters (n_chans,
|
|
123
154
|
n_times, sfreq, chs_info, etc.) by saving them in a config file alongside
|
|
124
155
|
the model weights. This ensures that loaded models are correctly configured
|
|
125
156
|
for their original data specifications.
|
|
126
157
|
|
|
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.
|
|
158
|
+
All model parameters (both EEG-specific and model-specific such as
|
|
159
|
+
dropout rates, activation functions, number of filters) are automatically
|
|
160
|
+
saved to the Hub and restored when loading.
|
|
139
161
|
"""
|
|
140
162
|
|
|
141
163
|
def __init_subclass__(cls, **kwargs):
|
|
164
|
+
# Append model-specific Hub integration notes to the docstring.
|
|
165
|
+
# This runs before the metaclass __init__, so the Hub notes will
|
|
166
|
+
# be included in the docstring that the metaclass processes.
|
|
167
|
+
if cls.__doc__ is not None:
|
|
168
|
+
hub_notes = cls._HUB_NOTES_TEMPLATE.format(
|
|
169
|
+
name=cls.__name__,
|
|
170
|
+
name_lower=cls.__name__.lower(),
|
|
171
|
+
)
|
|
172
|
+
cls.__doc__ = cls.__doc__.rstrip() + "\n" + hub_notes
|
|
173
|
+
|
|
142
174
|
if not HAS_HF_HUB:
|
|
143
175
|
super().__init_subclass__(**kwargs)
|
|
144
176
|
return
|
|
@@ -157,6 +189,19 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=NumpyDocstringInheritanceInitMeta)
|
|
|
157
189
|
repo_url = kwargs.pop("repo_url", "https://braindecode.org")
|
|
158
190
|
library_name = kwargs.pop("library_name", "braindecode")
|
|
159
191
|
license = kwargs.pop("license", "bsd-3-clause")
|
|
192
|
+
|
|
193
|
+
# Register a coder so that type[nn.Module] parameters
|
|
194
|
+
# (e.g. activation=nn.ELU) are serialized as importable
|
|
195
|
+
# strings in config.json and decoded back on load.
|
|
196
|
+
coders = kwargs.pop("coders", None) or {}
|
|
197
|
+
coders.setdefault(
|
|
198
|
+
type,
|
|
199
|
+
(
|
|
200
|
+
lambda t: f"{t.__module__}.{t.__qualname__}",
|
|
201
|
+
lambda data: _IMPORT_ADAPTER.validate_python(data),
|
|
202
|
+
),
|
|
203
|
+
)
|
|
204
|
+
|
|
160
205
|
# TODO: model_card_template can be added in the future for custom model cards
|
|
161
206
|
super().__init_subclass__(
|
|
162
207
|
tags=tags,
|
|
@@ -164,6 +209,7 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=NumpyDocstringInheritanceInitMeta)
|
|
|
164
209
|
repo_url=repo_url,
|
|
165
210
|
library_name=library_name,
|
|
166
211
|
license=license,
|
|
212
|
+
coders=coders,
|
|
167
213
|
**kwargs,
|
|
168
214
|
)
|
|
169
215
|
|
|
@@ -205,6 +251,17 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=NumpyDocstringInheritanceInitMeta)
|
|
|
205
251
|
self._n_times = n_times # type: ignore[assignment]
|
|
206
252
|
self._sfreq = sfreq # type: ignore[assignment]
|
|
207
253
|
|
|
254
|
+
# Back-fill instance attributes from _hub_mixin_config for any
|
|
255
|
+
# params the subclass didn't store on self. Skip EEG params
|
|
256
|
+
# (stored as self._*) and descriptors (properties).
|
|
257
|
+
for key, val in getattr(self, "_hub_mixin_config", {}).items():
|
|
258
|
+
if key in _EEG_PARAMS:
|
|
259
|
+
continue
|
|
260
|
+
if hasattr(getattr(type(self), key, None), "__get__"):
|
|
261
|
+
continue
|
|
262
|
+
if not hasattr(self, key):
|
|
263
|
+
setattr(self, key, val)
|
|
264
|
+
|
|
208
265
|
super().__init__()
|
|
209
266
|
|
|
210
267
|
@property
|
|
@@ -315,6 +372,104 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=NumpyDocstringInheritanceInitMeta)
|
|
|
315
372
|
raise ValueError(msg) from exc
|
|
316
373
|
raise exc
|
|
317
374
|
|
|
375
|
+
def get_config(self) -> dict:
|
|
376
|
+
"""Return a JSON-serializable dict of all ``__init__`` parameters.
|
|
377
|
+
|
|
378
|
+
The returned dictionary can be saved to a JSON file and later
|
|
379
|
+
used with :meth:`from_config` to reconstruct the model (without
|
|
380
|
+
weights). It is also used internally by :meth:`push_to_hub` to
|
|
381
|
+
persist the full model configuration.
|
|
382
|
+
|
|
383
|
+
Returns
|
|
384
|
+
-------
|
|
385
|
+
dict
|
|
386
|
+
All ``__init__`` parameters, JSON-serializable.
|
|
387
|
+
``type[nn.Module]`` parameters (e.g. ``activation``) are
|
|
388
|
+
encoded as importable dotted-path strings.
|
|
389
|
+
|
|
390
|
+
Examples
|
|
391
|
+
--------
|
|
392
|
+
>>> import json
|
|
393
|
+
>>> from braindecode.models import EEGNet
|
|
394
|
+
>>> model = EEGNet(n_chans=22, n_times=1000, n_outputs=4, F1=16)
|
|
395
|
+
>>> config = model.get_config()
|
|
396
|
+
>>> config["F1"]
|
|
397
|
+
16
|
|
398
|
+
>>> # Save to disk
|
|
399
|
+
>>> with open("config.json", "w") as f:
|
|
400
|
+
... json.dump(config, f)
|
|
401
|
+
|
|
402
|
+
.. versionadded:: 1.4
|
|
403
|
+
"""
|
|
404
|
+
return build_model_config(self)
|
|
405
|
+
|
|
406
|
+
@classmethod
|
|
407
|
+
def from_config(cls, config: dict) -> "EEGModuleMixin":
|
|
408
|
+
"""Create a model instance from a configuration dict.
|
|
409
|
+
|
|
410
|
+
This is the inverse of :meth:`get_config`. Weights are **not**
|
|
411
|
+
loaded -- use :meth:`from_pretrained` for that.
|
|
412
|
+
|
|
413
|
+
Parameters
|
|
414
|
+
----------
|
|
415
|
+
config : dict
|
|
416
|
+
Configuration dict as returned by :meth:`get_config`.
|
|
417
|
+
|
|
418
|
+
Returns
|
|
419
|
+
-------
|
|
420
|
+
EEGModuleMixin
|
|
421
|
+
A new model instance.
|
|
422
|
+
|
|
423
|
+
Examples
|
|
424
|
+
--------
|
|
425
|
+
>>> import json
|
|
426
|
+
>>> from braindecode.models import EEGNet
|
|
427
|
+
>>> model = EEGNet(n_chans=22, n_times=1000, n_outputs=4, F1=16)
|
|
428
|
+
>>> config = model.get_config()
|
|
429
|
+
>>> # Reconstruct (without weights)
|
|
430
|
+
>>> model2 = EEGNet.from_config(config)
|
|
431
|
+
>>> model2.F1
|
|
432
|
+
16
|
|
433
|
+
>>> # Or from a JSON file
|
|
434
|
+
>>> with open("config.json") as f:
|
|
435
|
+
... config = json.load(f)
|
|
436
|
+
>>> model3 = EEGNet.from_config(config)
|
|
437
|
+
|
|
438
|
+
.. versionadded:: 1.4
|
|
439
|
+
"""
|
|
440
|
+
config = dict(config) # shallow copy
|
|
441
|
+
config.pop("braindecode_version", None)
|
|
442
|
+
resolve_type_kwargs(cls, config)
|
|
443
|
+
return cls(**config)
|
|
444
|
+
|
|
445
|
+
def reset_head(self, n_outputs):
|
|
446
|
+
"""Replace the classification head for a new number of outputs.
|
|
447
|
+
|
|
448
|
+
This is called automatically by :meth:`from_pretrained` when the
|
|
449
|
+
user passes an ``n_outputs`` that differs from the saved config.
|
|
450
|
+
Override in subclasses that need a model-specific head structure.
|
|
451
|
+
|
|
452
|
+
Parameters
|
|
453
|
+
----------
|
|
454
|
+
n_outputs : int
|
|
455
|
+
New number of output classes.
|
|
456
|
+
|
|
457
|
+
Examples
|
|
458
|
+
--------
|
|
459
|
+
>>> from braindecode.models import BENDR
|
|
460
|
+
>>> model = BENDR(n_chans=22, n_times=1000, n_outputs=4)
|
|
461
|
+
>>> model.reset_head(10)
|
|
462
|
+
>>> model.n_outputs
|
|
463
|
+
10
|
|
464
|
+
|
|
465
|
+
.. versionadded:: 1.4
|
|
466
|
+
"""
|
|
467
|
+
raise NotImplementedError(
|
|
468
|
+
f"{type(self).__name__} does not implement reset_head(). "
|
|
469
|
+
"Override this method to support changing n_outputs after "
|
|
470
|
+
"loading pretrained weights."
|
|
471
|
+
)
|
|
472
|
+
|
|
318
473
|
mapping: Optional[Dict[str, str]] = None
|
|
319
474
|
|
|
320
475
|
def load_state_dict(self, state_dict, *args, **kwargs):
|
|
@@ -419,54 +574,22 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=NumpyDocstringInheritanceInitMeta)
|
|
|
419
574
|
|
|
420
575
|
@staticmethod
|
|
421
576
|
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
|
-
"""
|
|
577
|
+
"""Serialize MNE channel info (``info["chs"]``) to JSON-compatible dicts."""
|
|
435
578
|
if chs_info is None:
|
|
436
579
|
return None
|
|
437
|
-
|
|
580
|
+
_INT_FIELDS = ("kind", "coil_type", "unit")
|
|
581
|
+
_FLOAT_FIELDS = ("cal", "range")
|
|
438
582
|
serialized = []
|
|
439
583
|
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
|
|
584
|
+
ch_dict = {"ch_name": ch.get("ch_name", "")}
|
|
585
|
+
for key in _INT_FIELDS:
|
|
586
|
+
val = ch.get(key)
|
|
587
|
+
if val is not None:
|
|
588
|
+
ch_dict[key] = val if isinstance(val, str) else int(val)
|
|
589
|
+
for key in _FLOAT_FIELDS:
|
|
590
|
+
val = ch.get(key)
|
|
591
|
+
if val is not None:
|
|
592
|
+
ch_dict[key] = float(val)
|
|
470
593
|
if "loc" in ch and ch["loc"] is not None:
|
|
471
594
|
ch_dict["loc"] = (
|
|
472
595
|
ch["loc"].tolist()
|
|
@@ -474,35 +597,19 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=NumpyDocstringInheritanceInitMeta)
|
|
|
474
597
|
else list(ch["loc"])
|
|
475
598
|
)
|
|
476
599
|
serialized.append(ch_dict)
|
|
477
|
-
|
|
478
600
|
return serialized
|
|
479
601
|
|
|
480
602
|
@staticmethod
|
|
481
603
|
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
|
-
"""
|
|
604
|
+
"""Deserialize JSON channel dicts back to MNE-compatible format."""
|
|
495
605
|
if chs_info_dict is None:
|
|
496
606
|
return None
|
|
497
|
-
|
|
498
607
|
deserialized = []
|
|
499
608
|
for ch_dict in chs_info_dict:
|
|
500
609
|
ch = ch_dict.copy()
|
|
501
|
-
# Convert location back to numpy array if present
|
|
502
610
|
if "loc" in ch and ch["loc"] is not None:
|
|
503
611
|
ch["loc"] = np.array(ch["loc"])
|
|
504
612
|
deserialized.append(ch)
|
|
505
|
-
|
|
506
613
|
return deserialized
|
|
507
614
|
|
|
508
615
|
def _save_pretrained(self, save_directory):
|
|
@@ -522,16 +629,8 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=NumpyDocstringInheritanceInitMeta)
|
|
|
522
629
|
|
|
523
630
|
save_directory = Path(save_directory)
|
|
524
631
|
|
|
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
|
-
}
|
|
632
|
+
config = build_model_config(self)
|
|
633
|
+
config["braindecode_version"] = __version__
|
|
535
634
|
|
|
536
635
|
# Save to config.json
|
|
537
636
|
config_path = save_directory / "config.json"
|
|
@@ -570,7 +669,42 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=NumpyDocstringInheritanceInitMeta)
|
|
|
570
669
|
**model_kwargs,
|
|
571
670
|
):
|
|
572
671
|
model_kwargs.pop("braindecode_version", None)
|
|
573
|
-
|
|
672
|
+
resolve_type_kwargs(cls, model_kwargs)
|
|
673
|
+
|
|
674
|
+
# Read saved n_outputs from config.json to detect when the
|
|
675
|
+
# user wants a different number of outputs. Works for both
|
|
676
|
+
# local directories and Hub repo IDs.
|
|
677
|
+
saved_n_outputs = None
|
|
678
|
+
try:
|
|
679
|
+
if Path(model_id).is_dir():
|
|
680
|
+
config_file = Path(model_id) / "config.json"
|
|
681
|
+
else:
|
|
682
|
+
config_file = huggingface_hub.hf_hub_download(
|
|
683
|
+
repo_id=model_id,
|
|
684
|
+
filename="config.json",
|
|
685
|
+
revision=revision,
|
|
686
|
+
cache_dir=cache_dir,
|
|
687
|
+
force_download=force_download,
|
|
688
|
+
token=token,
|
|
689
|
+
local_files_only=local_files_only,
|
|
690
|
+
)
|
|
691
|
+
with open(config_file, "r") as f:
|
|
692
|
+
saved_n_outputs = json.load(f).get("n_outputs")
|
|
693
|
+
except (OSError, json.JSONDecodeError, KeyError):
|
|
694
|
+
pass # config unavailable; skip reset_head logic
|
|
695
|
+
|
|
696
|
+
requested_n_outputs = model_kwargs.get("n_outputs")
|
|
697
|
+
|
|
698
|
+
# If the user requests different n_outputs, load with the
|
|
699
|
+
# saved value first (so weights match), then swap the head.
|
|
700
|
+
if (
|
|
701
|
+
saved_n_outputs is not None
|
|
702
|
+
and requested_n_outputs is not None
|
|
703
|
+
and requested_n_outputs != saved_n_outputs
|
|
704
|
+
):
|
|
705
|
+
model_kwargs["n_outputs"] = saved_n_outputs
|
|
706
|
+
|
|
707
|
+
model = super()._from_pretrained( # type: ignore
|
|
574
708
|
model_id=model_id,
|
|
575
709
|
revision=revision,
|
|
576
710
|
cache_dir=cache_dir,
|
|
@@ -581,3 +715,20 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=NumpyDocstringInheritanceInitMeta)
|
|
|
581
715
|
strict=strict,
|
|
582
716
|
**model_kwargs,
|
|
583
717
|
)
|
|
718
|
+
|
|
719
|
+
if (
|
|
720
|
+
saved_n_outputs is not None
|
|
721
|
+
and requested_n_outputs is not None
|
|
722
|
+
and requested_n_outputs != saved_n_outputs
|
|
723
|
+
):
|
|
724
|
+
try:
|
|
725
|
+
model.reset_head(requested_n_outputs)
|
|
726
|
+
except NotImplementedError:
|
|
727
|
+
raise ValueError(
|
|
728
|
+
f"{type(model).__name__} does not support changing "
|
|
729
|
+
f"n_outputs after loading. Saved model has "
|
|
730
|
+
f"n_outputs={saved_n_outputs}, but "
|
|
731
|
+
f"n_outputs={requested_n_outputs} was requested."
|
|
732
|
+
) from None
|
|
733
|
+
|
|
734
|
+
return model
|
{braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/bendr.py
RENAMED
|
@@ -291,15 +291,23 @@ class BENDR(EEGModuleMixin, nn.Module):
|
|
|
291
291
|
else:
|
|
292
292
|
in_features = encoder_h
|
|
293
293
|
|
|
294
|
+
self._head_in_features = in_features
|
|
294
295
|
self.final_layer = None
|
|
295
296
|
if self.include_final_layer:
|
|
296
|
-
|
|
297
|
-
linear = nn.Linear(in_features=in_features, out_features=self.n_outputs)
|
|
298
|
-
self.final_layer = nn.utils.parametrizations.weight_norm(
|
|
299
|
-
linear, name="weight", dim=1
|
|
300
|
-
)
|
|
297
|
+
self._build_head(self.n_outputs)
|
|
301
298
|
|
|
302
|
-
def
|
|
299
|
+
def _build_head(self, n_outputs):
|
|
300
|
+
linear = nn.Linear(in_features=self._head_in_features, out_features=n_outputs)
|
|
301
|
+
self.final_layer = nn.utils.parametrizations.weight_norm(
|
|
302
|
+
linear, name="weight", dim=1
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
def reset_head(self, n_outputs):
|
|
306
|
+
self._n_outputs = n_outputs
|
|
307
|
+
self.include_final_layer = True
|
|
308
|
+
self._build_head(n_outputs)
|
|
309
|
+
|
|
310
|
+
def forward(self, x, return_features=False):
|
|
303
311
|
if self.channel_projection is not None:
|
|
304
312
|
x = self.channel_projection(x)
|
|
305
313
|
encoded = self.encoder(x)
|
|
@@ -328,6 +336,9 @@ class BENDR(EEGModuleMixin, nn.Module):
|
|
|
328
336
|
feature = context[:, :, 0]
|
|
329
337
|
# feature: [batch_size, encoder_h]
|
|
330
338
|
|
|
339
|
+
if return_features:
|
|
340
|
+
return {"features": feature, "cls_token": None}
|
|
341
|
+
|
|
331
342
|
if self.final_layer is not None:
|
|
332
343
|
feature = self.final_layer(feature)
|
|
333
344
|
# feature: [batch_size, n_outputs]
|
{braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/biot.py
RENAMED
|
@@ -183,13 +183,22 @@ class BIOT(EEGModuleMixin, nn.Module):
|
|
|
183
183
|
attn_layer_dropout=att_layer_drop_prob,
|
|
184
184
|
)
|
|
185
185
|
|
|
186
|
+
self._head_activation = activation
|
|
186
187
|
self.final_layer = _ClassificationHead(
|
|
187
188
|
emb_size=self.embed_dim,
|
|
188
189
|
n_outputs=self.n_outputs,
|
|
189
190
|
activation=activation,
|
|
190
191
|
)
|
|
191
192
|
|
|
192
|
-
def
|
|
193
|
+
def reset_head(self, n_outputs):
|
|
194
|
+
self._n_outputs = n_outputs
|
|
195
|
+
self.final_layer = _ClassificationHead(
|
|
196
|
+
emb_size=self.embed_dim,
|
|
197
|
+
n_outputs=n_outputs,
|
|
198
|
+
activation=self._head_activation,
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
def forward(self, x, return_features=False):
|
|
193
202
|
"""
|
|
194
203
|
Pass the input through the BIOT encoder, and then through the
|
|
195
204
|
classification head.
|
|
@@ -198,15 +207,24 @@ class BIOT(EEGModuleMixin, nn.Module):
|
|
|
198
207
|
----------
|
|
199
208
|
x: Tensor
|
|
200
209
|
(batch_size, n_channels, n_times)
|
|
210
|
+
return_features : bool
|
|
211
|
+
If True, return a dict with ``"features"`` and ``"cls_token"``
|
|
212
|
+
instead of the classification output.
|
|
201
213
|
|
|
202
214
|
Returns
|
|
203
215
|
-------
|
|
204
|
-
|
|
205
|
-
(batch_size, n_outputs)
|
|
206
|
-
|
|
207
|
-
(batch_size,
|
|
216
|
+
torch.Tensor or tuple or dict
|
|
217
|
+
Default: ``torch.Tensor`` of shape ``(batch_size, n_outputs)``.
|
|
218
|
+
If ``return_features=True``: ``dict`` with ``"features"``
|
|
219
|
+
``(batch_size, emb_size)`` and ``"cls_token"`` (``None``).
|
|
220
|
+
If legacy ``return_feature=True`` (init param):
|
|
221
|
+
``(out, emb)`` tuple (ignored when ``return_features=True``).
|
|
208
222
|
"""
|
|
209
223
|
emb = self.encoder(x)
|
|
224
|
+
|
|
225
|
+
if return_features:
|
|
226
|
+
return {"features": emb, "cls_token": None}
|
|
227
|
+
|
|
210
228
|
x = self.final_layer(emb)
|
|
211
229
|
|
|
212
230
|
if self.return_feature:
|
{braindecode-1.3.2.dev179983996 → braindecode-1.3.2.dev181313884}/braindecode/models/cbramod.py
RENAMED
|
@@ -205,13 +205,33 @@ class CBraMod(EEGModuleMixin, nn.Module):
|
|
|
205
205
|
self.encoder = _TransformerEncoder(encoder_layer, num_layers=n_layer)
|
|
206
206
|
self.proj_out = nn.Sequential(nn.Linear(d_model, emb_dim))
|
|
207
207
|
|
|
208
|
+
self._emb_dim = emb_dim
|
|
209
|
+
self._patch_size = patch_size
|
|
208
210
|
self._weights_init()
|
|
209
211
|
|
|
210
|
-
|
|
211
|
-
nn.Identity()
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
212
|
+
if return_encoder_output:
|
|
213
|
+
self.final_layer = nn.Identity()
|
|
214
|
+
elif self._n_times is not None and self._n_chans is not None:
|
|
215
|
+
n_patch = self._n_times // patch_size
|
|
216
|
+
flat_dim = self._n_chans * n_patch * emb_dim
|
|
217
|
+
self.final_layer = nn.Sequential(
|
|
218
|
+
nn.Flatten(), nn.Linear(flat_dim, self.n_outputs)
|
|
219
|
+
)
|
|
220
|
+
else:
|
|
221
|
+
self.final_layer = nn.Sequential(
|
|
222
|
+
nn.Flatten(), nn.LazyLinear(self.n_outputs)
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
def reset_head(self, n_outputs):
|
|
226
|
+
self._n_outputs = n_outputs
|
|
227
|
+
if self._n_times is not None and self._n_chans is not None:
|
|
228
|
+
n_patch = self._n_times // self._patch_size
|
|
229
|
+
flat_dim = self._n_chans * n_patch * self._emb_dim
|
|
230
|
+
self.final_layer = nn.Sequential(
|
|
231
|
+
nn.Flatten(), nn.Linear(flat_dim, n_outputs)
|
|
232
|
+
)
|
|
233
|
+
else:
|
|
234
|
+
self.final_layer = nn.Sequential(nn.Flatten(), nn.LazyLinear(n_outputs))
|
|
215
235
|
|
|
216
236
|
def _weights_init(self):
|
|
217
237
|
for m in self.modules():
|
|
@@ -223,11 +243,13 @@ class CBraMod(EEGModuleMixin, nn.Module):
|
|
|
223
243
|
nn.init.constant_(m.weight, 1)
|
|
224
244
|
nn.init.constant_(m.bias, 0)
|
|
225
245
|
|
|
226
|
-
def forward(self, x, mask=None):
|
|
246
|
+
def forward(self, x, mask=None, return_features=False):
|
|
227
247
|
x = self.rearrange(x)
|
|
228
248
|
patch_emb = self.patch_embedding(x, mask)
|
|
229
249
|
feats = self.encoder(patch_emb)
|
|
230
250
|
out = self.proj_out(feats)
|
|
251
|
+
if return_features:
|
|
252
|
+
return {"features": out, "cls_token": None}
|
|
231
253
|
return self.final_layer(out)
|
|
232
254
|
|
|
233
255
|
|