braindecode 1.7.0.dev181261618__tar.gz → 1.7.0.dev182553025__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.7.0.dev181261618/braindecode.egg-info → braindecode-1.7.0.dev182553025}/PKG-INFO +1 -1
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/functional/__init__.py +4 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/functional/functions.py +34 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/__init__.py +2 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/bendr.py +8 -1
- braindecode-1.7.0.dev182553025/braindecode/models/dance.py +368 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/fblightconvnet.py +31 -4
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/summary.csv +1 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/tcn.py +5 -2
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/util.py +22 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/modules/__init__.py +5 -2
- braindecode-1.7.0.dev182553025/braindecode/modules/dance_modules.py +333 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/training/__init__.py +4 -1
- braindecode-1.7.0.dev182553025/braindecode/training/losses.py +284 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/training/scoring.py +39 -0
- braindecode-1.7.0.dev182553025/braindecode/version.py +1 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025/braindecode.egg-info}/PKG-INFO +1 -1
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode.egg-info/SOURCES.txt +2 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/api.rst +2 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/whats_new.rst +28 -0
- braindecode-1.7.0.dev181261618/braindecode/training/losses.py +0 -105
- braindecode-1.7.0.dev181261618/braindecode/version.py +0 -1
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/LICENSE.txt +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/MANIFEST.in +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/NOTICE.txt +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/README.rst +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/__init__.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/augmentation/__init__.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/augmentation/base.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/augmentation/functional.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/augmentation/transforms.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/classifier.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datasets/__init__.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datasets/base.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datasets/bbci.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datasets/bcicomp.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datasets/bids/__init__.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datasets/bids/datasets.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datasets/bids/format.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datasets/bids/hub.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datasets/bids/hub_format.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datasets/bids/hub_io.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datasets/bids/hub_validation.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datasets/bids/iterable.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datasets/chb_mit.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datasets/collate.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datasets/mne.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datasets/moabb.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datasets/nmt.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datasets/registry.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datasets/siena.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datasets/sleep_physio_challe_18.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datasets/sleep_physionet.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datasets/tuh.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datasets/utils.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datasets/xy.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datautil/__init__.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datautil/channel_utils.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datautil/hub_formats.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datautil/serialization.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/datautil/util.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/eegneuralnet.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/functional/initialization.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/atcnet.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/attentionbasenet.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/attn_sleep.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/base.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/biot.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/brainmodule.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/cbramod.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/codebrain.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/config.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/contrawr.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/ctnet.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/deep4.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/deepsleepnet.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/dgcnn.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/eegconformer.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/eegdino.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/eeginception_erp.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/eeginception_mi.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/eegitnet.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/eegminer.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/eegnet.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/eegnex.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/eegpt.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/eegsimpleconv.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/eegsym.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/eegtcnet.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/emg2qwerty.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/fbcnet.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/fbmsnet.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/hybrid.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/ifnet.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/interpolated.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/labram.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/luna.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/medformer.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/meta_neuromotor.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/msvtnet.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/mvpformer.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/patchedtransformer.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/reve.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/sccnet.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/shallow_fbcsp.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/signal_jepa.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/sinc_shallow.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/sleep_stager_blanco_2020.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/sleep_stager_chambon_2018.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/sparcnet.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/sstdpn.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/steegformer.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/syncnet.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/tcformer.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/tidnet.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/tsinception.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/usleep.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/modules/activation.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/modules/attention.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/modules/blocks.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/modules/convolution.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/modules/filter.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/modules/interpolation.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/modules/layers.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/modules/linear.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/modules/parametrization.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/modules/stats.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/modules/util.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/modules/wrapper.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/preprocessing/__init__.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/preprocessing/eegprep_preprocess.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/preprocessing/mne_preprocess.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/preprocessing/preprocess.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/preprocessing/util.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/preprocessing/windowers.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/regressor.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/samplers/__init__.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/samplers/base.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/samplers/ssl.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/training/callbacks.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/util.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/visualization/__init__.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/visualization/attribution.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/visualization/confusion_matrices.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/visualization/frequency.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/visualization/metrics.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/visualization/sanity.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/visualization/topology.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode.egg-info/dependency_links.txt +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode.egg-info/requires.txt +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode.egg-info/top_level.txt +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/Makefile +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/_templates/autosummary/class.rst +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/_templates/autosummary/class_in_subdir.rst +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/_templates/autosummary/function.rst +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/_templates/autosummary/function_in_subdir.rst +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/cite.rst +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/conf.py +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/help.rst +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/index.rst +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/install/install.rst +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/install/install_pip.rst +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/install/install_source.rst +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/models/categorization/attention.rst +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/models/categorization/channel.rst +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/models/categorization/convolution.rst +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/models/categorization/filterbank.rst +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/models/categorization/gnn.rst +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/models/categorization/interpretable.rst +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/models/categorization/lbm.rst +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/models/categorization/recurrent.rst +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/models/categorization/spd.rst +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/models/models.rst +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/models/models_categorization.rst +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/models/models_table.rst +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/models/models_visualization.rst +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/docs/sg_execution_times.rst +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/pyproject.toml +0 -0
- {braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/setup.cfg +0 -0
{braindecode-1.7.0.dev181261618/braindecode.egg-info → braindecode-1.7.0.dev182553025}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: braindecode
|
|
3
|
-
Version: 1.7.0.
|
|
3
|
+
Version: 1.7.0.dev182553025
|
|
4
4
|
Summary: Deep learning software to decode EEG, ECG or MEG signals
|
|
5
5
|
Author-email: Robin Tibor Schirrmeister <robintibor@gmail.com>, Bruno Aristimunha Pinto <b.aristimunha@gmail.com>, Alexandre Gramfort <agramfort@meta.com>
|
|
6
6
|
Maintainer-email: Alexandre Gramfort <agramfort@meta.com>, Bruno Aristimunha Pinto <b.aristimunha@gmail.com>, Robin Tibor Schirrmeister <robintibor@gmail.com>
|
{braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/functional/__init__.py
RENAMED
|
@@ -5,6 +5,8 @@ from .functions import (
|
|
|
5
5
|
dwt_max_level,
|
|
6
6
|
hilbert_freq,
|
|
7
7
|
identity,
|
|
8
|
+
iou_1d,
|
|
9
|
+
pairwise_iou_1d,
|
|
8
10
|
plv_time,
|
|
9
11
|
safe_log,
|
|
10
12
|
sinusoidal_positional_encoding,
|
|
@@ -20,6 +22,8 @@ __all__ = [
|
|
|
20
22
|
"dwt_max_level",
|
|
21
23
|
"hilbert_freq",
|
|
22
24
|
"identity",
|
|
25
|
+
"iou_1d",
|
|
26
|
+
"pairwise_iou_1d",
|
|
23
27
|
"plv_time",
|
|
24
28
|
"safe_log",
|
|
25
29
|
"sinusoidal_positional_encoding",
|
|
@@ -260,6 +260,40 @@ def plv_time(
|
|
|
260
260
|
return plv_matrix
|
|
261
261
|
|
|
262
262
|
|
|
263
|
+
# -----------------------------------------------------------------------------
|
|
264
|
+
# DANCE functional helpers
|
|
265
|
+
#
|
|
266
|
+
# Authors: Bruno Aristimunha <b.aristimunha@gmail.com>
|
|
267
|
+
#
|
|
268
|
+
# License: MIT
|
|
269
|
+
#
|
|
270
|
+
# Ported from the DANCE event-detection model (facebookresearch/dance, MIT).
|
|
271
|
+
# -----------------------------------------------------------------------------
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def iou_1d(s1, e1, s2, e2, eps: float = 1e-7):
|
|
275
|
+
"""ELEMENTWISE 1-D temporal IoU. All four inputs share the same shape S
|
|
276
|
+
(e.g. ``(B, Q)``); returns IoU of shape S. Used by ``DanceLoss`` on the
|
|
277
|
+
matched ``(B, Q)`` spans. For (Q,)x(T,) pairwise IoU use ``pairwise_iou_1d``.
|
|
278
|
+
"""
|
|
279
|
+
inter = (torch.minimum(e1, e2) - torch.maximum(s1, s2)).clamp(min=0)
|
|
280
|
+
union = (e1 - s1) + (e2 - s2) - inter
|
|
281
|
+
return inter / (union + eps)
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def pairwise_iou_1d(s1, e1, s2, e2, eps: float = 1e-7):
|
|
285
|
+
"""PAIRWISE 1-D temporal IoU. ``s1,e1`` shape ``(Q,)``, ``s2,e2`` shape
|
|
286
|
+
``(T,)``; returns ``(Q, T)`` (broadcast ``[:, None]`` x ``[None, :]``).
|
|
287
|
+
Transcribed from ``dance/matcher.py:33-39`` (``_pairwise_iou``). Used by
|
|
288
|
+
``HungarianMatcher`` to build the ``(Q, n_targets)`` cost matrix.
|
|
289
|
+
"""
|
|
290
|
+
inter_start = torch.maximum(s1[:, None], s2[None, :])
|
|
291
|
+
inter_end = torch.minimum(e1[:, None], e2[None, :])
|
|
292
|
+
inter = (inter_end - inter_start).clamp(min=0)
|
|
293
|
+
union = (e1 - s1)[:, None] + (e2 - s2)[None, :] - inter
|
|
294
|
+
return inter / (union + eps)
|
|
295
|
+
|
|
296
|
+
|
|
263
297
|
def daubechies_filters(n_vanishing: int) -> torch.Tensor:
|
|
264
298
|
r"""Daubechies ``db<n_vanishing>`` wavelet decomposition filters.
|
|
265
299
|
|
{braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/__init__.py
RENAMED
|
@@ -11,6 +11,7 @@ from .cbramod import CBraMod
|
|
|
11
11
|
from .codebrain import CodeBrain
|
|
12
12
|
from .contrawr import ContraWR
|
|
13
13
|
from .ctnet import CTNet
|
|
14
|
+
from .dance import DANCE
|
|
14
15
|
from .deep4 import Deep4Net
|
|
15
16
|
from .deepsleepnet import DeepSleepNet
|
|
16
17
|
from .dgcnn import DGCNN
|
|
@@ -86,6 +87,7 @@ __all__ = [
|
|
|
86
87
|
"CodeBrain",
|
|
87
88
|
"ContraWR",
|
|
88
89
|
"CTNet",
|
|
90
|
+
"DANCE",
|
|
89
91
|
"Deep4Net",
|
|
90
92
|
"DeepSleepNet",
|
|
91
93
|
"BrainModule",
|
{braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/bendr.py
RENAMED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
# Authors: Bruno Aristimunha <b.aristimunha@gmail.com>
|
|
2
|
+
# Sarthak Tayal <sarthaktayal2@gmail.com>
|
|
3
|
+
#
|
|
4
|
+
# License: BSD (3-clause)
|
|
5
|
+
|
|
1
6
|
import copy
|
|
2
7
|
|
|
3
8
|
import numpy as np
|
|
@@ -435,7 +440,9 @@ class _ConvEncoderBENDR(nn.Module):
|
|
|
435
440
|
padding=width
|
|
436
441
|
// 2, # Correct padding for 'same' output length before stride
|
|
437
442
|
),
|
|
438
|
-
|
|
443
|
+
# channel-wise dropout (matches paper specification), on
|
|
444
|
+
# (batch, channels, times) activations
|
|
445
|
+
nn.Dropout1d(dropout),
|
|
439
446
|
nn.GroupNorm(
|
|
440
447
|
encoder_h // 2, encoder_h
|
|
441
448
|
), # Consider making num_groups configurable or ensure encoder_h is divisible by 2
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
# Authors: Bruno Aristimunha <b.aristimunha@gmail.com>
|
|
2
|
+
# Meta Platforms, Inc. and affiliates (original DANCE)
|
|
3
|
+
#
|
|
4
|
+
# License: MIT
|
|
5
|
+
# Adapted from https://github.com/facebookresearch/dance (MIT).
|
|
6
|
+
"""``DANCE``: detect-and-classify EEG events (DETR for 1-D EEG)."""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import warnings
|
|
11
|
+
|
|
12
|
+
import torch
|
|
13
|
+
from torch import nn
|
|
14
|
+
|
|
15
|
+
from braindecode.models.base import EEGModuleMixin
|
|
16
|
+
from braindecode.models.util import (
|
|
17
|
+
_disable_batch_norm_training_if_batch_size_one, # decorates ``forward``
|
|
18
|
+
)
|
|
19
|
+
from braindecode.models.util import has_valid_locations as _has_valid_locations
|
|
20
|
+
from braindecode.models.util import positions_from_chs_info as _positions_from_chs_info
|
|
21
|
+
from braindecode.modules import ChannelMerger, Perceiver, SimpleConv
|
|
22
|
+
from braindecode.modules.dance_modules import DanceDetrDecoder
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class DANCE(EEGModuleMixin, nn.Module):
|
|
26
|
+
r"""DANCE from Lévy et al (2026) [dance]_.
|
|
27
|
+
|
|
28
|
+
:bdg-success:`Convolution` :bdg-info:`Attention/Transformer` :bdg-dark-line:`Channel`
|
|
29
|
+
|
|
30
|
+
DANCE frames EEG decoding as event *set prediction*: a long, unaligned
|
|
31
|
+
window is mapped to a set of events ``(t_start, t_end, class)`` with
|
|
32
|
+
normalized ``[0, 1]`` spans -- DETR for 1-D EEG.
|
|
33
|
+
|
|
34
|
+
.. rubric:: Architecture Overview
|
|
35
|
+
|
|
36
|
+
``ChannelMerger`` (spatial Fourier attention over electrode positions) ->
|
|
37
|
+
``SimpleConv`` (dilated conv stack) -> ``Perceiver`` (cross-attention to a
|
|
38
|
+
fixed 256-latent grid) -> a dense head (``forward`` output) and a DETR
|
|
39
|
+
cross-attention decoder (``detect`` output).
|
|
40
|
+
|
|
41
|
+
.. rubric:: Macro Components
|
|
42
|
+
|
|
43
|
+
``DANCE.conv.merger`` (Spatial ChannelMerger)
|
|
44
|
+
**Operations.** :class:`~braindecode.modules.ChannelMerger` Fourier-embeds
|
|
45
|
+
each electrode's ``(x, y)`` position (:class:`~braindecode.modules.FourierEmb`)
|
|
46
|
+
and computes ``n_virtual_channels`` softmax-attention combinations of the
|
|
47
|
+
input channels, mapping ``(B, n_chans, T) -> (B, n_virtual_channels, T)``.
|
|
48
|
+
Nested inside ``self.conv`` (matching upstream); disabled (``None``) when
|
|
49
|
+
``chs_info`` has no usable locations. Controlled by ``merger_drop_prob``.
|
|
50
|
+
**Role.** Makes the model montage-agnostic by projecting any electrode
|
|
51
|
+
layout onto a fixed virtual-channel basis.
|
|
52
|
+
|
|
53
|
+
``DANCE.conv`` (SimpleConv dilated front-end)
|
|
54
|
+
**Operations.** :class:`~braindecode.modules.SimpleConv` runs the nested
|
|
55
|
+
merger, a ``1x1`` ``initial_linear`` projection, then ``conv_depth``
|
|
56
|
+
residual dilated ``Conv1d`` blocks (``nn.ReLU``, dilation accumulating as
|
|
57
|
+
``int(dilation * conv_dilation_growth)`` per block, same-padding preserves
|
|
58
|
+
``T``), mapping ``-> (B, embed_dim, T)``.
|
|
59
|
+
**Role.** Builds the temporal feature representation (Défossez lineage).
|
|
60
|
+
|
|
61
|
+
``DANCE.perceiver`` (Perceiver bottleneck)
|
|
62
|
+
**Operations.** :class:`~braindecode.modules.Perceiver` Fourier-encodes the
|
|
63
|
+
time axis, then cross-attends a fixed ``num_latents``-token learnable grid to
|
|
64
|
+
the conv features over ``perceiver_depth`` blocks, mapping
|
|
65
|
+
``(B, T, embed_dim) -> (B, num_latents, embed_dim)``.
|
|
66
|
+
**Role.** Makes the model length-agnostic (any ``T`` -> ``num_latents``
|
|
67
|
+
tokens) and forms the detection time-grid (``num_latents / duration``
|
|
68
|
+
tokens/s).
|
|
69
|
+
|
|
70
|
+
``DANCE.decoder`` (DETR cross-attention decoder)
|
|
71
|
+
**Operations.** ``DanceDetrDecoder`` projects the latents to
|
|
72
|
+
``decoder_dim``, then ``decoder_depth`` self-/cross-attention layers update
|
|
73
|
+
``n_queries`` learnable event queries; per-query heads emit class logits and
|
|
74
|
+
sigmoid ``start``/``end`` spans. Used only by :meth:`detect` (not
|
|
75
|
+
:meth:`forward`).
|
|
76
|
+
**Role.** Produces the event-set prediction ``{class, start, end}``.
|
|
77
|
+
|
|
78
|
+
``DANCE.final_layer`` (dense per-token head)
|
|
79
|
+
**Operations.** ``nn.Linear(embed_dim, n_outputs)`` applied to every latent
|
|
80
|
+
token, mapping ``(B, num_latents, embed_dim) -> (B, num_latents, n_outputs)``.
|
|
81
|
+
**Role.** The :meth:`forward` output (dense per-token class logits) and the
|
|
82
|
+
``dense`` term consumed by the consistency loss.
|
|
83
|
+
|
|
84
|
+
.. rubric:: Temporal, Spatial, and Spectral Encoding
|
|
85
|
+
|
|
86
|
+
Temporal context comes from the dilated conv stack; spatial structure from
|
|
87
|
+
the Fourier-position channel merge; the Perceiver fourier-encodes the time
|
|
88
|
+
axis before cross-attention.
|
|
89
|
+
|
|
90
|
+
.. rubric:: Additional Mechanisms
|
|
91
|
+
|
|
92
|
+
The DETR decoder uses learnable event queries and emits per-query class
|
|
93
|
+
logits plus sigmoid start/end spans. The dense head provides per-token
|
|
94
|
+
class logits used as ``forward``'s output and for the consistency loss.
|
|
95
|
+
|
|
96
|
+
.. versionadded:: 1.6.1
|
|
97
|
+
|
|
98
|
+
Parameters
|
|
99
|
+
----------
|
|
100
|
+
n_queries : int, optional
|
|
101
|
+
Number of learnable event queries. The default is ``100``.
|
|
102
|
+
use_channel_merger : bool, optional
|
|
103
|
+
Enable the spatial Fourier ChannelMerger. Auto-disabled if ``chs_info``
|
|
104
|
+
has no usable electrode locations. The default is ``True``.
|
|
105
|
+
n_virtual_channels : int, optional
|
|
106
|
+
Merger output channels. The default is ``270``.
|
|
107
|
+
fourier_emb_dim : int, optional
|
|
108
|
+
Fourier position embedding dim. The default is ``2048``.
|
|
109
|
+
merger_drop_prob : float, optional
|
|
110
|
+
Spatial dropout of the ChannelMerger ONLY (``self.conv.merger``);
|
|
111
|
+
bans whole channels within a random radius during training. The
|
|
112
|
+
default is ``0.2``.
|
|
113
|
+
embed_dim : int, optional
|
|
114
|
+
Conv/Perceiver feature dim. The default is ``128``.
|
|
115
|
+
conv_hidden : int, optional
|
|
116
|
+
SimpleConv hidden width. The default is ``512``.
|
|
117
|
+
conv_depth : int, optional
|
|
118
|
+
Number of dilated conv blocks. The default is ``10``.
|
|
119
|
+
conv_kernel_size : int, optional
|
|
120
|
+
Conv kernel size. The default is ``9``.
|
|
121
|
+
conv_dilation_growth : float, optional
|
|
122
|
+
Per-block dilation growth. The default is ``2.5``.
|
|
123
|
+
conv_initial_linear : int, optional
|
|
124
|
+
1x1 projection width. The default is ``256``.
|
|
125
|
+
conv_initial_depth : int, optional
|
|
126
|
+
Number of 1x1 projections. The default is ``1``.
|
|
127
|
+
conv_drop_prob : float, optional
|
|
128
|
+
Conv-block dropout knob, exposed for API symmetry. NOTE: the verified
|
|
129
|
+
DANCE config has NO conv dropout, so this maps to no upstream weights
|
|
130
|
+
and does not affect parity; kept for forward-compatibility. The
|
|
131
|
+
default is ``0.2`` (the paper value).
|
|
132
|
+
num_latents : int, optional
|
|
133
|
+
Perceiver latent count (detection token grid). The default is ``256``.
|
|
134
|
+
perceiver_depth : int, optional
|
|
135
|
+
Perceiver cross-attn blocks. The default is ``6``.
|
|
136
|
+
cross_attn_heads : int, optional
|
|
137
|
+
Perceiver cross-attn heads. The default is ``2``.
|
|
138
|
+
latent_attn_heads : int, optional
|
|
139
|
+
Perceiver self-attn heads. The default is ``2``.
|
|
140
|
+
cross_dim_head : int, optional
|
|
141
|
+
Perceiver cross-attn head dim. The default is ``64``.
|
|
142
|
+
latent_dim_head : int, optional
|
|
143
|
+
Perceiver self-attn head dim. The default is ``64``.
|
|
144
|
+
max_freq : float, optional
|
|
145
|
+
Perceiver fourier max frequency. The default is ``10.0``.
|
|
146
|
+
num_freq_bands : int, optional
|
|
147
|
+
Perceiver fourier bands. The default is ``6``.
|
|
148
|
+
decoder_dim : int, optional
|
|
149
|
+
DETR decoder dim. The default is ``256``.
|
|
150
|
+
decoder_depth : int, optional
|
|
151
|
+
DETR decoder layers. The default is ``4``.
|
|
152
|
+
decoder_heads : int, optional
|
|
153
|
+
DETR decoder heads. The default is ``4``.
|
|
154
|
+
activation : type[nn.Module], optional
|
|
155
|
+
Accepted for interface symmetry but currently INERT: it is forwarded to
|
|
156
|
+
``self.decoder`` yet the decoder feed-forward hardwires GEGLU
|
|
157
|
+
(:class:`~braindecode.modules.dance_modules._FeedForward`), and the
|
|
158
|
+
``SimpleConv`` front-end hardcodes ``nn.ReLU`` to match upstream. No
|
|
159
|
+
submodule reads it today. The default is ``nn.GELU``.
|
|
160
|
+
drop_prob : float, optional
|
|
161
|
+
Dropout applied to the raw input (``self.input_drop``) and inside the
|
|
162
|
+
DETR decoder (``self.decoder``). Does NOT touch the merger (use
|
|
163
|
+
``merger_drop_prob``) or the conv stack (no conv dropout upstream).
|
|
164
|
+
The default is ``0.1``.
|
|
165
|
+
|
|
166
|
+
References
|
|
167
|
+
----------
|
|
168
|
+
.. [dance] Lévy, Banville, Rapin, King, Moreau, d'Ascoli (2026). DANCE:
|
|
169
|
+
Detect and Classify Events in EEG. arXiv:2605.10688.
|
|
170
|
+
.. [defossez2023] Défossez et al. (2023). Decoding speech from
|
|
171
|
+
non-invasive brain recordings.
|
|
172
|
+
.. [perceiver2021] Jaegle et al. (2021). Perceiver: General perception
|
|
173
|
+
with iterative attention.
|
|
174
|
+
.. [detr2020] Carion et al. (2020). End-to-end object detection with
|
|
175
|
+
transformers.
|
|
176
|
+
"""
|
|
177
|
+
|
|
178
|
+
def __init__(
|
|
179
|
+
self,
|
|
180
|
+
n_outputs=None,
|
|
181
|
+
n_chans=None,
|
|
182
|
+
chs_info=None,
|
|
183
|
+
n_times=None,
|
|
184
|
+
input_window_seconds=None,
|
|
185
|
+
sfreq=None,
|
|
186
|
+
*,
|
|
187
|
+
n_queries: int = 100,
|
|
188
|
+
use_channel_merger: bool = True,
|
|
189
|
+
n_virtual_channels: int = 270,
|
|
190
|
+
fourier_emb_dim: int = 2048,
|
|
191
|
+
merger_drop_prob: float = 0.2,
|
|
192
|
+
embed_dim: int = 128,
|
|
193
|
+
conv_hidden: int = 512,
|
|
194
|
+
conv_depth: int = 10,
|
|
195
|
+
conv_kernel_size: int = 9,
|
|
196
|
+
conv_dilation_growth: float = 2.5,
|
|
197
|
+
conv_initial_linear: int = 256,
|
|
198
|
+
conv_initial_depth: int = 1,
|
|
199
|
+
conv_drop_prob: float = 0.2,
|
|
200
|
+
num_latents: int = 256,
|
|
201
|
+
perceiver_depth: int = 6,
|
|
202
|
+
cross_attn_heads: int = 2,
|
|
203
|
+
latent_attn_heads: int = 2,
|
|
204
|
+
cross_dim_head: int = 64,
|
|
205
|
+
latent_dim_head: int = 64,
|
|
206
|
+
max_freq: float = 10.0,
|
|
207
|
+
num_freq_bands: int = 6,
|
|
208
|
+
decoder_dim: int = 256,
|
|
209
|
+
decoder_depth: int = 4,
|
|
210
|
+
decoder_heads: int = 4,
|
|
211
|
+
activation: type[nn.Module] = nn.GELU,
|
|
212
|
+
drop_prob: float = 0.1,
|
|
213
|
+
):
|
|
214
|
+
super().__init__(
|
|
215
|
+
n_outputs=n_outputs,
|
|
216
|
+
n_chans=n_chans,
|
|
217
|
+
chs_info=chs_info,
|
|
218
|
+
n_times=n_times,
|
|
219
|
+
input_window_seconds=input_window_seconds,
|
|
220
|
+
sfreq=sfreq,
|
|
221
|
+
)
|
|
222
|
+
del n_outputs, n_chans, sfreq, n_times, input_window_seconds, chs_info
|
|
223
|
+
|
|
224
|
+
self.num_latents = num_latents
|
|
225
|
+
self.n_queries = n_queries
|
|
226
|
+
self.embed_dim = embed_dim
|
|
227
|
+
|
|
228
|
+
# Decide the merger up front (fall back to no-merger if no locations).
|
|
229
|
+
if use_channel_merger and not _has_valid_locations(self.chs_info):
|
|
230
|
+
warnings.warn(
|
|
231
|
+
"DANCE: chs_info has no usable electrode locations "
|
|
232
|
+
"('loc' missing or all-zero); disabling the ChannelMerger "
|
|
233
|
+
"(use_channel_merger=False).",
|
|
234
|
+
UserWarning,
|
|
235
|
+
)
|
|
236
|
+
use_channel_merger = False
|
|
237
|
+
# Public flag mirroring the fallback decision (``self.conv.merger`` is the
|
|
238
|
+
# source of truth in forward); kept for introspection/tests.
|
|
239
|
+
self.use_channel_merger = use_channel_merger
|
|
240
|
+
|
|
241
|
+
# The merger is NESTED INSIDE SimpleConv (self.conv.merger), matching
|
|
242
|
+
# upstream SimpleConvModel's call path and state_dict layout. There is
|
|
243
|
+
# NO top-level self.channel_merger. The (n_chans, 2) positions buffer is
|
|
244
|
+
# derived from chs_info and broadcast in forward; subject_ids is always
|
|
245
|
+
# None (braindecode has no subjects; per_subject=False).
|
|
246
|
+
merger = None
|
|
247
|
+
if use_channel_merger:
|
|
248
|
+
positions = _positions_from_chs_info(self.chs_info)
|
|
249
|
+
self.register_buffer(
|
|
250
|
+
"channel_positions",
|
|
251
|
+
torch.as_tensor(positions, dtype=torch.float32),
|
|
252
|
+
persistent=False,
|
|
253
|
+
)
|
|
254
|
+
merger = ChannelMerger(
|
|
255
|
+
out_channels=n_virtual_channels,
|
|
256
|
+
pos_dim=fourier_emb_dim,
|
|
257
|
+
dropout=merger_drop_prob,
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
self.input_drop = nn.Dropout(drop_prob)
|
|
261
|
+
self.conv = SimpleConv(
|
|
262
|
+
in_channels=self.n_chans,
|
|
263
|
+
out_channels=embed_dim,
|
|
264
|
+
hidden=conv_hidden,
|
|
265
|
+
depth=conv_depth,
|
|
266
|
+
kernel_size=conv_kernel_size,
|
|
267
|
+
dilation_growth=conv_dilation_growth,
|
|
268
|
+
initial_linear=conv_initial_linear,
|
|
269
|
+
initial_depth=conv_initial_depth,
|
|
270
|
+
drop_prob=conv_drop_prob,
|
|
271
|
+
activation=nn.ReLU,
|
|
272
|
+
merger=merger,
|
|
273
|
+
)
|
|
274
|
+
# The conv stack is SAME-padded, so it preserves length for any T >= 1;
|
|
275
|
+
# the dilated receptive field is not an input-length requirement. The
|
|
276
|
+
# genuine minimum is one first-block kernel (dilation 1), so the guard
|
|
277
|
+
# uses ``conv_kernel_size`` rather than the full receptive field.
|
|
278
|
+
self._min_n_times = conv_kernel_size
|
|
279
|
+
self.perceiver = Perceiver(
|
|
280
|
+
input_dim=embed_dim,
|
|
281
|
+
num_latents=num_latents,
|
|
282
|
+
latent_dim=embed_dim,
|
|
283
|
+
depth=perceiver_depth,
|
|
284
|
+
cross_heads=cross_attn_heads,
|
|
285
|
+
latent_heads=latent_attn_heads,
|
|
286
|
+
cross_dim_head=cross_dim_head,
|
|
287
|
+
latent_dim_head=latent_dim_head,
|
|
288
|
+
max_freq=max_freq,
|
|
289
|
+
num_freq_bands=num_freq_bands,
|
|
290
|
+
)
|
|
291
|
+
self.decoder = DanceDetrDecoder(
|
|
292
|
+
input_dim=embed_dim,
|
|
293
|
+
dim=decoder_dim,
|
|
294
|
+
depth=decoder_depth,
|
|
295
|
+
heads=decoder_heads,
|
|
296
|
+
n_queries=n_queries,
|
|
297
|
+
n_outputs=self.n_outputs,
|
|
298
|
+
drop_prob=drop_prob,
|
|
299
|
+
activation=activation,
|
|
300
|
+
)
|
|
301
|
+
# final_layer LAST so it lands in the last two named_children(); init
|
|
302
|
+
# weights AFTER it exists so the dense head gets the custom init too.
|
|
303
|
+
self.final_layer = nn.Linear(embed_dim, self.n_outputs)
|
|
304
|
+
self.apply(self._init_weights)
|
|
305
|
+
|
|
306
|
+
@staticmethod
|
|
307
|
+
def _init_weights(module: nn.Module) -> None:
|
|
308
|
+
if isinstance(module, nn.Linear):
|
|
309
|
+
nn.init.trunc_normal_(module.weight, std=0.02)
|
|
310
|
+
if module.bias is not None:
|
|
311
|
+
nn.init.zeros_(module.bias)
|
|
312
|
+
elif isinstance(module, nn.LayerNorm):
|
|
313
|
+
nn.init.ones_(module.weight)
|
|
314
|
+
nn.init.zeros_(module.bias)
|
|
315
|
+
|
|
316
|
+
def _encode(self, x: torch.Tensor) -> torch.Tensor:
|
|
317
|
+
if x.ndim != 3 or x.shape[-2] != self.n_chans:
|
|
318
|
+
raise ValueError(
|
|
319
|
+
f"expected (batch, {self.n_chans}, T) input; got {tuple(x.shape)}."
|
|
320
|
+
)
|
|
321
|
+
if x.shape[-1] < self._min_n_times:
|
|
322
|
+
raise ValueError(
|
|
323
|
+
f"n_times={x.shape[-1]} is shorter than the minimum input "
|
|
324
|
+
f"length ({self._min_n_times} samples = one conv kernel)."
|
|
325
|
+
)
|
|
326
|
+
x = self.input_drop(x)
|
|
327
|
+
# The merger is nested inside self.conv; pass positions through it.
|
|
328
|
+
# subject_ids is always None (braindecode has no subjects).
|
|
329
|
+
if self.conv.merger is not None:
|
|
330
|
+
pos = self.channel_positions.unsqueeze(0).expand(x.size(0), -1, -1)
|
|
331
|
+
x = self.conv(x, positions=pos) # merger -> initial_linear -> blocks
|
|
332
|
+
else:
|
|
333
|
+
x = self.conv(x) # (B, embed_dim, T)
|
|
334
|
+
x = x.transpose(2, 1) # (B, T, embed_dim)
|
|
335
|
+
x = self.perceiver(x) # (B, num_latents, embed_dim)
|
|
336
|
+
return x
|
|
337
|
+
|
|
338
|
+
@_disable_batch_norm_training_if_batch_size_one
|
|
339
|
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
|
340
|
+
latents = self._encode(x) # (B, num_latents, embed_dim)
|
|
341
|
+
return self.final_layer(latents) # (B, num_latents, n_outputs)
|
|
342
|
+
|
|
343
|
+
@_disable_batch_norm_training_if_batch_size_one
|
|
344
|
+
def detect(self, x: torch.Tensor) -> dict:
|
|
345
|
+
latents = self._encode(x) # (B, num_latents, embed_dim)
|
|
346
|
+
events = self.decoder(latents) # {class, start, end}
|
|
347
|
+
events["dense"] = self.final_layer(latents) # (B, num_latents, n_outputs)
|
|
348
|
+
return events
|
|
349
|
+
|
|
350
|
+
def reset_head(self, n_outputs: int) -> None:
|
|
351
|
+
"""Replace the dense head and the DETR class head for a new ``n_outputs``."""
|
|
352
|
+
if n_outputs <= 0:
|
|
353
|
+
raise ValueError(f"n_outputs must be positive; got {n_outputs}.")
|
|
354
|
+
old = self.final_layer
|
|
355
|
+
self.final_layer = nn.Linear(old.in_features, n_outputs).to(
|
|
356
|
+
device=old.weight.device, dtype=old.weight.dtype
|
|
357
|
+
)
|
|
358
|
+
ch = self.decoder.class_head
|
|
359
|
+
self.decoder.class_head = nn.Linear(ch.in_features, n_outputs).to(
|
|
360
|
+
device=ch.weight.device, dtype=ch.weight.dtype
|
|
361
|
+
)
|
|
362
|
+
self._n_outputs = n_outputs
|
|
363
|
+
init_kwargs = getattr(self, "_braindecode_init_kwargs", None)
|
|
364
|
+
if init_kwargs is not None and "n_outputs" in init_kwargs:
|
|
365
|
+
init_kwargs["n_outputs"] = n_outputs
|
|
366
|
+
hub_config = getattr(self, "_hub_mixin_config", None)
|
|
367
|
+
if hub_config is not None and "n_outputs" in hub_config:
|
|
368
|
+
hub_config["n_outputs"] = n_outputs
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
# Authors: Sarthak Tayal <sarthaktayal2@gmail.com>
|
|
2
|
+
#
|
|
3
|
+
# License: BSD-3
|
|
4
|
+
|
|
1
5
|
from __future__ import annotations
|
|
2
6
|
|
|
3
7
|
from typing import Optional
|
|
@@ -61,15 +65,18 @@ class FBLightConvNet(EEGModuleMixin, nn.Module):
|
|
|
61
65
|
|
|
62
66
|
Parameters
|
|
63
67
|
----------
|
|
64
|
-
n_bands : int or None or list of tuple of int, default=
|
|
68
|
+
n_bands : int or None or list of tuple of int, default=9
|
|
65
69
|
Number of frequency bands or a list of frequency band tuples. If a list of tuples is provided,
|
|
66
70
|
each tuple defines the lower and upper bounds of a frequency band.
|
|
67
71
|
n_filters_spat : int, default=32
|
|
68
72
|
Number of spatial filters in the depthwise convolutional layer.
|
|
69
73
|
n_dim : int, default=3
|
|
70
74
|
Number of dimensions for the temporal reduction layer.
|
|
71
|
-
|
|
72
|
-
|
|
75
|
+
win_len : int, default=250
|
|
76
|
+
Length in samples of the non-overlapping temporal windows the signal is
|
|
77
|
+
split into before the variance based feature extraction. The number of
|
|
78
|
+
windows passed to the attention module is ``n_times // win_len``, so
|
|
79
|
+
``n_times`` has to be at least ``win_len``.
|
|
73
80
|
activation : nn.Module, default=nn.ELU
|
|
74
81
|
Activation function class to apply after convolutional layers.
|
|
75
82
|
verbose : bool, default=False
|
|
@@ -82,6 +89,9 @@ class FBLightConvNet(EEGModuleMixin, nn.Module):
|
|
|
82
89
|
If True, applies softmax to the attention weights.
|
|
83
90
|
bias : bool, default=False
|
|
84
91
|
If True, includes a bias term in the convolutional layers.
|
|
92
|
+
stride_factor : int or None, default=None
|
|
93
|
+
Deprecated and ignored, it will be removed in a future release. The
|
|
94
|
+
temporal segmentation of this model is controlled by ``win_len``.
|
|
85
95
|
|
|
86
96
|
References
|
|
87
97
|
----------
|
|
@@ -106,7 +116,7 @@ class FBLightConvNet(EEGModuleMixin, nn.Module):
|
|
|
106
116
|
n_bands=9,
|
|
107
117
|
n_filters_spat: int = 32,
|
|
108
118
|
n_dim: int = 3,
|
|
109
|
-
stride_factor: int =
|
|
119
|
+
stride_factor: Optional[int] = None,
|
|
110
120
|
win_len: int = 250,
|
|
111
121
|
heads: int = 8,
|
|
112
122
|
weight_softmax: bool = True,
|
|
@@ -125,6 +135,14 @@ class FBLightConvNet(EEGModuleMixin, nn.Module):
|
|
|
125
135
|
)
|
|
126
136
|
del n_outputs, n_chans, chs_info, n_times, input_window_seconds, sfreq
|
|
127
137
|
|
|
138
|
+
if stride_factor is not None:
|
|
139
|
+
warn(
|
|
140
|
+
"The parameter `stride_factor` is deprecated and ignored, it "
|
|
141
|
+
"will be removed in a future release. The temporal "
|
|
142
|
+
"segmentation of FBLightConvNet is set by `win_len`.",
|
|
143
|
+
DeprecationWarning,
|
|
144
|
+
)
|
|
145
|
+
|
|
128
146
|
# Parameters
|
|
129
147
|
self.n_bands = n_bands
|
|
130
148
|
self.n_filters_spat = n_filters_spat
|
|
@@ -138,6 +156,13 @@ class FBLightConvNet(EEGModuleMixin, nn.Module):
|
|
|
138
156
|
self.filter_parameters = filter_parameters or {}
|
|
139
157
|
|
|
140
158
|
# Checkers
|
|
159
|
+
if self.n_times < self.win_len:
|
|
160
|
+
raise ValueError(
|
|
161
|
+
f"Time dimension ({self.n_times}) is shorter than win_len "
|
|
162
|
+
f"({self.win_len}), so the model cannot build a single "
|
|
163
|
+
f"temporal window. Pass a longer input or lower `win_len`."
|
|
164
|
+
)
|
|
165
|
+
|
|
141
166
|
self.n_times_truncated = self.n_times
|
|
142
167
|
if self.n_times % self.win_len != 0:
|
|
143
168
|
warn(
|
|
@@ -194,10 +219,12 @@ class FBLightConvNet(EEGModuleMixin, nn.Module):
|
|
|
194
219
|
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
|
195
220
|
"""
|
|
196
221
|
Forward pass of the FBLightConvNet model.
|
|
222
|
+
|
|
197
223
|
Parameters
|
|
198
224
|
----------
|
|
199
225
|
x : torch.Tensor
|
|
200
226
|
Input tensor with shape (batch_size, n_chans, n_times).
|
|
227
|
+
|
|
201
228
|
Returns
|
|
202
229
|
-------
|
|
203
230
|
torch.Tensor
|
{braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/summary.csv
RENAMED
|
@@ -58,5 +58,6 @@ InterpolatedLaBraM,General,"Prediction, Embedding",200,"chs_info, n_outputs, n_t
|
|
|
58
58
|
InterpolatedSignalJEPA,"Motor Imagery, ERP, SSVEP",Embedding,128,"chs_info",3456882,"InterpolatedSignalJEPA(chs_info=<user>)","Convolution,Channel,Foundation Model",EEG
|
|
59
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",EEG
|
|
60
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",EEG
|
|
61
|
+
DANCE,General,Event Detection,200,"n_chans, n_outputs, n_times, sfreq, chs_info",29813542,"DANCE(n_chans=19, n_outputs=4, n_times=6400, sfreq=200, input_window_seconds=32.0, chs_info=[{'ch_name': f'E{i+1}', 'kind': 'eeg', 'loc': numpy.random.default_rng(2024).random(12)} for i in range(19)])","Convolution,Attention/Transformer,Channel",EEG
|
|
61
62
|
STEEGFormer,General,Classification,250,"n_chans, n_outputs, n_times",25305604,"STEEGFormer(n_chans=22, n_outputs=4, n_times=1000)","Attention/Transformer,Foundation Model",EEG
|
|
62
63
|
MVPFormer,General,"Prediction, Embedding",512,"n_chans, n_outputs, n_times, sfreq",3356978,"MVPFormer(n_chans=22, n_outputs=4, n_times=2000, sfreq=100)","Foundation Model,Attention/Transformer",EEG
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# Authors: Patryk Chrabaszcz
|
|
2
2
|
# Lukas Gemein <l.gemein@gmail.com>
|
|
3
|
+
# Sarthak Tayal <sarthaktayal2@gmail.com>
|
|
3
4
|
#
|
|
4
5
|
# License: BSD-3
|
|
5
6
|
import torch
|
|
@@ -236,7 +237,9 @@ class _TemporalBlock(nn.Module):
|
|
|
236
237
|
)
|
|
237
238
|
self.chomp1 = Chomp1d(padding)
|
|
238
239
|
self.relu1 = activation()
|
|
239
|
-
|
|
240
|
+
# activations are (batch, channels, times), dropout2d only masks
|
|
241
|
+
# channel-wise there through a deprecated fallback
|
|
242
|
+
self.dropout1 = nn.Dropout1d(drop_prob)
|
|
240
243
|
|
|
241
244
|
self.conv2 = weight_norm(
|
|
242
245
|
nn.Conv1d(
|
|
@@ -250,7 +253,7 @@ class _TemporalBlock(nn.Module):
|
|
|
250
253
|
)
|
|
251
254
|
self.chomp2 = Chomp1d(padding)
|
|
252
255
|
self.relu2 = activation()
|
|
253
|
-
self.dropout2 = nn.
|
|
256
|
+
self.dropout2 = nn.Dropout1d(drop_prob)
|
|
254
257
|
|
|
255
258
|
self.downsample = (
|
|
256
259
|
nn.Conv1d(n_inputs, n_outputs, 1) if n_inputs != n_outputs else None
|
{braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/models/util.py
RENAMED
|
@@ -484,6 +484,25 @@ models_mandatory_parameters: list[
|
|
|
484
484
|
),
|
|
485
485
|
("DGCNN", ["n_chans", "n_outputs", "n_times", "chs_info"], None),
|
|
486
486
|
("EEGDINO", ["n_chans", "n_outputs", "n_times"], None),
|
|
487
|
+
(
|
|
488
|
+
"DANCE",
|
|
489
|
+
["n_outputs", "n_chans", "n_times", "sfreq", "chs_info"],
|
|
490
|
+
{
|
|
491
|
+
"n_chans": 19,
|
|
492
|
+
"n_times": 6400, # 32 s @ 200 Hz, above the depth-10 stack minimum
|
|
493
|
+
"sfreq": 200.0,
|
|
494
|
+
"input_window_seconds": 32.0,
|
|
495
|
+
"n_outputs": 4,
|
|
496
|
+
"chs_info": [
|
|
497
|
+
{
|
|
498
|
+
"ch_name": f"E{i + 1}",
|
|
499
|
+
"kind": "eeg",
|
|
500
|
+
"loc": _rng.random(12),
|
|
501
|
+
}
|
|
502
|
+
for i in range(19)
|
|
503
|
+
],
|
|
504
|
+
},
|
|
505
|
+
),
|
|
487
506
|
]
|
|
488
507
|
|
|
489
508
|
################################################################
|
|
@@ -498,6 +517,9 @@ non_classification_models = [
|
|
|
498
517
|
# Emits a (batch, T_out, vocab) sequence for CTC, not class logits.
|
|
499
518
|
"MetaNeuromotorHand",
|
|
500
519
|
"EMG2QwertyNet",
|
|
520
|
+
# forward returns (batch, num_latents, n_outputs) dense per-token logits,
|
|
521
|
+
# not class logits.
|
|
522
|
+
"DANCE",
|
|
501
523
|
]
|
|
502
524
|
|
|
503
525
|
################################################################
|
{braindecode-1.7.0.dev181261618 → braindecode-1.7.0.dev182553025}/braindecode/modules/__init__.py
RENAMED
|
@@ -23,6 +23,7 @@ from .convolution import (
|
|
|
23
23
|
Conv2dWithConstraint,
|
|
24
24
|
DepthwiseConv2d,
|
|
25
25
|
)
|
|
26
|
+
from .dance_modules import Perceiver, SimpleConv
|
|
26
27
|
from .filter import FilterBankLayer, GeneralizedGaussianFilter
|
|
27
28
|
from .interpolation import ChannelInterpolationLayer
|
|
28
29
|
from .layers import (
|
|
@@ -78,6 +79,10 @@ __all__ = [
|
|
|
78
79
|
"Conv1dWithConstraint",
|
|
79
80
|
"Conv2dWithConstraint",
|
|
80
81
|
"DepthwiseConv2d",
|
|
82
|
+
"ChannelMerger",
|
|
83
|
+
"FourierEmb",
|
|
84
|
+
"Perceiver",
|
|
85
|
+
"SimpleConv",
|
|
81
86
|
"FilterBankLayer",
|
|
82
87
|
"GeneralizedGaussianFilter",
|
|
83
88
|
"Chomp1d",
|
|
@@ -88,8 +93,6 @@ __all__ = [
|
|
|
88
93
|
"TimeDistributed",
|
|
89
94
|
"LinearWithConstraint",
|
|
90
95
|
"MaxNormLinear",
|
|
91
|
-
"ChannelMerger",
|
|
92
|
-
"FourierEmb",
|
|
93
96
|
"MaxNorm",
|
|
94
97
|
"MaxNormParametrize",
|
|
95
98
|
"LogPowerLayer",
|