Braindecode 1.6.1.dev1014__tar.gz → 1.6.1.dev1034__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.6.1.dev1014/braindecode.egg-info → braindecode-1.6.1.dev1034}/PKG-INFO +2 -2
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datasets/bids/hub.py +1 -41
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datasets/moabb.py +10 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/eegneuralnet.py +0 -41
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/__init__.py +2 -5
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/atcnet.py +1 -118
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/attn_sleep.py +10 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/eegnet.py +10 -1
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/eegtcnet.py +27 -62
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/sstdpn.py +4 -10
- braindecode-1.6.1.dev1034/braindecode/models/summary.csv +58 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/tsinception.py +11 -1
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/util.py +2 -2
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/modules/__init__.py +1 -2
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/modules/blocks.py +0 -82
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/preprocessing/mne_preprocess.py +1 -28
- braindecode-1.6.1.dev1034/braindecode/version.py +1 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034/braindecode.egg-info}/PKG-INFO +2 -2
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode.egg-info/SOURCES.txt +0 -2
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode.egg-info/requires.txt +1 -1
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/api.rst +0 -3
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/index.rst +4 -5
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/models/models_table.rst +2 -4
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/whats_new.rst +2 -90
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/pyproject.toml +1 -7
- braindecode-1.6.1.dev1014/braindecode/models/eegdino.py +0 -533
- braindecode-1.6.1.dev1014/braindecode/models/summary.csv +0 -60
- braindecode-1.6.1.dev1014/braindecode/models/tcformer.py +0 -643
- braindecode-1.6.1.dev1014/braindecode/version.py +0 -1
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/LICENSE.txt +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/MANIFEST.in +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/NOTICE.txt +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/README.rst +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/__init__.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/augmentation/__init__.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/augmentation/base.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/augmentation/functional.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/augmentation/transforms.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/classifier.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datasets/__init__.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datasets/base.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datasets/bbci.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datasets/bcicomp.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datasets/bids/__init__.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datasets/bids/datasets.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datasets/bids/format.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datasets/bids/hub_format.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datasets/bids/hub_io.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datasets/bids/hub_validation.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datasets/bids/iterable.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datasets/chb_mit.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datasets/mne.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datasets/nmt.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datasets/registry.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datasets/siena.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datasets/sleep_physio_challe_18.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datasets/sleep_physionet.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datasets/tuh.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datasets/utils.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datasets/xy.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datautil/__init__.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datautil/channel_utils.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datautil/hub_formats.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datautil/serialization.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/datautil/util.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/functional/__init__.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/functional/functions.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/functional/initialization.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/attentionbasenet.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/base.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/bendr.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/biot.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/brainmodule.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/cbramod.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/codebrain.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/config.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/contrawr.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/ctnet.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/deep4.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/deepsleepnet.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/dgcnn.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/eegconformer.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/eeginception_erp.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/eeginception_mi.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/eegitnet.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/eegminer.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/eegnex.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/eegpt.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/eegsimpleconv.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/eegsym.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/emg2qwerty.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/fbcnet.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/fblightconvnet.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/fbmsnet.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/hybrid.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/ifnet.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/interpolated.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/labram.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/luna.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/medformer.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/meta_neuromotor.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/msvtnet.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/patchedtransformer.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/reve.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/sccnet.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/shallow_fbcsp.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/signal_jepa.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/sinc_shallow.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/sleep_stager_blanco_2020.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/sleep_stager_chambon_2018.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/sparcnet.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/syncnet.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/tcn.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/tidnet.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/models/usleep.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/modules/activation.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/modules/attention.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/modules/convolution.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/modules/filter.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/modules/interpolation.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/modules/layers.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/modules/linear.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/modules/parametrization.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/modules/stats.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/modules/util.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/modules/wrapper.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/preprocessing/__init__.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/preprocessing/eegprep_preprocess.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/preprocessing/preprocess.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/preprocessing/util.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/preprocessing/windowers.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/regressor.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/samplers/__init__.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/samplers/base.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/samplers/ssl.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/training/__init__.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/training/callbacks.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/training/losses.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/training/scoring.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/util.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/visualization/__init__.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/visualization/attribution.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/visualization/confusion_matrices.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/visualization/frequency.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/visualization/metrics.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/visualization/sanity.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode/visualization/topology.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode.egg-info/dependency_links.txt +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/braindecode.egg-info/top_level.txt +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/Makefile +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/_templates/autosummary/class.rst +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/_templates/autosummary/class_in_subdir.rst +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/_templates/autosummary/function.rst +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/_templates/autosummary/function_in_subdir.rst +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/cite.rst +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/conf.py +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/help.rst +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/install/install.rst +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/install/install_pip.rst +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/install/install_source.rst +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/models/categorization/attention.rst +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/models/categorization/channel.rst +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/models/categorization/convolution.rst +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/models/categorization/filterbank.rst +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/models/categorization/gnn.rst +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/models/categorization/interpretable.rst +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/models/categorization/lbm.rst +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/models/categorization/recurrent.rst +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/models/categorization/spd.rst +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/models/models.rst +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/models/models_categorization.rst +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/models/models_visualization.rst +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/docs/sg_execution_times.rst +0 -0
- {braindecode-1.6.1.dev1014 → braindecode-1.6.1.dev1034}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: braindecode
|
|
3
|
-
Version: 1.6.1.
|
|
3
|
+
Version: 1.6.1.dev1034
|
|
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>
|
|
@@ -46,7 +46,7 @@ Requires-Dist: zarr>=3.0; extra == "hub"
|
|
|
46
46
|
Provides-Extra: viz
|
|
47
47
|
Requires-Dist: captum>=0.7.0; extra == "viz"
|
|
48
48
|
Provides-Extra: tests
|
|
49
|
-
Requires-Dist: pytest
|
|
49
|
+
Requires-Dist: pytest; extra == "tests"
|
|
50
50
|
Requires-Dist: pytest-cov; extra == "tests"
|
|
51
51
|
Requires-Dist: codecov; extra == "tests"
|
|
52
52
|
Requires-Dist: pytest_cases; extra == "tests"
|
|
@@ -327,7 +327,6 @@ class HubDatasetMixin:
|
|
|
327
327
|
|
|
328
328
|
n_recordings = len(self.datasets)
|
|
329
329
|
first_ds = self.datasets[0]
|
|
330
|
-
descriptions = [ds.description for ds in self.datasets]
|
|
331
330
|
|
|
332
331
|
# Get dataset-specific info based on type using registry
|
|
333
332
|
dataset_type = get_dataset_type(first_ds)
|
|
@@ -359,9 +358,6 @@ class HubDatasetMixin:
|
|
|
359
358
|
raise TypeError(f"Unsupported dataset type: {dataset_type}")
|
|
360
359
|
|
|
361
360
|
# Create README content and save
|
|
362
|
-
license_value, license_needs_update = _infer_license_from_descriptions(
|
|
363
|
-
descriptions
|
|
364
|
-
)
|
|
365
361
|
readme_content = _generate_readme_content(
|
|
366
362
|
format_info=format_info,
|
|
367
363
|
n_recordings=n_recordings,
|
|
@@ -370,8 +366,6 @@ class HubDatasetMixin:
|
|
|
370
366
|
data_type=data_type,
|
|
371
367
|
n_windows=n_windows,
|
|
372
368
|
total_duration=total_duration,
|
|
373
|
-
license=license_value,
|
|
374
|
-
license_needs_update=license_needs_update,
|
|
375
369
|
)
|
|
376
370
|
|
|
377
371
|
# Save README
|
|
@@ -973,8 +967,6 @@ def _generate_readme_content(
|
|
|
973
967
|
n_windows: int,
|
|
974
968
|
total_duration: float | None = None,
|
|
975
969
|
format: str = "zarr",
|
|
976
|
-
license: str = "please-specify",
|
|
977
|
-
license_needs_update: bool = True,
|
|
978
970
|
):
|
|
979
971
|
"""Generate README.md content for a dataset uploaded to the Hub.
|
|
980
972
|
|
|
@@ -996,10 +988,6 @@ def _generate_readme_content(
|
|
|
996
988
|
Total duration in seconds across all recordings.
|
|
997
989
|
format : str
|
|
998
990
|
Storage format (default: "zarr").
|
|
999
|
-
license : str
|
|
1000
|
-
Dataset license string to write in YAML front matter.
|
|
1001
|
-
license_needs_update : bool
|
|
1002
|
-
Whether to append a reminder comment next to the license field.
|
|
1003
991
|
|
|
1004
992
|
Returns
|
|
1005
993
|
-------
|
|
@@ -1015,10 +1003,6 @@ def _generate_readme_content(
|
|
|
1015
1003
|
str(timedelta(seconds=int(total_duration))) if total_duration else "N/A"
|
|
1016
1004
|
)
|
|
1017
1005
|
|
|
1018
|
-
license_line = f"license: {license}"
|
|
1019
|
-
if license_needs_update:
|
|
1020
|
-
license_line += " # Please update this field to reflect your dataset's license"
|
|
1021
|
-
|
|
1022
1006
|
return f"""---
|
|
1023
1007
|
tags:
|
|
1024
1008
|
- braindecode
|
|
@@ -1026,7 +1010,7 @@ tags:
|
|
|
1026
1010
|
- neuroscience
|
|
1027
1011
|
- brain-computer-interface
|
|
1028
1012
|
- deep-learning
|
|
1029
|
-
|
|
1013
|
+
license: unknown
|
|
1030
1014
|
---
|
|
1031
1015
|
|
|
1032
1016
|
# EEG Dataset
|
|
@@ -1122,27 +1106,3 @@ if hasattr(dataset.datasets[0], "bids_channels"):
|
|
|
1122
1106
|
|
|
1123
1107
|
*Created with [braindecode](https://braindecode.org)*
|
|
1124
1108
|
"""
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
def _infer_license_from_descriptions(
|
|
1128
|
-
descriptions: list[pd.Series | None],
|
|
1129
|
-
) -> tuple[str, bool]:
|
|
1130
|
-
"""Infer a single dataset license from descriptions.
|
|
1131
|
-
|
|
1132
|
-
Returns inferred license and whether a manual update reminder is needed.
|
|
1133
|
-
"""
|
|
1134
|
-
licenses = set()
|
|
1135
|
-
for description in descriptions:
|
|
1136
|
-
if description is None:
|
|
1137
|
-
continue
|
|
1138
|
-
raw_license = description.get("license", None)
|
|
1139
|
-
if raw_license is None:
|
|
1140
|
-
continue
|
|
1141
|
-
normalized = str(raw_license).strip()
|
|
1142
|
-
if normalized and normalized.lower() != "nan":
|
|
1143
|
-
licenses.add(normalized)
|
|
1144
|
-
|
|
1145
|
-
if len(licenses) == 1:
|
|
1146
|
-
return next(iter(licenses)), False
|
|
1147
|
-
|
|
1148
|
-
return "please-specify", True
|
|
@@ -15,6 +15,7 @@ from typing import Any
|
|
|
15
15
|
|
|
16
16
|
import mne
|
|
17
17
|
import pandas as pd
|
|
18
|
+
from mne.utils import deprecated
|
|
18
19
|
|
|
19
20
|
from braindecode.util import _update_moabb_docstring
|
|
20
21
|
|
|
@@ -207,3 +208,12 @@ class HGD(MOABBDataset):
|
|
|
207
208
|
|
|
208
209
|
def __init__(self, subject_ids):
|
|
209
210
|
super().__init__("Schirrmeister2017", subject_ids=subject_ids)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
@deprecated(
|
|
214
|
+
"`BNCI2014001` was renamed to `BNCI2014_001` in v1.13; this alias will be removed in v1.14."
|
|
215
|
+
)
|
|
216
|
+
class BNCI2014001(BNCI2014_001):
|
|
217
|
+
"""Deprecated alias for BNCI2014001."""
|
|
218
|
+
|
|
219
|
+
pass
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
import abc
|
|
8
8
|
import inspect
|
|
9
9
|
import logging
|
|
10
|
-
import warnings
|
|
11
10
|
from typing import Literal
|
|
12
11
|
|
|
13
12
|
import mne
|
|
@@ -42,7 +41,6 @@ def _get_model(model: str):
|
|
|
42
41
|
|
|
43
42
|
class _EEGNeuralNet(NeuralNet, abc.ABC):
|
|
44
43
|
signal_args_set_ = False
|
|
45
|
-
_warned_drop_last_ = False
|
|
46
44
|
|
|
47
45
|
@property
|
|
48
46
|
def log(self):
|
|
@@ -269,44 +267,6 @@ class _EEGNeuralNet(NeuralNet, abc.ABC):
|
|
|
269
267
|
X = X.get_data(units="uV")
|
|
270
268
|
return super().get_dataset(X, y)
|
|
271
269
|
|
|
272
|
-
def get_iterator(self, dataset, training=False):
|
|
273
|
-
iterator = super().get_iterator(dataset, training=training)
|
|
274
|
-
# Warn (once per fit) if drop_last would discard every training batch,
|
|
275
|
-
# e.g. a training set smaller than batch_size. This silently skips
|
|
276
|
-
# training without raising any error, which is hard to diagnose.
|
|
277
|
-
if training and not self._warned_drop_last_:
|
|
278
|
-
self._warn_if_training_batches_dropped(iterator)
|
|
279
|
-
return iterator
|
|
280
|
-
|
|
281
|
-
def _warn_if_training_batches_dropped(self, loader):
|
|
282
|
-
"""Warn if ``drop_last`` discards all training batches.
|
|
283
|
-
|
|
284
|
-
With ``iterator_train__drop_last=True`` (the braindecode default), a
|
|
285
|
-
training set smaller than ``batch_size`` yields zero batches, so no
|
|
286
|
-
forward/backward pass runs and the model is left untrained without any
|
|
287
|
-
error. We inspect the resolved training ``DataLoader`` (after
|
|
288
|
-
``train_split`` has been applied), so the count reflects the actual
|
|
289
|
-
number of training examples.
|
|
290
|
-
"""
|
|
291
|
-
self._warned_drop_last_ = True
|
|
292
|
-
if not getattr(loader, "drop_last", False):
|
|
293
|
-
return
|
|
294
|
-
batch_size = getattr(loader, "batch_size", None)
|
|
295
|
-
try:
|
|
296
|
-
n_train = len(loader.dataset)
|
|
297
|
-
except TypeError:
|
|
298
|
-
return # e.g. an IterableDataset whose length is unknown
|
|
299
|
-
if not batch_size or n_train == 0 or n_train >= batch_size:
|
|
300
|
-
return
|
|
301
|
-
warnings.warn(
|
|
302
|
-
f"The training set has {n_train} example(s), which is smaller than "
|
|
303
|
-
f"batch_size={batch_size}. With iterator_train__drop_last=True "
|
|
304
|
-
f"(the braindecode default), all training batches are dropped and "
|
|
305
|
-
f"the model is not trained. Reduce batch_size to at most {n_train}, "
|
|
306
|
-
f"or pass iterator_train__drop_last=False.",
|
|
307
|
-
UserWarning,
|
|
308
|
-
)
|
|
309
|
-
|
|
310
270
|
def partial_fit(self, X, y=None, classes=None, **fit_params):
|
|
311
271
|
"""Fit the module.
|
|
312
272
|
|
|
@@ -406,7 +366,6 @@ class _EEGNeuralNet(NeuralNet, abc.ABC):
|
|
|
406
366
|
the module and to the ``self.train_split`` call.
|
|
407
367
|
"""
|
|
408
368
|
# this needs to be executed before the net is initialized:
|
|
409
|
-
self._warned_drop_last_ = False # re-check on every fresh fit
|
|
410
369
|
if not self.signal_args_set_:
|
|
411
370
|
self._set_signal_args(X, y, classes=None)
|
|
412
371
|
self.signal_args_set_ = True
|
|
@@ -15,12 +15,11 @@ from .deep4 import Deep4Net
|
|
|
15
15
|
from .deepsleepnet import DeepSleepNet
|
|
16
16
|
from .dgcnn import DGCNN
|
|
17
17
|
from .eegconformer import EEGConformer
|
|
18
|
-
from .eegdino import EEGDINO
|
|
19
18
|
from .eeginception_erp import EEGInceptionERP
|
|
20
19
|
from .eeginception_mi import EEGInceptionMI
|
|
21
20
|
from .eegitnet import EEGITNet
|
|
22
21
|
from .eegminer import EEGMiner
|
|
23
|
-
from .eegnet import EEGNet
|
|
22
|
+
from .eegnet import EEGNet, EEGNetv4
|
|
24
23
|
from .eegnex import EEGNeX
|
|
25
24
|
from .eegpt import EEGPT, InterpolatedEEGPT
|
|
26
25
|
from .eegsimpleconv import EEGSimpleConv
|
|
@@ -55,7 +54,6 @@ from .sleep_stager_chambon_2018 import SleepStagerChambon2018
|
|
|
55
54
|
from .sparcnet import SPARCNet
|
|
56
55
|
from .sstdpn import SSTDPN
|
|
57
56
|
from .syncnet import SyncNet
|
|
58
|
-
from .tcformer import TCFormer
|
|
59
57
|
from .tcn import BDTCN, TCN
|
|
60
58
|
from .tidnet import TIDNet
|
|
61
59
|
from .tsinception import TSception
|
|
@@ -86,7 +84,6 @@ __all__ = [
|
|
|
86
84
|
"DeepSleepNet",
|
|
87
85
|
"BrainModule",
|
|
88
86
|
"EEGConformer",
|
|
89
|
-
"EEGDINO",
|
|
90
87
|
"EEGPT",
|
|
91
88
|
"InterpolatedEEGPT",
|
|
92
89
|
"EEGInceptionERP",
|
|
@@ -94,6 +91,7 @@ __all__ = [
|
|
|
94
91
|
"EEGITNet",
|
|
95
92
|
"EEGMiner",
|
|
96
93
|
"EEGNet",
|
|
94
|
+
"EEGNetv4",
|
|
97
95
|
"EEGNeX",
|
|
98
96
|
"EEGSym",
|
|
99
97
|
"EEGSimpleConv",
|
|
@@ -131,7 +129,6 @@ __all__ = [
|
|
|
131
129
|
"SPARCNet",
|
|
132
130
|
"SyncNet",
|
|
133
131
|
"BDTCN",
|
|
134
|
-
"TCFormer",
|
|
135
132
|
"TCN",
|
|
136
133
|
"TIDNet",
|
|
137
134
|
"TSception",
|
|
@@ -2,21 +2,14 @@
|
|
|
2
2
|
#
|
|
3
3
|
# License: BSD (3-clause)
|
|
4
4
|
import math
|
|
5
|
-
from typing import Optional
|
|
6
5
|
|
|
7
6
|
import torch
|
|
8
7
|
from einops.layers.torch import Rearrange
|
|
9
8
|
from mne.utils import warn
|
|
10
9
|
from torch import nn
|
|
11
|
-
from torch.nn.utils.parametrize import is_parametrized, register_parametrization
|
|
12
10
|
|
|
13
11
|
from braindecode.models.base import EEGModuleMixin
|
|
14
|
-
from braindecode.modules import
|
|
15
|
-
CausalConv1d,
|
|
16
|
-
Ensure4d,
|
|
17
|
-
MaxNormLinear,
|
|
18
|
-
MaxNormParametrize,
|
|
19
|
-
)
|
|
12
|
+
from braindecode.modules import CausalConv1d, Ensure4d, MaxNormLinear
|
|
20
13
|
|
|
21
14
|
|
|
22
15
|
class ATCNet(EEGModuleMixin, nn.Module):
|
|
@@ -220,16 +213,6 @@ class ATCNet(EEGModuleMixin, nn.Module):
|
|
|
220
213
|
max_norm_const : float
|
|
221
214
|
Maximum L2-norm constraint imposed on weights of the last
|
|
222
215
|
fully-connected layer. Defaults to 0.25.
|
|
223
|
-
conv_max_norm_const : float | None
|
|
224
|
-
If not ``None``, applies a max-norm constraint (via a weight
|
|
225
|
-
parametrization) to the convolution kernels of :class:`_ConvBlock` and
|
|
226
|
-
:class:`_TCNResidualBlock`, matching the official implementation which
|
|
227
|
-
uses ``0.6``. When ``None`` (default), no constraint is applied to those
|
|
228
|
-
layers, preserving the previous behavior. The complementary ``L2``
|
|
229
|
-
weight decay of the official code can be obtained from
|
|
230
|
-
:meth:`source_optimizer_param_groups`.
|
|
231
|
-
|
|
232
|
-
.. versionadded:: 1.6.1
|
|
233
216
|
|
|
234
217
|
Notes
|
|
235
218
|
-----
|
|
@@ -274,7 +257,6 @@ class ATCNet(EEGModuleMixin, nn.Module):
|
|
|
274
257
|
tcn_activation: type[nn.Module] = nn.ELU,
|
|
275
258
|
concat=False,
|
|
276
259
|
max_norm_const=0.25,
|
|
277
|
-
conv_max_norm_const: Optional[float] = None,
|
|
278
260
|
chs_info=None,
|
|
279
261
|
n_times=None,
|
|
280
262
|
):
|
|
@@ -343,7 +325,6 @@ class ATCNet(EEGModuleMixin, nn.Module):
|
|
|
343
325
|
self.tcn_activation = tcn_activation
|
|
344
326
|
self.concat = concat
|
|
345
327
|
self.max_norm_const = max_norm_const
|
|
346
|
-
self.conv_max_norm_const = conv_max_norm_const
|
|
347
328
|
self.tcn_n_filters = int(self.conv_block_depth_mult * self.conv_block_n_filters)
|
|
348
329
|
map = dict()
|
|
349
330
|
for w in range(self.n_windows):
|
|
@@ -365,7 +346,6 @@ class ATCNet(EEGModuleMixin, nn.Module):
|
|
|
365
346
|
pool_size_2=conv_block_pool_size_2,
|
|
366
347
|
depth_mult=conv_block_depth_mult,
|
|
367
348
|
dropout=conv_block_dropout,
|
|
368
|
-
conv_max_norm=self.conv_max_norm_const,
|
|
369
349
|
)
|
|
370
350
|
|
|
371
351
|
self.F2 = int(conv_block_depth_mult * conv_block_n_filters)
|
|
@@ -395,7 +375,6 @@ class ATCNet(EEGModuleMixin, nn.Module):
|
|
|
395
375
|
dropout=self.tcn_dropout,
|
|
396
376
|
activation=self.tcn_activation,
|
|
397
377
|
dilation=2**i,
|
|
398
|
-
conv_max_norm=self.conv_max_norm_const,
|
|
399
378
|
)
|
|
400
379
|
for i in range(self.tcn_depth)
|
|
401
380
|
]
|
|
@@ -479,93 +458,6 @@ class ATCNet(EEGModuleMixin, nn.Module):
|
|
|
479
458
|
|
|
480
459
|
return self.out_fun(sw_concat_agg)
|
|
481
460
|
|
|
482
|
-
def source_optimizer_param_groups(
|
|
483
|
-
self,
|
|
484
|
-
conv_weight_decay: float = 0.009,
|
|
485
|
-
dense_weight_decay: float = 0.5,
|
|
486
|
-
) -> list[dict]:
|
|
487
|
-
r"""Source-faithful optimizer parameter groups for ATCNet.
|
|
488
|
-
|
|
489
|
-
The official Keras implementation applies ``L2`` weight decay only to the
|
|
490
|
-
convolution / TCN kernels (``conv_weightDecay = 0.009``) and to the final
|
|
491
|
-
dense layer (``dense_weightDecay = 0.5``); biases, BatchNorm and attention
|
|
492
|
-
weights are left undecayed. This reproduces the Keras ``L2`` kernel penalty
|
|
493
|
-
only for optimizers that implement ``weight_decay`` as a coupled L2 term,
|
|
494
|
-
e.g. :class:`torch.optim.SGD` or :class:`torch.optim.Adam` (as used by the
|
|
495
|
-
official code). For decoupled-weight-decay optimizers such as
|
|
496
|
-
:class:`torch.optim.AdamW`, ``weight_decay`` is *not* equivalent to a Keras
|
|
497
|
-
``L2`` penalty.
|
|
498
|
-
|
|
499
|
-
Parameters
|
|
500
|
-
----------
|
|
501
|
-
conv_weight_decay : float
|
|
502
|
-
Weight decay applied to the convolution and TCN kernels. Defaults to
|
|
503
|
-
``0.009`` as in the official code.
|
|
504
|
-
dense_weight_decay : float
|
|
505
|
-
Weight decay applied to the final (dense) layer weights. Defaults to
|
|
506
|
-
``0.5`` as in the official code.
|
|
507
|
-
|
|
508
|
-
Returns
|
|
509
|
-
-------
|
|
510
|
-
list of dict
|
|
511
|
-
Parameter groups ready to be passed to a ``torch.optim`` optimizer:
|
|
512
|
-
convolution/TCN kernels, final dense weights, and everything else
|
|
513
|
-
(no decay).
|
|
514
|
-
|
|
515
|
-
Examples
|
|
516
|
-
--------
|
|
517
|
-
>>> model = ATCNet(n_chans=22, n_outputs=4, n_times=1125) # doctest: +SKIP
|
|
518
|
-
>>> opt = torch.optim.Adam(model.source_optimizer_param_groups()) # doctest: +SKIP
|
|
519
|
-
"""
|
|
520
|
-
|
|
521
|
-
def weight_leaf(module):
|
|
522
|
-
# Return the leaf weight Parameter, accounting for a registered
|
|
523
|
-
# max-norm parametrization (``conv_max_norm_const`` / MaxNormLinear).
|
|
524
|
-
if is_parametrized(module, "weight"):
|
|
525
|
-
return module.parametrizations.weight.original
|
|
526
|
-
return module.weight
|
|
527
|
-
|
|
528
|
-
conv_weights: list[nn.Parameter] = []
|
|
529
|
-
dense_weights: list[nn.Parameter] = []
|
|
530
|
-
decayed_ids: set[int] = set()
|
|
531
|
-
|
|
532
|
-
# Convolution / TCN kernels (Keras L2 = 0.009).
|
|
533
|
-
for parent in (self.conv_block, self.temporal_conv_nets):
|
|
534
|
-
for module in parent.modules():
|
|
535
|
-
if isinstance(module, (nn.Conv1d, nn.Conv2d)):
|
|
536
|
-
weight = weight_leaf(module)
|
|
537
|
-
conv_weights.append(weight)
|
|
538
|
-
decayed_ids.add(id(weight))
|
|
539
|
-
|
|
540
|
-
# Final dense / readout weights (Keras L2 = 0.5).
|
|
541
|
-
for module in self.final_layer.modules():
|
|
542
|
-
if isinstance(module, nn.Linear):
|
|
543
|
-
weight = weight_leaf(module)
|
|
544
|
-
dense_weights.append(weight)
|
|
545
|
-
decayed_ids.add(id(weight))
|
|
546
|
-
|
|
547
|
-
# Everything else (biases, BatchNorm, attention) is left undecayed.
|
|
548
|
-
other = [p for p in self.parameters() if id(p) not in decayed_ids]
|
|
549
|
-
|
|
550
|
-
return [
|
|
551
|
-
{"params": conv_weights, "weight_decay": conv_weight_decay},
|
|
552
|
-
{"params": dense_weights, "weight_decay": dense_weight_decay},
|
|
553
|
-
{"params": other, "weight_decay": 0.0},
|
|
554
|
-
]
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
def _register_max_norm(max_norm, *convs):
|
|
558
|
-
"""Register a max-norm weight parametrization on each given convolution.
|
|
559
|
-
|
|
560
|
-
No-op when ``max_norm`` is ``None`` or a passed layer is not a convolution
|
|
561
|
-
(e.g. an ``nn.Identity`` residual shortcut).
|
|
562
|
-
"""
|
|
563
|
-
if max_norm is None:
|
|
564
|
-
return
|
|
565
|
-
for conv in convs:
|
|
566
|
-
if isinstance(conv, (nn.Conv1d, nn.Conv2d)):
|
|
567
|
-
register_parametrization(conv, "weight", MaxNormParametrize(max_norm))
|
|
568
|
-
|
|
569
461
|
|
|
570
462
|
class _ConvBlock(nn.Module):
|
|
571
463
|
r"""Convolutional block proposed in ATCNet [1]_, inspired by the EEGNet.
|
|
@@ -595,7 +487,6 @@ class _ConvBlock(nn.Module):
|
|
|
595
487
|
pool_size_2=7,
|
|
596
488
|
depth_mult=2,
|
|
597
489
|
dropout=0.3,
|
|
598
|
-
conv_max_norm: Optional[float] = None,
|
|
599
490
|
):
|
|
600
491
|
super().__init__()
|
|
601
492
|
|
|
@@ -643,9 +534,6 @@ class _ConvBlock(nn.Module):
|
|
|
643
534
|
|
|
644
535
|
self.drop3 = nn.Dropout2d(dropout)
|
|
645
536
|
|
|
646
|
-
# Optional source-faithful max-norm constraint on the conv kernels.
|
|
647
|
-
_register_max_norm(conv_max_norm, self.conv1, self.conv2, self.conv3)
|
|
648
|
-
|
|
649
537
|
def forward(self, X):
|
|
650
538
|
# ----- Temporal convolution -----
|
|
651
539
|
# Dimension: (batch_size, 1, T, C)
|
|
@@ -774,7 +662,6 @@ class _TCNResidualBlock(nn.Module):
|
|
|
774
662
|
dropout=0.3,
|
|
775
663
|
activation: type[nn.Module] = nn.ELU,
|
|
776
664
|
dilation=1,
|
|
777
|
-
conv_max_norm: Optional[float] = None,
|
|
778
665
|
):
|
|
779
666
|
super().__init__()
|
|
780
667
|
self.activation = activation()
|
|
@@ -819,10 +706,6 @@ class _TCNResidualBlock(nn.Module):
|
|
|
819
706
|
else:
|
|
820
707
|
self.reshaping_conv = nn.Identity()
|
|
821
708
|
|
|
822
|
-
# Optional source-faithful max-norm constraint on the conv kernels
|
|
823
|
-
# (reshaping_conv may be nn.Identity, which the helper skips).
|
|
824
|
-
_register_max_norm(conv_max_norm, self.conv1, self.conv2, self.reshaping_conv)
|
|
825
|
-
|
|
826
709
|
def forward(self, X):
|
|
827
710
|
# Dimension: (batch_size, F2, Tw)
|
|
828
711
|
# ----- Double dilated convolutions -----
|
|
@@ -8,6 +8,7 @@ from copy import deepcopy
|
|
|
8
8
|
|
|
9
9
|
import torch
|
|
10
10
|
import torch.nn.functional as F
|
|
11
|
+
from mne.utils import deprecated
|
|
11
12
|
from torch import nn
|
|
12
13
|
|
|
13
14
|
from braindecode.models.base import EEGModuleMixin
|
|
@@ -537,3 +538,12 @@ class _PositionwiseFeedForward(nn.Module):
|
|
|
537
538
|
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
|
538
539
|
"""Implements FFN equation."""
|
|
539
540
|
return self.w_2(self.dropout(self.activate(self.w_1(x))))
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
@deprecated(
|
|
544
|
+
"`SleepStagerEldele2021` was renamed to `AttnSleep` in v1.12 to follow original author's name; this alias will be removed in v1.14."
|
|
545
|
+
)
|
|
546
|
+
class SleepStagerEldele2021(AttnSleep):
|
|
547
|
+
r"""Deprecated alias for SleepStagerEldele2021."""
|
|
548
|
+
|
|
549
|
+
pass
|
|
@@ -6,7 +6,7 @@ from __future__ import annotations
|
|
|
6
6
|
from typing import Dict, Optional
|
|
7
7
|
|
|
8
8
|
from einops.layers.torch import Rearrange
|
|
9
|
-
from mne.utils import warn
|
|
9
|
+
from mne.utils import deprecated, warn
|
|
10
10
|
from torch import nn
|
|
11
11
|
|
|
12
12
|
from braindecode.functional import glorot_weight_zero_bias
|
|
@@ -348,3 +348,12 @@ class EEGNet(EEGModuleMixin, nn.Sequential):
|
|
|
348
348
|
self.add_module("final_layer", module)
|
|
349
349
|
|
|
350
350
|
glorot_weight_zero_bias(self)
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
@deprecated(
|
|
354
|
+
"`EEGNetv4` was renamed to `EEGNet` in v1.12; this alias will be removed in v1.14."
|
|
355
|
+
)
|
|
356
|
+
class EEGNetv4(EEGNet):
|
|
357
|
+
r"""Deprecated alias for EEGNet."""
|
|
358
|
+
|
|
359
|
+
pass
|
|
@@ -9,7 +9,6 @@ import torch.nn as nn
|
|
|
9
9
|
from einops.layers.torch import Rearrange
|
|
10
10
|
|
|
11
11
|
from braindecode.models.base import EEGModuleMixin
|
|
12
|
-
from braindecode.models.util import _disable_batch_norm_training_if_batch_size_one
|
|
13
12
|
from braindecode.modules import Chomp1d, MaxNormLinear
|
|
14
13
|
|
|
15
14
|
|
|
@@ -34,10 +33,8 @@ class EEGTCNet(EEGModuleMixin, nn.Module):
|
|
|
34
33
|
Number of temporal filters in the first convolutional layer. Default is 8.
|
|
35
34
|
kern_length : int, optional
|
|
36
35
|
Length of the temporal kernel in the first convolutional layer. Default is 64.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
block unless overridden by ``drop_prob_eeg`` / ``drop_prob_tcn``.
|
|
40
|
-
Default is 0.5.
|
|
36
|
+
dropout : float, optional
|
|
37
|
+
Dropout rate. Default is 0.5.
|
|
41
38
|
depth : int, optional
|
|
42
39
|
Number of residual blocks in the TCN. Default is 2.
|
|
43
40
|
kernel_size : int, optional
|
|
@@ -47,20 +44,6 @@ class EEGTCNet(EEGModuleMixin, nn.Module):
|
|
|
47
44
|
max_norm_const : float
|
|
48
45
|
Maximum L2-norm constraint imposed on weights of the last
|
|
49
46
|
fully-connected layer. Defaults to 0.25.
|
|
50
|
-
drop_prob_eeg : float | None, optional
|
|
51
|
-
Dropout rate for the EEGNet front-end. If ``None`` (default), falls back
|
|
52
|
-
to ``drop_prob``. The source/paper uses ``0.2`` for BCI IV 2a.
|
|
53
|
-
drop_prob_tcn : float | None, optional
|
|
54
|
-
Dropout rate for the TCN block. If ``None`` (default), falls back to
|
|
55
|
-
``drop_prob``. The source/paper uses ``0.3`` for BCI IV 2a.
|
|
56
|
-
tcn_batch_norm : bool, optional
|
|
57
|
-
If ``True`` (default), insert a :class:`~torch.nn.BatchNorm1d` after each
|
|
58
|
-
TCN convolution and use a bias in the residual ``1x1`` downsample, matching
|
|
59
|
-
the original Keras source. Set to ``False`` to recover the previous
|
|
60
|
-
braindecode architecture (e.g. to load checkpoints trained before this
|
|
61
|
-
change). Default is ``True``.
|
|
62
|
-
|
|
63
|
-
.. versionadded:: 1.6.1
|
|
64
47
|
|
|
65
48
|
References
|
|
66
49
|
----------
|
|
@@ -89,9 +72,6 @@ class EEGTCNet(EEGModuleMixin, nn.Module):
|
|
|
89
72
|
kernel_size: int = 4,
|
|
90
73
|
filters: int = 12,
|
|
91
74
|
max_norm_const: float = 0.25,
|
|
92
|
-
drop_prob_eeg: float | None = None,
|
|
93
|
-
drop_prob_tcn: float | None = None,
|
|
94
|
-
tcn_batch_norm: bool = True,
|
|
95
75
|
):
|
|
96
76
|
super().__init__(
|
|
97
77
|
n_outputs=n_outputs,
|
|
@@ -105,11 +85,6 @@ class EEGTCNet(EEGModuleMixin, nn.Module):
|
|
|
105
85
|
|
|
106
86
|
self.activation = activation
|
|
107
87
|
self.drop_prob = drop_prob
|
|
108
|
-
# Separate dropout rates for the EEGNet front-end and the TCN block;
|
|
109
|
-
# fall back to ``drop_prob`` when not explicitly set.
|
|
110
|
-
self.drop_prob_eeg = drop_prob if drop_prob_eeg is None else drop_prob_eeg
|
|
111
|
-
self.drop_prob_tcn = drop_prob if drop_prob_tcn is None else drop_prob_tcn
|
|
112
|
-
self.tcn_batch_norm = tcn_batch_norm
|
|
113
88
|
self.depth_multiplier = depth_multiplier
|
|
114
89
|
self.filter_1 = filter_1
|
|
115
90
|
self.kern_length = kern_length
|
|
@@ -128,7 +103,7 @@ class EEGTCNet(EEGModuleMixin, nn.Module):
|
|
|
128
103
|
filter_1=self.filter_1,
|
|
129
104
|
kern_length=self.kern_length,
|
|
130
105
|
depth_multiplier=self.depth_multiplier,
|
|
131
|
-
drop_prob=self.
|
|
106
|
+
drop_prob=self.drop_prob,
|
|
132
107
|
activation=self.activation,
|
|
133
108
|
)
|
|
134
109
|
self.arrange_dim_eegnet = Rearrange(
|
|
@@ -141,9 +116,8 @@ class EEGTCNet(EEGModuleMixin, nn.Module):
|
|
|
141
116
|
depth=self.depth,
|
|
142
117
|
kernel_size=self.kernel_size,
|
|
143
118
|
filters=self.filters,
|
|
144
|
-
drop_prob=self.
|
|
119
|
+
drop_prob=self.drop_prob,
|
|
145
120
|
activation=self.activation,
|
|
146
|
-
batch_norm=self.tcn_batch_norm,
|
|
147
121
|
)
|
|
148
122
|
|
|
149
123
|
# Classification Block
|
|
@@ -153,7 +127,6 @@ class EEGTCNet(EEGModuleMixin, nn.Module):
|
|
|
153
127
|
max_norm_val=self.max_norm_const,
|
|
154
128
|
)
|
|
155
129
|
|
|
156
|
-
@_disable_batch_norm_training_if_batch_size_one
|
|
157
130
|
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
|
158
131
|
"""
|
|
159
132
|
Forward pass of the EEGTCNet model.
|
|
@@ -304,7 +277,6 @@ class _TCNBlock(nn.Module):
|
|
|
304
277
|
filters: int,
|
|
305
278
|
drop_prob: float,
|
|
306
279
|
activation: type[nn.Module] = nn.ELU,
|
|
307
|
-
batch_norm: bool = True,
|
|
308
280
|
):
|
|
309
281
|
super().__init__()
|
|
310
282
|
self.activation = activation()
|
|
@@ -312,15 +284,10 @@ class _TCNBlock(nn.Module):
|
|
|
312
284
|
self.depth = depth
|
|
313
285
|
self.filters = filters
|
|
314
286
|
self.kernel_size = kernel_size
|
|
315
|
-
self.batch_norm = batch_norm
|
|
316
287
|
|
|
317
288
|
self.layers = nn.ModuleList()
|
|
318
|
-
# The Keras source uses a bias on the residual 1x1 downsample, paired
|
|
319
|
-
# with the per-conv BatchNorm; the previous braindecode default omitted
|
|
320
|
-
# both. Keeping them on the same flag makes ``batch_norm=False`` reproduce
|
|
321
|
-
# the legacy architecture exactly.
|
|
322
289
|
self.downsample = (
|
|
323
|
-
nn.Conv1d(input_dimension, filters, kernel_size=1, bias=
|
|
290
|
+
nn.Conv1d(input_dimension, filters, kernel_size=1, bias=False)
|
|
324
291
|
if input_dimension != filters
|
|
325
292
|
else None
|
|
326
293
|
)
|
|
@@ -328,34 +295,32 @@ class _TCNBlock(nn.Module):
|
|
|
328
295
|
for i in range(depth):
|
|
329
296
|
dilation = 2**i
|
|
330
297
|
padding = (kernel_size - 1) * dilation
|
|
331
|
-
in_dim = input_dimension if i == 0 else filters
|
|
332
298
|
conv_block = nn.Sequential(
|
|
333
|
-
|
|
334
|
-
|
|
299
|
+
nn.Conv1d(
|
|
300
|
+
in_channels=input_dimension if i == 0 else filters,
|
|
301
|
+
out_channels=filters,
|
|
302
|
+
kernel_size=kernel_size,
|
|
303
|
+
dilation=dilation,
|
|
304
|
+
padding=padding,
|
|
305
|
+
bias=False,
|
|
306
|
+
),
|
|
307
|
+
Chomp1d(padding),
|
|
308
|
+
self.activation,
|
|
309
|
+
nn.Dropout(self.drop_prob),
|
|
310
|
+
nn.Conv1d(
|
|
311
|
+
in_channels=filters,
|
|
312
|
+
out_channels=filters,
|
|
313
|
+
kernel_size=kernel_size,
|
|
314
|
+
dilation=dilation,
|
|
315
|
+
padding=padding,
|
|
316
|
+
bias=False,
|
|
317
|
+
),
|
|
318
|
+
Chomp1d(padding),
|
|
319
|
+
self.activation,
|
|
320
|
+
nn.Dropout(self.drop_prob),
|
|
335
321
|
)
|
|
336
322
|
self.layers.append(conv_block)
|
|
337
323
|
|
|
338
|
-
def _conv_unit(self, in_channels: int, dilation: int, padding: int):
|
|
339
|
-
# Conv -> Chomp -> [BatchNorm] -> activation -> Dropout, as in the
|
|
340
|
-
# original EEG-TCNet Keras implementation.
|
|
341
|
-
unit = [
|
|
342
|
-
nn.Conv1d(
|
|
343
|
-
in_channels=in_channels,
|
|
344
|
-
out_channels=self.filters,
|
|
345
|
-
kernel_size=self.kernel_size,
|
|
346
|
-
dilation=dilation,
|
|
347
|
-
padding=padding,
|
|
348
|
-
bias=False,
|
|
349
|
-
),
|
|
350
|
-
Chomp1d(padding),
|
|
351
|
-
]
|
|
352
|
-
if self.batch_norm:
|
|
353
|
-
# Keras BatchNormalization defaults: momentum=0.99 (-> 0.01 in
|
|
354
|
-
# PyTorch convention) and epsilon=1e-3.
|
|
355
|
-
unit.append(nn.BatchNorm1d(self.filters, momentum=0.01, eps=1e-3))
|
|
356
|
-
unit += [self.activation, nn.Dropout(self.drop_prob)]
|
|
357
|
-
return unit
|
|
358
|
-
|
|
359
324
|
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
|
360
325
|
# x shape: (batch_size, time_steps, input_dimension)
|
|
361
326
|
x = x.permute(0, 2, 1) # (batch_size, input_dimension, time_steps)
|