Braindecode 1.7.0__tar.gz → 1.7.0.dev174519142__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/braindecode.egg-info → braindecode-1.7.0.dev174519142}/PKG-INFO +1 -1
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/classifier.py +7 -7
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/functional/__init__.py +0 -4
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/functional/functions.py +2 -39
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/__init__.py +0 -2
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/bendr.py +1 -8
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/eegminer.py +62 -38
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/summary.csv +0 -1
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/tcn.py +2 -5
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/util.py +0 -22
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/modules/__init__.py +2 -5
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/modules/filter.py +10 -16
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/regressor.py +7 -7
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/training/__init__.py +1 -4
- braindecode-1.7.0.dev174519142/braindecode/training/losses.py +105 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/training/scoring.py +5 -46
- braindecode-1.7.0.dev174519142/braindecode/version.py +1 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142/braindecode.egg-info}/PKG-INFO +1 -1
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode.egg-info/SOURCES.txt +0 -2
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/api.rst +0 -2
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/whats_new.rst +1 -26
- braindecode-1.7.0/braindecode/models/dance.py +0 -368
- braindecode-1.7.0/braindecode/modules/dance_modules.py +0 -333
- braindecode-1.7.0/braindecode/training/losses.py +0 -284
- braindecode-1.7.0/braindecode/version.py +0 -1
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/LICENSE.txt +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/MANIFEST.in +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/NOTICE.txt +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/README.rst +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/__init__.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/augmentation/__init__.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/augmentation/base.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/augmentation/functional.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/augmentation/transforms.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datasets/__init__.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datasets/base.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datasets/bbci.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datasets/bcicomp.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datasets/bids/__init__.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datasets/bids/datasets.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datasets/bids/format.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datasets/bids/hub.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datasets/bids/hub_format.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datasets/bids/hub_io.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datasets/bids/hub_validation.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datasets/bids/iterable.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datasets/chb_mit.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datasets/collate.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datasets/mne.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datasets/moabb.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datasets/nmt.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datasets/registry.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datasets/siena.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datasets/sleep_physio_challe_18.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datasets/sleep_physionet.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datasets/tuh.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datasets/utils.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datasets/xy.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datautil/__init__.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datautil/channel_utils.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datautil/hub_formats.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datautil/serialization.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/datautil/util.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/eegneuralnet.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/functional/initialization.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/atcnet.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/attentionbasenet.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/attn_sleep.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/base.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/biot.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/brainmodule.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/cbramod.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/codebrain.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/config.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/contrawr.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/ctnet.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/deep4.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/deepsleepnet.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/dgcnn.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/eegconformer.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/eegdino.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/eeginception_erp.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/eeginception_mi.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/eegitnet.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/eegnet.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/eegnex.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/eegpt.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/eegsimpleconv.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/eegsym.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/eegtcnet.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/emg2qwerty.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/fbcnet.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/fblightconvnet.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/fbmsnet.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/hybrid.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/ifnet.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/interpolated.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/labram.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/luna.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/medformer.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/meta_neuromotor.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/msvtnet.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/mvpformer.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/patchedtransformer.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/reve.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/sccnet.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/shallow_fbcsp.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/signal_jepa.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/sinc_shallow.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/sleep_stager_blanco_2020.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/sleep_stager_chambon_2018.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/sparcnet.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/sstdpn.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/steegformer.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/syncnet.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/tcformer.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/tidnet.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/tsinception.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/models/usleep.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/modules/activation.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/modules/attention.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/modules/blocks.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/modules/convolution.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/modules/interpolation.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/modules/layers.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/modules/linear.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/modules/parametrization.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/modules/stats.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/modules/util.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/modules/wrapper.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/preprocessing/__init__.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/preprocessing/eegprep_preprocess.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/preprocessing/mne_preprocess.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/preprocessing/preprocess.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/preprocessing/util.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/preprocessing/windowers.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/samplers/__init__.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/samplers/base.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/samplers/ssl.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/training/callbacks.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/util.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/visualization/__init__.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/visualization/attribution.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/visualization/confusion_matrices.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/visualization/frequency.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/visualization/metrics.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/visualization/sanity.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode/visualization/topology.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode.egg-info/dependency_links.txt +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode.egg-info/requires.txt +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/braindecode.egg-info/top_level.txt +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/Makefile +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/_templates/autosummary/class.rst +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/_templates/autosummary/class_in_subdir.rst +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/_templates/autosummary/function.rst +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/_templates/autosummary/function_in_subdir.rst +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/cite.rst +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/conf.py +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/help.rst +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/index.rst +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/install/install.rst +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/install/install_pip.rst +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/install/install_source.rst +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/models/categorization/attention.rst +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/models/categorization/channel.rst +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/models/categorization/convolution.rst +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/models/categorization/filterbank.rst +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/models/categorization/gnn.rst +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/models/categorization/interpretable.rst +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/models/categorization/lbm.rst +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/models/categorization/recurrent.rst +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/models/categorization/spd.rst +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/models/models.rst +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/models/models_categorization.rst +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/models/models_table.rst +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/models/models_visualization.rst +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/docs/sg_execution_times.rst +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/pyproject.toml +0 -0
- {braindecode-1.7.0 → braindecode-1.7.0.dev174519142}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: braindecode
|
|
3
|
-
Version: 1.7.0
|
|
3
|
+
Version: 1.7.0.dev174519142
|
|
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>
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
# Lukas Gemein <l.gemein@gmail.com>
|
|
4
4
|
# Bruno Aristimunha <b.aristimunha@gmail.com>
|
|
5
5
|
# Pierre Guetschel <pierre.guetschel@gmail.com>
|
|
6
|
-
# Sarthak Tayal <sarthaktayal2@gmail.com>
|
|
7
6
|
#
|
|
8
7
|
# License: BSD (3-clause)
|
|
9
8
|
|
|
@@ -196,7 +195,9 @@ class EEGClassifier(_EEGNeuralNet, NeuralNetClassifier):
|
|
|
196
195
|
return self.predict_proba(X).argmax(1)
|
|
197
196
|
|
|
198
197
|
def predict_trials(self, X, return_targets=True):
|
|
199
|
-
"""Create trialwise predictions
|
|
198
|
+
"""Create trialwise predictions and optionally also return trialwise.
|
|
199
|
+
|
|
200
|
+
labels from cropped dataset.
|
|
200
201
|
|
|
201
202
|
Parameters
|
|
202
203
|
----------
|
|
@@ -211,11 +212,10 @@ class EEGClassifier(_EEGNeuralNet, NeuralNetClassifier):
|
|
|
211
212
|
3-dimensional array (n_trials x n_classes x n_predictions), where
|
|
212
213
|
the number of predictions depend on the chosen window size and the
|
|
213
214
|
receptive field of the network.
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
either a single value, multiple values, or a sequence.
|
|
215
|
+
trial_labels : np.ndarray
|
|
216
|
+
2-dimensional array (n_trials x n_targets) where the number of
|
|
217
|
+
targets depends on the decoding paradigm and can be either a single
|
|
218
|
+
value, multiple values, or a sequence.
|
|
219
219
|
"""
|
|
220
220
|
if not self.cropped:
|
|
221
221
|
warnings.warn(
|
|
@@ -5,8 +5,6 @@ from .functions import (
|
|
|
5
5
|
dwt_max_level,
|
|
6
6
|
hilbert_freq,
|
|
7
7
|
identity,
|
|
8
|
-
iou_1d,
|
|
9
|
-
pairwise_iou_1d,
|
|
10
8
|
plv_time,
|
|
11
9
|
safe_log,
|
|
12
10
|
sinusoidal_positional_encoding,
|
|
@@ -22,8 +20,6 @@ __all__ = [
|
|
|
22
20
|
"dwt_max_level",
|
|
23
21
|
"hilbert_freq",
|
|
24
22
|
"identity",
|
|
25
|
-
"iou_1d",
|
|
26
|
-
"pairwise_iou_1d",
|
|
27
23
|
"plv_time",
|
|
28
24
|
"safe_log",
|
|
29
25
|
"sinusoidal_positional_encoding",
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# Authors: Robin Schirrmeister <robintibor@gmail.com>
|
|
2
2
|
# Bruno Aristimunha <b.aristimunha@gmail.com>
|
|
3
|
-
# Sarthak Tayal <sarthaktayal2@gmail.com>
|
|
4
3
|
#
|
|
5
4
|
# License: BSD (3-clause)
|
|
6
5
|
|
|
@@ -110,7 +109,7 @@ def _get_gaussian_kernel1d(kernel_size: int, sigma: float) -> torch.Tensor:
|
|
|
110
109
|
return kernel1d
|
|
111
110
|
|
|
112
111
|
|
|
113
|
-
def hilbert_freq(x
|
|
112
|
+
def hilbert_freq(x, forward_fourier=True):
|
|
114
113
|
r"""
|
|
115
114
|
Compute the Hilbert transform using PyTorch, separating the real and
|
|
116
115
|
imaginary parts.
|
|
@@ -179,9 +178,7 @@ def hilbert_freq(x: torch.Tensor, forward_fourier: bool = True) -> torch.Tensor:
|
|
|
179
178
|
return x
|
|
180
179
|
|
|
181
180
|
|
|
182
|
-
def plv_time(
|
|
183
|
-
x: torch.Tensor, forward_fourier: bool = True, epsilon: float = 1e-6
|
|
184
|
-
) -> torch.Tensor:
|
|
181
|
+
def plv_time(x, forward_fourier=True, epsilon: float = 1e-6):
|
|
185
182
|
"""Compute the Phase Locking Value (PLV) metric in the time domain.
|
|
186
183
|
|
|
187
184
|
The Phase Locking Value (PLV) is a measure of the synchronization between
|
|
@@ -260,40 +257,6 @@ def plv_time(
|
|
|
260
257
|
return plv_matrix
|
|
261
258
|
|
|
262
259
|
|
|
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
|
-
|
|
297
260
|
def daubechies_filters(n_vanishing: int) -> torch.Tensor:
|
|
298
261
|
r"""Daubechies ``db<n_vanishing>`` wavelet decomposition filters.
|
|
299
262
|
|
|
@@ -11,7 +11,6 @@ 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
|
|
15
14
|
from .deep4 import Deep4Net
|
|
16
15
|
from .deepsleepnet import DeepSleepNet
|
|
17
16
|
from .dgcnn import DGCNN
|
|
@@ -87,7 +86,6 @@ __all__ = [
|
|
|
87
86
|
"CodeBrain",
|
|
88
87
|
"ContraWR",
|
|
89
88
|
"CTNet",
|
|
90
|
-
"DANCE",
|
|
91
89
|
"Deep4Net",
|
|
92
90
|
"DeepSleepNet",
|
|
93
91
|
"BrainModule",
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
# Authors: Bruno Aristimunha <b.aristimunha@gmail.com>
|
|
2
|
-
# Sarthak Tayal <sarthaktayal2@gmail.com>
|
|
3
|
-
#
|
|
4
|
-
# License: BSD (3-clause)
|
|
5
|
-
|
|
6
1
|
import copy
|
|
7
2
|
|
|
8
3
|
import numpy as np
|
|
@@ -440,9 +435,7 @@ class _ConvEncoderBENDR(nn.Module):
|
|
|
440
435
|
padding=width
|
|
441
436
|
// 2, # Correct padding for 'same' output length before stride
|
|
442
437
|
),
|
|
443
|
-
#
|
|
444
|
-
# (batch, channels, times) activations
|
|
445
|
-
nn.Dropout1d(dropout),
|
|
438
|
+
nn.Dropout2d(dropout), # 2D dropout (matches paper specification)
|
|
446
439
|
nn.GroupNorm(
|
|
447
440
|
encoder_h // 2, encoder_h
|
|
448
441
|
), # Consider making num_groups configurable or ensure encoder_h is divisible by 2
|
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
* https://www.ipo.gov.uk/p-ipsum/Case/ApplicationNumber/GB2113420.0
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
from functools import partial
|
|
9
9
|
|
|
10
10
|
import torch
|
|
11
|
+
from einops.layers.torch import Rearrange
|
|
11
12
|
from torch import nn
|
|
12
13
|
|
|
13
14
|
import braindecode.functional as F
|
|
@@ -18,36 +19,6 @@ from braindecode.modules import GeneralizedGaussianFilter
|
|
|
18
19
|
_eeg_miner_methods = ["mag", "corr", "plv"]
|
|
19
20
|
|
|
20
21
|
|
|
21
|
-
class _EEGMinerFeatures(nn.Module):
|
|
22
|
-
def __init__(self, method, n_chans, n_filters, n_times):
|
|
23
|
-
super().__init__()
|
|
24
|
-
self.method = method
|
|
25
|
-
self.n_chans = n_chans
|
|
26
|
-
self.n_filters = n_filters
|
|
27
|
-
self.n_times = n_times
|
|
28
|
-
triu = torch.triu_indices(n_chans, n_chans, 1)
|
|
29
|
-
self.register_buffer("triu_row", triu[0], persistent=False)
|
|
30
|
-
self.register_buffer("triu_col", triu[1], persistent=False)
|
|
31
|
-
|
|
32
|
-
def forward(self, x):
|
|
33
|
-
if self.method == "mag":
|
|
34
|
-
return torch.sqrt((x * x).mean(dim=-1))
|
|
35
|
-
if self.method == "corr":
|
|
36
|
-
x = x.reshape(
|
|
37
|
-
x.shape[0], self.n_chans, self.n_filters, self.n_times
|
|
38
|
-
).transpose(-3, -2)
|
|
39
|
-
x = (x - x.mean(dim=-1, keepdim=True)) / torch.sqrt(
|
|
40
|
-
x.var(dim=-1, keepdim=True) + 1e-6
|
|
41
|
-
)
|
|
42
|
-
x = torch.matmul(x, x.transpose(-2, -1)) / x.shape[-1]
|
|
43
|
-
x = x.permute(0, 2, 3, 1).abs()
|
|
44
|
-
else:
|
|
45
|
-
x = x.transpose(-4, -3)
|
|
46
|
-
x = F.plv_time(x, forward_fourier=False)
|
|
47
|
-
x = x.permute(0, 2, 3, 1)
|
|
48
|
-
return x[:, self.triu_row, self.triu_col, :]
|
|
49
|
-
|
|
50
|
-
|
|
51
22
|
class EEGMiner(EEGModuleMixin, nn.Module):
|
|
52
23
|
r"""EEGMiner from Ludwig et al (2024) [eegminer]_.
|
|
53
24
|
|
|
@@ -197,18 +168,24 @@ class EEGMiner(EEGModuleMixin, nn.Module):
|
|
|
197
168
|
)
|
|
198
169
|
|
|
199
170
|
# Forward method
|
|
200
|
-
self.ensure_dim = nn.Identity()
|
|
201
171
|
if self.method == "mag":
|
|
172
|
+
self.method_forward = self._apply_mag_forward
|
|
202
173
|
self.n_features = self.n_chans * self.n_filters
|
|
174
|
+
self.ensure_dim = nn.Identity()
|
|
203
175
|
elif self.method == "corr":
|
|
176
|
+
self.method_forward = partial(
|
|
177
|
+
self._apply_corr_forward,
|
|
178
|
+
n_chans=self.n_chans,
|
|
179
|
+
n_filters=self.n_filters,
|
|
180
|
+
n_times=self.n_times,
|
|
181
|
+
)
|
|
204
182
|
self.n_features = self.n_filters * self.n_chans * (self.n_chans - 1) // 2
|
|
183
|
+
self.ensure_dim = nn.Identity()
|
|
205
184
|
elif self.method == "plv":
|
|
206
|
-
self.
|
|
185
|
+
self.method_forward = partial(self._apply_plv, n_chans=self.n_chans)
|
|
186
|
+
self.ensure_dim = Rearrange("... d -> ... 1 d")
|
|
207
187
|
self.n_features = (self.n_filters * self.n_chans * (self.n_chans - 1)) // 2
|
|
208
188
|
|
|
209
|
-
self.feature_layer = _EEGMinerFeatures(
|
|
210
|
-
self.method, self.n_chans, self.n_filters, self.n_times
|
|
211
|
-
)
|
|
212
189
|
self.flatten_layer = nn.Flatten()
|
|
213
190
|
# Classifier
|
|
214
191
|
self.batch_layer = nn.BatchNorm1d(self.n_features, affine=False)
|
|
@@ -218,17 +195,64 @@ class EEGMiner(EEGModuleMixin, nn.Module):
|
|
|
218
195
|
@_disable_batch_norm_training_if_batch_size_one
|
|
219
196
|
def forward(self, x):
|
|
220
197
|
"""x: (batch, electrodes, time)"""
|
|
198
|
+
batch = x.shape[0]
|
|
221
199
|
x = self.ensure_dim(x)
|
|
222
200
|
# Apply Gaussian filters in frequency domain
|
|
223
201
|
# x -> (batch, electrodes * filters, time)
|
|
224
202
|
x = self.filter(x)
|
|
225
203
|
|
|
226
|
-
x = self.
|
|
204
|
+
x = self.method_forward(x=x, batch=batch)
|
|
227
205
|
# Classifier
|
|
228
206
|
# Note that the order of dimensions before flattening the feature vector is important
|
|
229
207
|
# for attributing feature weights during interpretation.
|
|
230
|
-
x = x.reshape(
|
|
208
|
+
x = x.reshape(batch, self.n_features)
|
|
231
209
|
x = self.batch_layer(x)
|
|
232
210
|
x = self.final_layer(x)
|
|
233
211
|
|
|
234
212
|
return x
|
|
213
|
+
|
|
214
|
+
@staticmethod
|
|
215
|
+
def _apply_mag_forward(x, batch=None):
|
|
216
|
+
# Signal magnitude
|
|
217
|
+
x = x * x
|
|
218
|
+
x = x.mean(dim=-1)
|
|
219
|
+
x = torch.sqrt(x)
|
|
220
|
+
return x
|
|
221
|
+
|
|
222
|
+
@staticmethod
|
|
223
|
+
def _apply_corr_forward(
|
|
224
|
+
x, batch, n_chans, n_filters, n_times, epilson: float = 1e-6
|
|
225
|
+
):
|
|
226
|
+
x = x.reshape(batch, n_chans, n_filters, n_times).transpose(-3, -2)
|
|
227
|
+
x = (x - x.mean(dim=-1, keepdim=True)) / torch.sqrt(
|
|
228
|
+
x.var(dim=-1, keepdim=True) + epilson
|
|
229
|
+
)
|
|
230
|
+
x = torch.matmul(x, x.transpose(-2, -1)) / x.shape[-1]
|
|
231
|
+
# Original tensor shape: [batch, n_filters, chans, chans]
|
|
232
|
+
x = x.permute(0, 2, 3, 1)
|
|
233
|
+
# New tensor shape: [batch, chans, chans, n_filters]
|
|
234
|
+
# move filter channels to the end
|
|
235
|
+
x = x.abs()
|
|
236
|
+
|
|
237
|
+
# Get upper triu of symmetric connectivity matrix
|
|
238
|
+
triu = torch.triu_indices(n_chans, n_chans, 1)
|
|
239
|
+
x = x[:, triu[0], triu[1], :]
|
|
240
|
+
|
|
241
|
+
return x
|
|
242
|
+
|
|
243
|
+
@staticmethod
|
|
244
|
+
def _apply_plv(x, n_chans, batch=None):
|
|
245
|
+
# Compute PLV connectivity
|
|
246
|
+
# x -> (batch, electrodes, electrodes, filters)
|
|
247
|
+
x = x.transpose(-4, -3) # swap electrodes and filters
|
|
248
|
+
# adjusting to compute the plv
|
|
249
|
+
x = F.plv_time(x, forward_fourier=False)
|
|
250
|
+
# batch, number of filters, connectivity matrix
|
|
251
|
+
# [batch, n_filters, chans, chans]
|
|
252
|
+
x = x.permute(0, 2, 3, 1)
|
|
253
|
+
# [batch, chans, chans, n_filters]
|
|
254
|
+
|
|
255
|
+
# Get upper triu of symmetric connectivity matrix
|
|
256
|
+
triu = torch.triu_indices(n_chans, n_chans, 1)
|
|
257
|
+
x = x[:, triu[0], triu[1], :]
|
|
258
|
+
return x
|
|
@@ -58,6 +58,5 @@ 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
|
|
62
61
|
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
|
|
63
62
|
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,6 +1,5 @@
|
|
|
1
1
|
# Authors: Patryk Chrabaszcz
|
|
2
2
|
# Lukas Gemein <l.gemein@gmail.com>
|
|
3
|
-
# Sarthak Tayal <sarthaktayal2@gmail.com>
|
|
4
3
|
#
|
|
5
4
|
# License: BSD-3
|
|
6
5
|
import torch
|
|
@@ -237,9 +236,7 @@ class _TemporalBlock(nn.Module):
|
|
|
237
236
|
)
|
|
238
237
|
self.chomp1 = Chomp1d(padding)
|
|
239
238
|
self.relu1 = activation()
|
|
240
|
-
|
|
241
|
-
# channel-wise there through a deprecated fallback
|
|
242
|
-
self.dropout1 = nn.Dropout1d(drop_prob)
|
|
239
|
+
self.dropout1 = nn.Dropout2d(drop_prob)
|
|
243
240
|
|
|
244
241
|
self.conv2 = weight_norm(
|
|
245
242
|
nn.Conv1d(
|
|
@@ -253,7 +250,7 @@ class _TemporalBlock(nn.Module):
|
|
|
253
250
|
)
|
|
254
251
|
self.chomp2 = Chomp1d(padding)
|
|
255
252
|
self.relu2 = activation()
|
|
256
|
-
self.dropout2 = nn.
|
|
253
|
+
self.dropout2 = nn.Dropout2d(drop_prob)
|
|
257
254
|
|
|
258
255
|
self.downsample = (
|
|
259
256
|
nn.Conv1d(n_inputs, n_outputs, 1) if n_inputs != n_outputs else None
|
|
@@ -484,25 +484,6 @@ 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
|
-
),
|
|
506
487
|
]
|
|
507
488
|
|
|
508
489
|
################################################################
|
|
@@ -517,9 +498,6 @@ non_classification_models = [
|
|
|
517
498
|
# Emits a (batch, T_out, vocab) sequence for CTC, not class logits.
|
|
518
499
|
"MetaNeuromotorHand",
|
|
519
500
|
"EMG2QwertyNet",
|
|
520
|
-
# forward returns (batch, num_latents, n_outputs) dense per-token logits,
|
|
521
|
-
# not class logits.
|
|
522
|
-
"DANCE",
|
|
523
501
|
]
|
|
524
502
|
|
|
525
503
|
################################################################
|
|
@@ -23,7 +23,6 @@ from .convolution import (
|
|
|
23
23
|
Conv2dWithConstraint,
|
|
24
24
|
DepthwiseConv2d,
|
|
25
25
|
)
|
|
26
|
-
from .dance_modules import Perceiver, SimpleConv
|
|
27
26
|
from .filter import FilterBankLayer, GeneralizedGaussianFilter
|
|
28
27
|
from .interpolation import ChannelInterpolationLayer
|
|
29
28
|
from .layers import (
|
|
@@ -79,10 +78,6 @@ __all__ = [
|
|
|
79
78
|
"Conv1dWithConstraint",
|
|
80
79
|
"Conv2dWithConstraint",
|
|
81
80
|
"DepthwiseConv2d",
|
|
82
|
-
"ChannelMerger",
|
|
83
|
-
"FourierEmb",
|
|
84
|
-
"Perceiver",
|
|
85
|
-
"SimpleConv",
|
|
86
81
|
"FilterBankLayer",
|
|
87
82
|
"GeneralizedGaussianFilter",
|
|
88
83
|
"Chomp1d",
|
|
@@ -93,6 +88,8 @@ __all__ = [
|
|
|
93
88
|
"TimeDistributed",
|
|
94
89
|
"LinearWithConstraint",
|
|
95
90
|
"MaxNormLinear",
|
|
91
|
+
"ChannelMerger",
|
|
92
|
+
"FourierEmb",
|
|
96
93
|
"MaxNorm",
|
|
97
94
|
"MaxNormParametrize",
|
|
98
95
|
"LogPowerLayer",
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
# Authors: Sarthak Tayal <sarthaktayal2@gmail.com>
|
|
2
|
-
#
|
|
3
|
-
# License: BSD-3
|
|
4
|
-
|
|
5
1
|
from __future__ import annotations
|
|
6
2
|
|
|
7
3
|
from typing import Optional
|
|
@@ -641,22 +637,20 @@ class GeneralizedGaussianFilter(nn.Module):
|
|
|
641
637
|
The constructed filters with shape `(out_channels, freq_bins, 2)`.
|
|
642
638
|
|
|
643
639
|
"""
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
self.
|
|
640
|
+
# Clamp parameters
|
|
641
|
+
self.f_mean.data = torch.clamp(
|
|
642
|
+
self.f_mean.data,
|
|
643
|
+
min=self.clamp_f_mean[0] / (self.sample_rate / 2),
|
|
644
|
+
max=self.clamp_f_mean[1] / (self.sample_rate / 2),
|
|
649
645
|
)
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
self.bandwidth.data = bandwidth
|
|
655
|
-
self.shape.data = shape
|
|
646
|
+
self.bandwidth.data = torch.clamp(
|
|
647
|
+
self.bandwidth.data, min=1.0 / (self.sample_rate / 2), max=1.0
|
|
648
|
+
)
|
|
649
|
+
self.shape.data = torch.clamp(self.shape.data, min=2.0, max=3.0)
|
|
656
650
|
|
|
657
651
|
# Create magnitude response with gain=1 -> (channels, freqs)
|
|
658
652
|
mag_response = self.exponential_power(
|
|
659
|
-
self.n_range, f_mean, bandwidth, shape * 8 - 14
|
|
653
|
+
self.n_range, self.f_mean, self.bandwidth, self.shape * 8 - 14
|
|
660
654
|
)
|
|
661
655
|
mag_response = mag_response / mag_response.max(dim=-1, keepdim=True)[0]
|
|
662
656
|
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
# Lukas Gemein <l.gemein@gmail.com>
|
|
4
4
|
# Bruno Aristimunha <b.aristimunha@gmail.com>
|
|
5
5
|
# Pierre Guetschel <pierre.guetschel@gmail.com>
|
|
6
|
-
# Sarthak Tayal <sarthaktayal2@gmail.com>
|
|
7
6
|
#
|
|
8
7
|
# License: BSD (3-clause)
|
|
9
8
|
|
|
@@ -140,7 +139,9 @@ class EEGRegressor(_EEGNeuralNet, NeuralNetRegressor):
|
|
|
140
139
|
return y_pred
|
|
141
140
|
|
|
142
141
|
def predict_trials(self, X, return_targets=True):
|
|
143
|
-
"""Create trialwise predictions
|
|
142
|
+
"""Create trialwise predictions and optionally also return trialwise.
|
|
143
|
+
|
|
144
|
+
labels from cropped dataset.
|
|
144
145
|
|
|
145
146
|
Parameters
|
|
146
147
|
----------
|
|
@@ -155,11 +156,10 @@ class EEGRegressor(_EEGNeuralNet, NeuralNetRegressor):
|
|
|
155
156
|
3-dimensional array (n_trials x n_classes x n_predictions), where
|
|
156
157
|
the number of predictions depend on the chosen window size and the
|
|
157
158
|
receptive field of the network.
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
either a single value, multiple values, or a sequence.
|
|
159
|
+
trial_labels : np.ndarray
|
|
160
|
+
2-dimensional array (n_trials x n_targets) where the number of
|
|
161
|
+
targets depends on the decoding paradigm and can be either a single
|
|
162
|
+
value, multiple values, or a sequence.
|
|
163
163
|
"""
|
|
164
164
|
if not self.cropped:
|
|
165
165
|
warnings.warn(
|
|
@@ -2,19 +2,17 @@
|
|
|
2
2
|
Functionality for skorch-based training.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from .losses import CroppedLoss,
|
|
5
|
+
from .losses import CroppedLoss, TimeSeriesLoss, mixup_criterion
|
|
6
6
|
from .scoring import (
|
|
7
7
|
CroppedTimeSeriesEpochScoring,
|
|
8
8
|
CroppedTrialEpochScoring,
|
|
9
9
|
PostEpochTrainScoring,
|
|
10
|
-
f1_event,
|
|
11
10
|
predict_trials,
|
|
12
11
|
trial_preds_from_window_preds,
|
|
13
12
|
)
|
|
14
13
|
|
|
15
14
|
__all__ = [
|
|
16
15
|
"CroppedLoss",
|
|
17
|
-
"DanceLoss",
|
|
18
16
|
"mixup_criterion",
|
|
19
17
|
"TimeSeriesLoss",
|
|
20
18
|
"CroppedTrialEpochScoring",
|
|
@@ -22,5 +20,4 @@ __all__ = [
|
|
|
22
20
|
"CroppedTimeSeriesEpochScoring",
|
|
23
21
|
"trial_preds_from_window_preds",
|
|
24
22
|
"predict_trials",
|
|
25
|
-
"f1_event",
|
|
26
23
|
]
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Authors: Robin Schirrmeister <robintibor@gmail.com>
|
|
2
|
+
# Maciej Sliwowski <maciek.sliwowski@gmail.com>
|
|
3
|
+
# Mohammed Fattouh <mo.fattouh@gmail.com>
|
|
4
|
+
#
|
|
5
|
+
# License: BSD (3-clause)
|
|
6
|
+
|
|
7
|
+
import torch
|
|
8
|
+
from torch import nn
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class CroppedLoss(nn.Module):
|
|
12
|
+
"""Compute Loss after averaging predictions across time.
|
|
13
|
+
Assumes predictions are in shape:
|
|
14
|
+
n_batch size x n_classes x n_predictions (in time)"""
|
|
15
|
+
|
|
16
|
+
def __init__(self, loss_function):
|
|
17
|
+
super().__init__()
|
|
18
|
+
self.loss_function = loss_function
|
|
19
|
+
|
|
20
|
+
def forward(self, preds, targets):
|
|
21
|
+
"""Forward pass.
|
|
22
|
+
|
|
23
|
+
Parameters
|
|
24
|
+
----------
|
|
25
|
+
preds: torch.Tensor
|
|
26
|
+
Model's prediction with shape (batch_size, n_classes, n_times).
|
|
27
|
+
targets: torch.Tensor
|
|
28
|
+
Target labels with shape (batch_size, n_classes, n_times).
|
|
29
|
+
"""
|
|
30
|
+
avg_preds = torch.mean(preds, dim=2)
|
|
31
|
+
avg_preds = avg_preds.squeeze(dim=1)
|
|
32
|
+
return self.loss_function(avg_preds, targets)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class TimeSeriesLoss(nn.Module):
|
|
36
|
+
"""Compute Loss between timeseries targets and predictions.
|
|
37
|
+
Assumes predictions are in shape:
|
|
38
|
+
n_batch size x n_classes x n_predictions (in time)
|
|
39
|
+
Assumes targets are in shape:
|
|
40
|
+
n_batch size x n_classes x window_len (in time)
|
|
41
|
+
If the targets contain NaNs, the NaNs will be masked out and the loss will be only computed for
|
|
42
|
+
predictions valid corresponding to valid target values."""
|
|
43
|
+
|
|
44
|
+
def __init__(self, loss_function):
|
|
45
|
+
super().__init__()
|
|
46
|
+
self.loss_function = loss_function
|
|
47
|
+
|
|
48
|
+
def forward(self, preds, targets):
|
|
49
|
+
"""Forward pass.
|
|
50
|
+
|
|
51
|
+
Parameters
|
|
52
|
+
----------
|
|
53
|
+
preds: torch.Tensor
|
|
54
|
+
Model's prediction with shape (batch_size, n_classes, n_times).
|
|
55
|
+
targets: torch.Tensor
|
|
56
|
+
Target labels with shape (batch_size, n_classes, n_times).
|
|
57
|
+
"""
|
|
58
|
+
n_preds = preds.shape[-1]
|
|
59
|
+
# slice the targets to fit preds shape
|
|
60
|
+
targets = targets[:, :, -n_preds:]
|
|
61
|
+
# create valid targets mask
|
|
62
|
+
mask = ~torch.isnan(targets)
|
|
63
|
+
# select valid targets that have a matching predictions
|
|
64
|
+
masked_targets = targets[mask]
|
|
65
|
+
masked_preds = preds[mask]
|
|
66
|
+
return self.loss_function(masked_preds, masked_targets)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def mixup_criterion(preds, target):
|
|
70
|
+
"""Implements loss for Mixup for EEG data. See [1]_.
|
|
71
|
+
|
|
72
|
+
Implementation based on [2]_.
|
|
73
|
+
|
|
74
|
+
Parameters
|
|
75
|
+
----------
|
|
76
|
+
preds : torch.Tensor
|
|
77
|
+
Predictions from the model.
|
|
78
|
+
target : torch.Tensor | list of torch.Tensor
|
|
79
|
+
For predictions without mixup, the targets as a tensor. If mixup has
|
|
80
|
+
been applied, a list containing the targets of the two mixed
|
|
81
|
+
samples and the mixing coefficients as tensors.
|
|
82
|
+
|
|
83
|
+
Returns
|
|
84
|
+
-------
|
|
85
|
+
loss : float
|
|
86
|
+
The loss value.
|
|
87
|
+
|
|
88
|
+
References
|
|
89
|
+
----------
|
|
90
|
+
.. [1] Hongyi Zhang, Moustapha Cisse, Yann N. Dauphin, David Lopez-Paz
|
|
91
|
+
mixup: Beyond Empirical Risk Minimization
|
|
92
|
+
Online: https://arxiv.org/abs/1710.09412
|
|
93
|
+
.. [2] https://github.com/facebookresearch/mixup-cifar10/blob/master/train.py
|
|
94
|
+
"""
|
|
95
|
+
if len(target) == 3:
|
|
96
|
+
# unpack target
|
|
97
|
+
y_a, y_b, lam = target
|
|
98
|
+
# compute loss per sample
|
|
99
|
+
loss_a = torch.nn.functional.nll_loss(preds, y_a, reduction="none")
|
|
100
|
+
loss_b = torch.nn.functional.nll_loss(preds, y_b, reduction="none")
|
|
101
|
+
# compute weighted mean
|
|
102
|
+
ret = torch.mul(lam, loss_a) + torch.mul(1 - lam, loss_b)
|
|
103
|
+
return ret.mean()
|
|
104
|
+
else:
|
|
105
|
+
return torch.nn.functional.nll_loss(preds, target)
|