braindecode 1.6.1.dev1056__tar.gz → 1.6.1.dev1065__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.dev1056/braindecode.egg-info → braindecode-1.6.1.dev1065}/PKG-INFO +1 -1
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/__init__.py +2 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/atcnet.py +118 -1
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/eegtcnet.py +62 -27
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/sstdpn.py +10 -4
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/summary.csv +1 -0
- braindecode-1.6.1.dev1065/braindecode/models/tcformer.py +643 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/util.py +1 -0
- braindecode-1.6.1.dev1065/braindecode/version.py +1 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065/braindecode.egg-info}/PKG-INFO +1 -1
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode.egg-info/SOURCES.txt +1 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/api.rst +1 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/whats_new.rst +31 -0
- braindecode-1.6.1.dev1056/braindecode/version.py +0 -1
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/LICENSE.txt +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/MANIFEST.in +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/NOTICE.txt +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/README.rst +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/__init__.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/augmentation/__init__.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/augmentation/base.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/augmentation/functional.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/augmentation/transforms.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/classifier.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datasets/__init__.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datasets/base.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datasets/bbci.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datasets/bcicomp.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datasets/bids/__init__.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datasets/bids/datasets.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datasets/bids/format.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datasets/bids/hub.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datasets/bids/hub_format.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datasets/bids/hub_io.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datasets/bids/hub_validation.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datasets/bids/iterable.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datasets/chb_mit.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datasets/mne.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datasets/moabb.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datasets/nmt.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datasets/registry.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datasets/siena.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datasets/sleep_physio_challe_18.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datasets/sleep_physionet.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datasets/tuh.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datasets/utils.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datasets/xy.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datautil/__init__.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datautil/channel_utils.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datautil/hub_formats.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datautil/serialization.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/datautil/util.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/eegneuralnet.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/functional/__init__.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/functional/functions.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/functional/initialization.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/attentionbasenet.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/attn_sleep.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/base.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/bendr.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/biot.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/brainmodule.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/cbramod.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/codebrain.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/config.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/contrawr.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/ctnet.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/deep4.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/deepsleepnet.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/dgcnn.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/eegconformer.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/eegdino.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/eeginception_erp.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/eeginception_mi.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/eegitnet.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/eegminer.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/eegnet.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/eegnex.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/eegpt.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/eegsimpleconv.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/eegsym.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/emg2qwerty.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/fbcnet.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/fblightconvnet.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/fbmsnet.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/hybrid.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/ifnet.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/interpolated.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/labram.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/luna.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/medformer.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/meta_neuromotor.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/msvtnet.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/patchedtransformer.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/reve.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/sccnet.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/shallow_fbcsp.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/signal_jepa.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/sinc_shallow.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/sleep_stager_blanco_2020.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/sleep_stager_chambon_2018.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/sparcnet.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/syncnet.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/tcn.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/tidnet.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/tsinception.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/models/usleep.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/modules/__init__.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/modules/activation.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/modules/attention.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/modules/blocks.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/modules/convolution.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/modules/filter.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/modules/interpolation.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/modules/layers.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/modules/linear.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/modules/parametrization.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/modules/stats.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/modules/util.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/modules/wrapper.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/preprocessing/__init__.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/preprocessing/eegprep_preprocess.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/preprocessing/mne_preprocess.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/preprocessing/preprocess.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/preprocessing/util.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/preprocessing/windowers.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/regressor.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/samplers/__init__.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/samplers/base.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/samplers/ssl.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/training/__init__.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/training/callbacks.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/training/losses.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/training/scoring.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/util.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/visualization/__init__.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/visualization/attribution.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/visualization/confusion_matrices.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/visualization/frequency.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/visualization/metrics.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/visualization/sanity.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode/visualization/topology.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode.egg-info/dependency_links.txt +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode.egg-info/requires.txt +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/braindecode.egg-info/top_level.txt +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/Makefile +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/_templates/autosummary/class.rst +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/_templates/autosummary/class_in_subdir.rst +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/_templates/autosummary/function.rst +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/_templates/autosummary/function_in_subdir.rst +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/cite.rst +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/conf.py +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/help.rst +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/index.rst +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/install/install.rst +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/install/install_pip.rst +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/install/install_source.rst +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/models/categorization/attention.rst +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/models/categorization/channel.rst +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/models/categorization/convolution.rst +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/models/categorization/filterbank.rst +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/models/categorization/gnn.rst +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/models/categorization/interpretable.rst +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/models/categorization/lbm.rst +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/models/categorization/recurrent.rst +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/models/categorization/spd.rst +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/models/models.rst +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/models/models_categorization.rst +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/models/models_table.rst +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/models/models_visualization.rst +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/docs/sg_execution_times.rst +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/pyproject.toml +0 -0
- {braindecode-1.6.1.dev1056 → braindecode-1.6.1.dev1065}/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.dev1065
|
|
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>
|
|
@@ -55,6 +55,7 @@ from .sleep_stager_chambon_2018 import SleepStagerChambon2018
|
|
|
55
55
|
from .sparcnet import SPARCNet
|
|
56
56
|
from .sstdpn import SSTDPN
|
|
57
57
|
from .syncnet import SyncNet
|
|
58
|
+
from .tcformer import TCFormer
|
|
58
59
|
from .tcn import BDTCN, TCN
|
|
59
60
|
from .tidnet import TIDNet
|
|
60
61
|
from .tsinception import TSception
|
|
@@ -130,6 +131,7 @@ __all__ = [
|
|
|
130
131
|
"SPARCNet",
|
|
131
132
|
"SyncNet",
|
|
132
133
|
"BDTCN",
|
|
134
|
+
"TCFormer",
|
|
133
135
|
"TCN",
|
|
134
136
|
"TIDNet",
|
|
135
137
|
"TSception",
|
|
@@ -2,14 +2,21 @@
|
|
|
2
2
|
#
|
|
3
3
|
# License: BSD (3-clause)
|
|
4
4
|
import math
|
|
5
|
+
from typing import Optional
|
|
5
6
|
|
|
6
7
|
import torch
|
|
7
8
|
from einops.layers.torch import Rearrange
|
|
8
9
|
from mne.utils import warn
|
|
9
10
|
from torch import nn
|
|
11
|
+
from torch.nn.utils.parametrize import is_parametrized, register_parametrization
|
|
10
12
|
|
|
11
13
|
from braindecode.models.base import EEGModuleMixin
|
|
12
|
-
from braindecode.modules import
|
|
14
|
+
from braindecode.modules import (
|
|
15
|
+
CausalConv1d,
|
|
16
|
+
Ensure4d,
|
|
17
|
+
MaxNormLinear,
|
|
18
|
+
MaxNormParametrize,
|
|
19
|
+
)
|
|
13
20
|
|
|
14
21
|
|
|
15
22
|
class ATCNet(EEGModuleMixin, nn.Module):
|
|
@@ -213,6 +220,16 @@ class ATCNet(EEGModuleMixin, nn.Module):
|
|
|
213
220
|
max_norm_const : float
|
|
214
221
|
Maximum L2-norm constraint imposed on weights of the last
|
|
215
222
|
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
|
|
216
233
|
|
|
217
234
|
Notes
|
|
218
235
|
-----
|
|
@@ -257,6 +274,7 @@ class ATCNet(EEGModuleMixin, nn.Module):
|
|
|
257
274
|
tcn_activation: type[nn.Module] = nn.ELU,
|
|
258
275
|
concat=False,
|
|
259
276
|
max_norm_const=0.25,
|
|
277
|
+
conv_max_norm_const: Optional[float] = None,
|
|
260
278
|
chs_info=None,
|
|
261
279
|
n_times=None,
|
|
262
280
|
):
|
|
@@ -325,6 +343,7 @@ class ATCNet(EEGModuleMixin, nn.Module):
|
|
|
325
343
|
self.tcn_activation = tcn_activation
|
|
326
344
|
self.concat = concat
|
|
327
345
|
self.max_norm_const = max_norm_const
|
|
346
|
+
self.conv_max_norm_const = conv_max_norm_const
|
|
328
347
|
self.tcn_n_filters = int(self.conv_block_depth_mult * self.conv_block_n_filters)
|
|
329
348
|
map = dict()
|
|
330
349
|
for w in range(self.n_windows):
|
|
@@ -346,6 +365,7 @@ class ATCNet(EEGModuleMixin, nn.Module):
|
|
|
346
365
|
pool_size_2=conv_block_pool_size_2,
|
|
347
366
|
depth_mult=conv_block_depth_mult,
|
|
348
367
|
dropout=conv_block_dropout,
|
|
368
|
+
conv_max_norm=self.conv_max_norm_const,
|
|
349
369
|
)
|
|
350
370
|
|
|
351
371
|
self.F2 = int(conv_block_depth_mult * conv_block_n_filters)
|
|
@@ -375,6 +395,7 @@ class ATCNet(EEGModuleMixin, nn.Module):
|
|
|
375
395
|
dropout=self.tcn_dropout,
|
|
376
396
|
activation=self.tcn_activation,
|
|
377
397
|
dilation=2**i,
|
|
398
|
+
conv_max_norm=self.conv_max_norm_const,
|
|
378
399
|
)
|
|
379
400
|
for i in range(self.tcn_depth)
|
|
380
401
|
]
|
|
@@ -458,6 +479,93 @@ class ATCNet(EEGModuleMixin, nn.Module):
|
|
|
458
479
|
|
|
459
480
|
return self.out_fun(sw_concat_agg)
|
|
460
481
|
|
|
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
|
+
|
|
461
569
|
|
|
462
570
|
class _ConvBlock(nn.Module):
|
|
463
571
|
r"""Convolutional block proposed in ATCNet [1]_, inspired by the EEGNet.
|
|
@@ -487,6 +595,7 @@ class _ConvBlock(nn.Module):
|
|
|
487
595
|
pool_size_2=7,
|
|
488
596
|
depth_mult=2,
|
|
489
597
|
dropout=0.3,
|
|
598
|
+
conv_max_norm: Optional[float] = None,
|
|
490
599
|
):
|
|
491
600
|
super().__init__()
|
|
492
601
|
|
|
@@ -534,6 +643,9 @@ class _ConvBlock(nn.Module):
|
|
|
534
643
|
|
|
535
644
|
self.drop3 = nn.Dropout2d(dropout)
|
|
536
645
|
|
|
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
|
+
|
|
537
649
|
def forward(self, X):
|
|
538
650
|
# ----- Temporal convolution -----
|
|
539
651
|
# Dimension: (batch_size, 1, T, C)
|
|
@@ -662,6 +774,7 @@ class _TCNResidualBlock(nn.Module):
|
|
|
662
774
|
dropout=0.3,
|
|
663
775
|
activation: type[nn.Module] = nn.ELU,
|
|
664
776
|
dilation=1,
|
|
777
|
+
conv_max_norm: Optional[float] = None,
|
|
665
778
|
):
|
|
666
779
|
super().__init__()
|
|
667
780
|
self.activation = activation()
|
|
@@ -706,6 +819,10 @@ class _TCNResidualBlock(nn.Module):
|
|
|
706
819
|
else:
|
|
707
820
|
self.reshaping_conv = nn.Identity()
|
|
708
821
|
|
|
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
|
+
|
|
709
826
|
def forward(self, X):
|
|
710
827
|
# Dimension: (batch_size, F2, Tw)
|
|
711
828
|
# ----- Double dilated convolutions -----
|
|
@@ -9,6 +9,7 @@ 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
|
|
12
13
|
from braindecode.modules import Chomp1d, MaxNormLinear
|
|
13
14
|
|
|
14
15
|
|
|
@@ -33,8 +34,10 @@ class EEGTCNet(EEGModuleMixin, nn.Module):
|
|
|
33
34
|
Number of temporal filters in the first convolutional layer. Default is 8.
|
|
34
35
|
kern_length : int, optional
|
|
35
36
|
Length of the temporal kernel in the first convolutional layer. Default is 64.
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
drop_prob : float, optional
|
|
38
|
+
Default dropout rate, used for both the EEGNet front-end and the TCN
|
|
39
|
+
block unless overridden by ``drop_prob_eeg`` / ``drop_prob_tcn``.
|
|
40
|
+
Default is 0.5.
|
|
38
41
|
depth : int, optional
|
|
39
42
|
Number of residual blocks in the TCN. Default is 2.
|
|
40
43
|
kernel_size : int, optional
|
|
@@ -44,6 +47,20 @@ class EEGTCNet(EEGModuleMixin, nn.Module):
|
|
|
44
47
|
max_norm_const : float
|
|
45
48
|
Maximum L2-norm constraint imposed on weights of the last
|
|
46
49
|
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
|
|
47
64
|
|
|
48
65
|
References
|
|
49
66
|
----------
|
|
@@ -72,6 +89,9 @@ class EEGTCNet(EEGModuleMixin, nn.Module):
|
|
|
72
89
|
kernel_size: int = 4,
|
|
73
90
|
filters: int = 12,
|
|
74
91
|
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,
|
|
75
95
|
):
|
|
76
96
|
super().__init__(
|
|
77
97
|
n_outputs=n_outputs,
|
|
@@ -85,6 +105,11 @@ class EEGTCNet(EEGModuleMixin, nn.Module):
|
|
|
85
105
|
|
|
86
106
|
self.activation = activation
|
|
87
107
|
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
|
|
88
113
|
self.depth_multiplier = depth_multiplier
|
|
89
114
|
self.filter_1 = filter_1
|
|
90
115
|
self.kern_length = kern_length
|
|
@@ -103,7 +128,7 @@ class EEGTCNet(EEGModuleMixin, nn.Module):
|
|
|
103
128
|
filter_1=self.filter_1,
|
|
104
129
|
kern_length=self.kern_length,
|
|
105
130
|
depth_multiplier=self.depth_multiplier,
|
|
106
|
-
drop_prob=self.
|
|
131
|
+
drop_prob=self.drop_prob_eeg,
|
|
107
132
|
activation=self.activation,
|
|
108
133
|
)
|
|
109
134
|
self.arrange_dim_eegnet = Rearrange(
|
|
@@ -116,8 +141,9 @@ class EEGTCNet(EEGModuleMixin, nn.Module):
|
|
|
116
141
|
depth=self.depth,
|
|
117
142
|
kernel_size=self.kernel_size,
|
|
118
143
|
filters=self.filters,
|
|
119
|
-
drop_prob=self.
|
|
144
|
+
drop_prob=self.drop_prob_tcn,
|
|
120
145
|
activation=self.activation,
|
|
146
|
+
batch_norm=self.tcn_batch_norm,
|
|
121
147
|
)
|
|
122
148
|
|
|
123
149
|
# Classification Block
|
|
@@ -127,6 +153,7 @@ class EEGTCNet(EEGModuleMixin, nn.Module):
|
|
|
127
153
|
max_norm_val=self.max_norm_const,
|
|
128
154
|
)
|
|
129
155
|
|
|
156
|
+
@_disable_batch_norm_training_if_batch_size_one
|
|
130
157
|
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
|
131
158
|
"""
|
|
132
159
|
Forward pass of the EEGTCNet model.
|
|
@@ -277,6 +304,7 @@ class _TCNBlock(nn.Module):
|
|
|
277
304
|
filters: int,
|
|
278
305
|
drop_prob: float,
|
|
279
306
|
activation: type[nn.Module] = nn.ELU,
|
|
307
|
+
batch_norm: bool = True,
|
|
280
308
|
):
|
|
281
309
|
super().__init__()
|
|
282
310
|
self.activation = activation()
|
|
@@ -284,10 +312,15 @@ class _TCNBlock(nn.Module):
|
|
|
284
312
|
self.depth = depth
|
|
285
313
|
self.filters = filters
|
|
286
314
|
self.kernel_size = kernel_size
|
|
315
|
+
self.batch_norm = batch_norm
|
|
287
316
|
|
|
288
317
|
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.
|
|
289
322
|
self.downsample = (
|
|
290
|
-
nn.Conv1d(input_dimension, filters, kernel_size=1, bias=
|
|
323
|
+
nn.Conv1d(input_dimension, filters, kernel_size=1, bias=batch_norm)
|
|
291
324
|
if input_dimension != filters
|
|
292
325
|
else None
|
|
293
326
|
)
|
|
@@ -295,32 +328,34 @@ class _TCNBlock(nn.Module):
|
|
|
295
328
|
for i in range(depth):
|
|
296
329
|
dilation = 2**i
|
|
297
330
|
padding = (kernel_size - 1) * dilation
|
|
331
|
+
in_dim = input_dimension if i == 0 else filters
|
|
298
332
|
conv_block = nn.Sequential(
|
|
299
|
-
|
|
300
|
-
|
|
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),
|
|
333
|
+
*self._conv_unit(in_dim, dilation, padding),
|
|
334
|
+
*self._conv_unit(filters, dilation, padding),
|
|
321
335
|
)
|
|
322
336
|
self.layers.append(conv_block)
|
|
323
337
|
|
|
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
|
+
|
|
324
359
|
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
|
325
360
|
# x shape: (batch_size, time_steps, input_dimension)
|
|
326
361
|
x = x.permute(0, 2, 1) # (batch_size, input_dimension, time_steps)
|
|
@@ -183,7 +183,11 @@ class SSTDPN(EEGModuleMixin, nn.Module):
|
|
|
183
183
|
This constraint acts as an implicit force to push features away from the origin. Default is 1.0.
|
|
184
184
|
|
|
185
185
|
proto_cpt_std : float, optional
|
|
186
|
-
Standard deviation for Intra-class Compactness Prototype initialization. Default is 0
|
|
186
|
+
Standard deviation for Intra-class Compactness Prototype initialization. Default is 1.0,
|
|
187
|
+
matching the source ``torch.randn`` initialization.
|
|
188
|
+
|
|
189
|
+
.. versionchanged:: 1.6.1
|
|
190
|
+
Default changed from ``0.01`` to ``1.0`` to match the original implementation.
|
|
187
191
|
|
|
188
192
|
spt_attn_global_context_kernel : int, optional
|
|
189
193
|
Kernel size for global context embedding in Spatial-Spectral Attention module.
|
|
@@ -231,7 +235,7 @@ class SSTDPN(EEGModuleMixin, nn.Module):
|
|
|
231
235
|
mvp_kernel_sizes: Optional[List[int]] = None,
|
|
232
236
|
return_features: bool = False,
|
|
233
237
|
proto_sep_maxnorm: float = 1.0,
|
|
234
|
-
proto_cpt_std: float = 0
|
|
238
|
+
proto_cpt_std: float = 1.0,
|
|
235
239
|
spt_attn_global_context_kernel: int = 250,
|
|
236
240
|
spt_attn_epsilon: float = 1e-5,
|
|
237
241
|
spt_attn_mode: str = "var",
|
|
@@ -327,9 +331,11 @@ class SSTDPN(EEGModuleMixin, nn.Module):
|
|
|
327
331
|
"""
|
|
328
332
|
|
|
329
333
|
features = self.encoder(x) # (b, feat_dim)
|
|
330
|
-
# Renormalize inter-class separation prototypes
|
|
334
|
+
# Renormalize inter-class separation prototypes. ``proto_sep`` has shape
|
|
335
|
+
# (n_outputs, feat_dim); the source constrains each class-row prototype
|
|
336
|
+
# vector (``||s_i|| <= S``), i.e. renorm along dim=0.
|
|
331
337
|
self.proto_sep.data = torch.renorm(
|
|
332
|
-
self.proto_sep.data, p=2, dim=
|
|
338
|
+
self.proto_sep.data, p=2, dim=0, maxnorm=self.proto_sep_maxnorm
|
|
333
339
|
)
|
|
334
340
|
logits = torch.einsum("bd,cd->bc", features, self.proto_sep) # (b, n_outputs)
|
|
335
341
|
logits = self.final_layer(logits)
|
|
@@ -56,4 +56,5 @@ InterpolatedBIOT,"Sleep Staging, Epilepsy",Classification,200,"chs_info, n_outpu
|
|
|
56
56
|
InterpolatedEEGPT,General,Classification,256,"chs_info, n_outputs, n_times",25323137,"InterpolatedEEGPT(chs_info=<user>, n_outputs=4, n_times=1024)","Foundation Model,Attention/Transformer,Channel"
|
|
57
57
|
InterpolatedLaBraM,General,"Classification, Embedding",200,"chs_info, n_outputs, n_times",5866196,"InterpolatedLaBraM(chs_info=<user>, n_outputs=4, n_times=1000)","Convolution,Foundation Model,Channel"
|
|
58
58
|
InterpolatedSignalJEPA,"Motor Imagery, ERP, SSVEP",Embedding,128,"chs_info",3456882,"InterpolatedSignalJEPA(chs_info=<user>)","Convolution,Channel,Foundation Model"
|
|
59
|
+
TCFormer,Motor Imagery,Classification,250,"n_chans, n_outputs, n_times",77820,"TCFormer(n_chans=22, n_outputs=4, n_times=1000)","Convolution,Attention/Transformer"
|
|
59
60
|
EEGDINO,General,Classification,200,"n_chans, n_outputs, n_times",4539698,"EEGDINO(n_chans=19, n_outputs=4, n_times=1000)","Foundation Model,Attention/Transformer"
|