braindecode 1.8.1.dev174425547__tar.gz → 1.8.1.dev174649576__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.
Files changed (208) hide show
  1. {braindecode-1.8.1.dev174425547/braindecode.egg-info → braindecode-1.8.1.dev174649576}/PKG-INFO +1 -1
  2. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/ctnet.py +9 -1
  3. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/eegconformer.py +14 -1
  4. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/eegsym.py +68 -16
  5. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/luna.py +4 -3
  6. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/mirepnet.py +15 -4
  7. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/msvtnet.py +115 -0
  8. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/neurorvq.py +3 -2
  9. braindecode-1.8.1.dev174649576/braindecode/version.py +1 -0
  10. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576/braindecode.egg-info}/PKG-INFO +1 -1
  11. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/whats_new.rst +10 -0
  12. braindecode-1.8.1.dev174425547/braindecode/version.py +0 -1
  13. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/LICENSE.txt +0 -0
  14. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/MANIFEST.in +0 -0
  15. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/NOTICE.txt +0 -0
  16. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/README.rst +0 -0
  17. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/__init__.py +0 -0
  18. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/augmentation/__init__.py +0 -0
  19. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/augmentation/base.py +0 -0
  20. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/augmentation/functional.py +0 -0
  21. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/augmentation/transforms.py +0 -0
  22. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/classifier.py +0 -0
  23. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datasets/__init__.py +0 -0
  24. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datasets/_notebook_viewer.py +0 -0
  25. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datasets/base.py +0 -0
  26. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datasets/bbci.py +0 -0
  27. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datasets/bcicomp.py +0 -0
  28. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datasets/bids/__init__.py +0 -0
  29. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datasets/bids/datasets.py +0 -0
  30. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datasets/bids/format.py +0 -0
  31. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datasets/bids/hub.py +0 -0
  32. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datasets/bids/hub_format.py +0 -0
  33. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datasets/bids/hub_io.py +0 -0
  34. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datasets/bids/hub_validation.py +0 -0
  35. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datasets/bids/iterable.py +0 -0
  36. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datasets/chb_mit.py +0 -0
  37. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datasets/collate.py +0 -0
  38. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datasets/mne.py +0 -0
  39. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datasets/moabb.py +0 -0
  40. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datasets/nmt.py +0 -0
  41. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datasets/registry.py +0 -0
  42. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datasets/siena.py +0 -0
  43. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datasets/sleep_physio_challe_18.py +0 -0
  44. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datasets/sleep_physionet.py +0 -0
  45. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datasets/tuh.py +0 -0
  46. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datasets/utils.py +0 -0
  47. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datasets/xy.py +0 -0
  48. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datautil/__init__.py +0 -0
  49. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datautil/channel_utils.py +0 -0
  50. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datautil/hub_formats.py +0 -0
  51. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datautil/serialization.py +0 -0
  52. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/datautil/util.py +0 -0
  53. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/eegneuralnet.py +0 -0
  54. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/functional/__init__.py +0 -0
  55. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/functional/_real_dft.py +0 -0
  56. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/functional/functions.py +0 -0
  57. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/functional/initialization.py +0 -0
  58. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/__init__.py +0 -0
  59. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/atcnet.py +0 -0
  60. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/attentionbasenet.py +0 -0
  61. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/attn_sleep.py +0 -0
  62. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/axon.py +0 -0
  63. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/barista.py +0 -0
  64. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/base.py +0 -0
  65. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/bendr.py +0 -0
  66. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/biot.py +0 -0
  67. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/brainbert.py +0 -0
  68. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/brainmodule.py +0 -0
  69. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/brainomni.py +0 -0
  70. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/brant.py +0 -0
  71. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/cbramod.py +0 -0
  72. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/codebrain.py +0 -0
  73. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/config.py +0 -0
  74. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/contrawr.py +0 -0
  75. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/csbrain.py +0 -0
  76. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/dance.py +0 -0
  77. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/deep4.py +0 -0
  78. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/deepsleepnet.py +0 -0
  79. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/dgcnn.py +0 -0
  80. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/diver1.py +0 -0
  81. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/eeg_clip.py +0 -0
  82. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/eegdino.py +0 -0
  83. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/eeginception_erp.py +0 -0
  84. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/eeginception_mi.py +0 -0
  85. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/eegitnet.py +0 -0
  86. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/eegminer.py +0 -0
  87. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/eegnet.py +0 -0
  88. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/eegnex.py +0 -0
  89. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/eegpt.py +0 -0
  90. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/eegsimpleconv.py +0 -0
  91. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/eegtcnet.py +0 -0
  92. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/emg2qwerty.py +0 -0
  93. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/fbcnet.py +0 -0
  94. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/fblightconvnet.py +0 -0
  95. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/fbmsnet.py +0 -0
  96. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/guetschel2026.py +0 -0
  97. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/hybrid.py +0 -0
  98. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/ifnet.py +0 -0
  99. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/labram.py +0 -0
  100. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/mapa.py +0 -0
  101. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/medformer.py +0 -0
  102. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/meta_neuromotor.py +0 -0
  103. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/mscformer.py +0 -0
  104. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/mvpformer.py +0 -0
  105. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/neuropose.py +0 -0
  106. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/neurorvq_tokenizer.py +0 -0
  107. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/patchedtransformer.py +0 -0
  108. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/popt.py +0 -0
  109. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/reve.py +0 -0
  110. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/sccnet.py +0 -0
  111. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/seizure_transformer.py +0 -0
  112. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/sensingdynamics.py +0 -0
  113. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/shallow_fbcsp.py +0 -0
  114. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/signal_jepa.py +0 -0
  115. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/sinc_shallow.py +0 -0
  116. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/sleep_stager_blanco_2020.py +0 -0
  117. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/sleep_stager_chambon_2018.py +0 -0
  118. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/sleepfm.py +0 -0
  119. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/sparcnet.py +0 -0
  120. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/sstdpn.py +0 -0
  121. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/steegformer.py +0 -0
  122. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/summary.csv +0 -0
  123. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/syncnet.py +0 -0
  124. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/tcformer.py +0 -0
  125. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/tcn.py +0 -0
  126. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/tfm_tokenizer.py +0 -0
  127. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/tidnet.py +0 -0
  128. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/tmsanet.py +0 -0
  129. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/tsinception.py +0 -0
  130. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/usleep.py +0 -0
  131. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/util.py +0 -0
  132. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/vemg2pose.py +0 -0
  133. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/models/zuna.py +0 -0
  134. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/modules/__init__.py +0 -0
  135. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/modules/activation.py +0 -0
  136. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/modules/attention.py +0 -0
  137. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/modules/blocks.py +0 -0
  138. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/modules/channels.py +0 -0
  139. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/modules/convolution.py +0 -0
  140. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/modules/dance_modules.py +0 -0
  141. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/modules/filter.py +0 -0
  142. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/modules/layers.py +0 -0
  143. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/modules/linear.py +0 -0
  144. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/modules/linear_attention.py +0 -0
  145. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/modules/parametrization.py +0 -0
  146. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/modules/popt_modules.py +0 -0
  147. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/modules/quantization.py +0 -0
  148. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/modules/stats.py +0 -0
  149. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/modules/util.py +0 -0
  150. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/modules/wrapper.py +0 -0
  151. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/preprocessing/__init__.py +0 -0
  152. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/preprocessing/eegprep_preprocess.py +0 -0
  153. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/preprocessing/mne_preprocess.py +0 -0
  154. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/preprocessing/preprocess.py +0 -0
  155. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/preprocessing/util.py +0 -0
  156. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/preprocessing/windowers.py +0 -0
  157. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/regressor.py +0 -0
  158. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/samplers/__init__.py +0 -0
  159. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/samplers/base.py +0 -0
  160. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/samplers/ssl.py +0 -0
  161. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/training/__init__.py +0 -0
  162. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/training/callbacks.py +0 -0
  163. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/training/losses.py +0 -0
  164. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/training/scoring.py +0 -0
  165. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/util.py +0 -0
  166. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/visualization/__init__.py +0 -0
  167. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/visualization/activations.py +0 -0
  168. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/visualization/attribution.py +0 -0
  169. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/visualization/confusion_matrices.py +0 -0
  170. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/visualization/frequency.py +0 -0
  171. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/visualization/metrics.py +0 -0
  172. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/visualization/sanity.py +0 -0
  173. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode/visualization/topology.py +0 -0
  174. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode.egg-info/SOURCES.txt +0 -0
  175. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode.egg-info/dependency_links.txt +0 -0
  176. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode.egg-info/requires.txt +0 -0
  177. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/braindecode.egg-info/top_level.txt +0 -0
  178. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/Makefile +0 -0
  179. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/_templates/autosummary/class.rst +0 -0
  180. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/_templates/autosummary/class_in_subdir.rst +0 -0
  181. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/_templates/autosummary/function.rst +0 -0
  182. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/_templates/autosummary/function_in_subdir.rst +0 -0
  183. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/agent_docs.rst +0 -0
  184. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/api.rst +0 -0
  185. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/cite.rst +0 -0
  186. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/conf.py +0 -0
  187. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/help.rst +0 -0
  188. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/index.rst +0 -0
  189. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/install/install.rst +0 -0
  190. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/install/install_pip.rst +0 -0
  191. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/install/install_source.rst +0 -0
  192. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/models/categorization/attention.rst +0 -0
  193. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/models/categorization/channel.rst +0 -0
  194. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/models/categorization/convolution.rst +0 -0
  195. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/models/categorization/filterbank.rst +0 -0
  196. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/models/categorization/gnn.rst +0 -0
  197. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/models/categorization/interpretable.rst +0 -0
  198. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/models/categorization/lbm.rst +0 -0
  199. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/models/categorization/recurrent.rst +0 -0
  200. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/models/categorization/spd.rst +0 -0
  201. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/models/models.rst +0 -0
  202. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/models/models_categorization.rst +0 -0
  203. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/models/models_table.rst +0 -0
  204. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/models/models_visualization.rst +0 -0
  205. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/sg_execution_times.rst +0 -0
  206. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/docs/user_guide/channel_strategies.rst +0 -0
  207. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/pyproject.toml +0 -0
  208. {braindecode-1.8.1.dev174425547 → braindecode-1.8.1.dev174649576}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: braindecode
3
- Version: 1.8.1.dev174425547
3
+ Version: 1.8.1.dev174649576
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>
@@ -378,7 +378,15 @@ class _PatchEmbeddingEEGNet(nn.Module):
378
378
  Tensor
379
379
  Embedded patches of shape (batch_size, num_patches, embedding_dim).
380
380
  """
381
- x = self.eegnet_module(x)
381
+ layers = self.eegnet_module
382
+ x = layers[1](layers[0](x))
383
+ # The depthwise (n_chans, 1) convolution as a matmul over the channel
384
+ # axis: same values, a faster backward than the grouped convolution's.
385
+ b, f, c, t = x.shape
386
+ x = torch.matmul(layers[2].weight.view(f, -1, c), x).view(b, -1, 1, t)
387
+ for i, layer in enumerate(layers):
388
+ if i > 2:
389
+ x = layer(x)
382
390
  x = self.projection(x)
383
391
  return x
384
392
 
@@ -4,6 +4,7 @@
4
4
  import warnings
5
5
 
6
6
  import torch
7
+ import torch.nn.functional as F
7
8
  from einops.layers.torch import Rearrange
8
9
  from torch import Tensor, nn
9
10
 
@@ -346,7 +347,19 @@ class _PatchEmbedding(nn.Module):
346
347
  )
347
348
 
348
349
  def forward(self, x: Tensor) -> Tensor:
349
- x = self.shallownet(x)
350
+ # Nothing runs between the temporal and the spatial convolution, so
351
+ # they run as one convolution with the composed weight and bias (as
352
+ # CombinedConv does), without the (batch, filters, chans, time)
353
+ # intermediate.
354
+ conv_time, conv_spat = self.shallownet[0], self.shallownet[1]
355
+ bias_time, bias_spat = conv_time.bias, conv_spat.bias
356
+ assert bias_time is not None and bias_spat is not None
357
+ weight = (conv_time.weight * conv_spat.weight.permute(1, 0, 2, 3)).sum(0)
358
+ bias = conv_spat.weight.sum((2, 3)) @ bias_time + bias_spat
359
+ x = F.conv1d(x.squeeze(1), weight, bias).unsqueeze(2)
360
+ for i, layer in enumerate(self.shallownet):
361
+ if i > 1:
362
+ x = layer(x)
350
363
  x = self.projection(x)
351
364
  return x
352
365
 
@@ -457,6 +457,58 @@ class _SpatialConv3d(nn.Conv3d):
457
457
  return y.reshape(b, -1, z, t, y.shape[-1])
458
458
 
459
459
 
460
+ class _BatchNorm3d(nn.BatchNorm3d):
461
+ """``nn.BatchNorm3d`` with running statistics (as built here); on HPU it
462
+ normalises the ``(batch, channels, -1)`` view, same statistics and
463
+ buffers: Gaudi's 5-D batch norm backward is 2-7x slower than its 3-D one
464
+ on these activations. Elsewhere the same ``batch_norm`` call as torch's."""
465
+
466
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
467
+ if self.training and self.num_batches_tracked is not None:
468
+ self.num_batches_tracked.add_(1)
469
+ y = nn.functional.batch_norm(
470
+ x.flatten(2) if x.device.type == "hpu" else x,
471
+ self.running_mean,
472
+ self.running_var,
473
+ self.weight,
474
+ self.bias,
475
+ self.training,
476
+ self.momentum, # type: ignore[arg-type]
477
+ self.eps,
478
+ )
479
+ return y.view_as(x)
480
+
481
+
482
+ class _TemporalConv3d(nn.Conv3d):
483
+ """``nn.Conv3d`` with a ``(1, k, 1)`` kernel (padding on time only); on HPU
484
+ it runs as ``conv1d`` on a ``(batch * z * space, channels, time)`` copy of
485
+ the input, same parameters. Gaudi's conv3d along time, which is not the
486
+ innermost axis here, is 10-50x slower than that conv1d."""
487
+
488
+ def __init__(self, *args, **kwargs):
489
+ super().__init__(*args, **kwargs)
490
+ self.time_padding = (
491
+ self.padding if isinstance(self.padding, str) else self.padding[1]
492
+ )
493
+
494
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
495
+ if x.device.type == "hpu":
496
+ return self._time_last(x)
497
+ return self._conv_forward(x, self.weight, self.bias)
498
+
499
+ def _time_last(self, x: torch.Tensor) -> torch.Tensor:
500
+ b, c, z, t, s = x.shape
501
+ y = nn.functional.conv1d(
502
+ x.permute(0, 2, 4, 1, 3).reshape(b * z * s, c, t),
503
+ self.weight.flatten(2),
504
+ self.bias,
505
+ padding=self.time_padding,
506
+ groups=self.groups,
507
+ )
508
+ y = y.reshape(b, z, s, y.shape[1], y.shape[2])
509
+ return y.permute(0, 3, 1, 4, 2).contiguous()
510
+
511
+
460
512
  class _InceptionBlock(nn.Module):
461
513
  r"""Inception module used in EEGSym architecture.
462
514
 
@@ -498,13 +550,13 @@ class _InceptionBlock(nn.Module):
498
550
  for scale in scales_samples:
499
551
  self.temporal_convs.append(
500
552
  nn.Sequential(
501
- nn.Conv3d(
553
+ _TemporalConv3d(
502
554
  in_channels=in_channels,
503
555
  out_channels=filters_per_branch,
504
556
  kernel_size=(1, scale, 1),
505
557
  padding="same",
506
558
  ),
507
- nn.BatchNorm3d(filters_per_branch, eps=1e-3, momentum=0.01),
559
+ _BatchNorm3d(filters_per_branch, eps=1e-3, momentum=0.01),
508
560
  activation,
509
561
  nn.Dropout(drop_prob),
510
562
  )
@@ -527,7 +579,7 @@ class _InceptionBlock(nn.Module):
527
579
  groups=filters_per_branch * len(scales_samples),
528
580
  bias=False,
529
581
  ),
530
- nn.BatchNorm3d(
582
+ _BatchNorm3d(
531
583
  filters_per_branch * len(scales_samples),
532
584
  eps=1e-3,
533
585
  momentum=0.01,
@@ -598,13 +650,13 @@ class _ResidualBlock(nn.Module):
598
650
 
599
651
  # Temporal convolution
600
652
  self.temporal_conv = nn.Sequential(
601
- nn.Conv3d(
653
+ _TemporalConv3d(
602
654
  in_channels=in_channels,
603
655
  out_channels=filters,
604
656
  kernel_size=(1, kernel_size, 1),
605
657
  padding="same",
606
658
  ),
607
- nn.BatchNorm3d(filters, eps=1e-3, momentum=0.01),
659
+ _BatchNorm3d(filters, eps=1e-3, momentum=0.01),
608
660
  activation,
609
661
  nn.Dropout(drop_prob),
610
662
  )
@@ -618,7 +670,7 @@ class _ResidualBlock(nn.Module):
618
670
  kernel_size=(1, 1, 1),
619
671
  bias=False,
620
672
  ),
621
- nn.BatchNorm3d(filters, eps=1e-3, momentum=0.01),
673
+ _BatchNorm3d(filters, eps=1e-3, momentum=0.01),
622
674
  activation,
623
675
  nn.Dropout(drop_prob),
624
676
  )
@@ -642,7 +694,7 @@ class _ResidualBlock(nn.Module):
642
694
  groups=1,
643
695
  bias=False,
644
696
  ),
645
- nn.BatchNorm3d(filters, eps=1e-3, momentum=0.01),
697
+ _BatchNorm3d(filters, eps=1e-3, momentum=0.01),
646
698
  activation,
647
699
  nn.Dropout(drop_prob),
648
700
  )
@@ -694,14 +746,14 @@ class _TemporalBlock(nn.Module):
694
746
  super().__init__()
695
747
 
696
748
  self.conv = nn.Sequential(
697
- nn.Conv3d(
749
+ _TemporalConv3d(
698
750
  in_channels=in_channels,
699
751
  out_channels=filters,
700
752
  kernel_size=(1, kernel_size, 1),
701
753
  padding="same",
702
754
  bias=False,
703
755
  ),
704
- nn.BatchNorm3d(filters, eps=1e-3, momentum=0.01),
756
+ _BatchNorm3d(filters, eps=1e-3, momentum=0.01),
705
757
  activation,
706
758
  nn.Dropout(drop_prob),
707
759
  )
@@ -762,7 +814,7 @@ class _ChannelMergingBlock(nn.Module):
762
814
  padding=(0, 0, 0), # Valid padding
763
815
  bias=False,
764
816
  ),
765
- nn.BatchNorm3d(filters, eps=1e-3, momentum=0.01),
817
+ _BatchNorm3d(filters, eps=1e-3, momentum=0.01),
766
818
  activation,
767
819
  nn.Dropout(drop_prob),
768
820
  )
@@ -779,7 +831,7 @@ class _ChannelMergingBlock(nn.Module):
779
831
  padding=(0, 0, 0),
780
832
  bias=False,
781
833
  ),
782
- nn.BatchNorm3d(filters, eps=1e-3, momentum=0.01),
834
+ _BatchNorm3d(filters, eps=1e-3, momentum=0.01),
783
835
  activation,
784
836
  nn.Dropout(drop_prob),
785
837
  )
@@ -837,21 +889,21 @@ class _TemporalMergingBlock(nn.Module):
837
889
 
838
890
  # Residual convolution (collapses time dimension)
839
891
  self.residual_conv = nn.Sequential(
840
- nn.Conv3d(
892
+ _TemporalConv3d(
841
893
  in_channels=in_channels,
842
894
  out_channels=in_channels, # Same channels for residual
843
895
  kernel_size=(1, self.temporal_kernel, 1), # (Z, Time, Space)
844
896
  padding=(0, 0, 0), # Valid padding - reduces time to 1
845
897
  bias=False,
846
898
  ),
847
- nn.BatchNorm3d(in_channels, eps=1e-3, momentum=0.01),
899
+ _BatchNorm3d(in_channels, eps=1e-3, momentum=0.01),
848
900
  activation,
849
901
  nn.Dropout(drop_prob),
850
902
  )
851
903
 
852
904
  # Grouped convolution (collapses time dimension, doubles filters)
853
905
  self.grouped_conv = nn.Sequential(
854
- nn.Conv3d(
906
+ _TemporalConv3d(
855
907
  in_channels=in_channels,
856
908
  out_channels=filters, # Double the channels
857
909
  kernel_size=(1, self.temporal_kernel, 1), # (Z, Time, Space)
@@ -859,7 +911,7 @@ class _TemporalMergingBlock(nn.Module):
859
911
  padding=(0, 0, 0),
860
912
  bias=False,
861
913
  ),
862
- nn.BatchNorm3d(filters, eps=1e-3, momentum=0.01),
914
+ _BatchNorm3d(filters, eps=1e-3, momentum=0.01),
863
915
  activation,
864
916
  nn.Dropout(drop_prob),
865
917
  )
@@ -908,7 +960,7 @@ class _OutputBlock(nn.Module):
908
960
  padding=(0, 0, 0),
909
961
  bias=False,
910
962
  ),
911
- nn.BatchNorm3d(in_channels, eps=1e-3, momentum=0.01),
963
+ _BatchNorm3d(in_channels, eps=1e-3, momentum=0.01),
912
964
  activation,
913
965
  nn.Dropout(drop_prob),
914
966
  )
@@ -23,6 +23,7 @@ import torch.nn.functional as F
23
23
 
24
24
  from braindecode.functional import rotate_pairs, spectral_input
25
25
  from braindecode.models.base import EEGModuleMixin
26
+ from braindecode.models.signal_jepa import _GroupNorm
26
27
  from braindecode.models.util import extract_channel_locations_from_chs_info
27
28
  from braindecode.modules.blocks import PatchTokenizer
28
29
  from braindecode.modules.layers import DropPath
@@ -884,7 +885,7 @@ class _PatchEmbedNetwork(nn.Module):
884
885
  stride=(1, self.kernel_size // 2),
885
886
  padding=(0, self.kernel_size // 2 - 1),
886
887
  ),
887
- nn.GroupNorm(self.groups, self.out_channels),
888
+ _GroupNorm(self.groups, self.out_channels),
888
889
  nn.GELU(),
889
890
  nn.Conv2d(
890
891
  in_channels=self.out_channels,
@@ -893,7 +894,7 @@ class _PatchEmbedNetwork(nn.Module):
893
894
  stride=(1, 1),
894
895
  padding=(0, 1),
895
896
  ),
896
- nn.GroupNorm(self.groups, self.out_channels),
897
+ _GroupNorm(self.groups, self.out_channels),
897
898
  nn.GELU(),
898
899
  nn.Conv2d(
899
900
  in_channels=self.out_channels,
@@ -902,7 +903,7 @@ class _PatchEmbedNetwork(nn.Module):
902
903
  stride=(1, 1),
903
904
  padding=(0, 1),
904
905
  ),
905
- nn.GroupNorm(self.groups, self.out_channels),
906
+ _GroupNorm(self.groups, self.out_channels),
906
907
  nn.GELU(),
907
908
  )
908
909
 
@@ -9,6 +9,7 @@ from __future__ import annotations
9
9
 
10
10
  from typing import Dict, Optional, Union
11
11
 
12
+ import torch.nn.functional as F
12
13
  from torch import Tensor, nn
13
14
 
14
15
  from braindecode.models.base import EEGModuleMixin
@@ -300,15 +301,25 @@ class _PatchEmbedding(nn.Module):
300
301
  self.projection = nn.Conv2d(n_filters_spat, embed_dim, kernel_size=(1, 1))
301
302
 
302
303
  def forward(self, x: Tensor) -> Tensor:
303
- x = x.unsqueeze(1)
304
- x = self.conv1(x)
305
- x = self.conv2(x)
304
+ # Nothing runs between the temporal and the spatial convolution, so
305
+ # they run as one convolution over the channels with the composed
306
+ # weight and bias, without the (batch, filters, chans, time)
307
+ # intermediate.
308
+ bias_time, bias_spat = self.conv1.bias, self.conv2.bias
309
+ assert bias_time is not None and bias_spat is not None
310
+ w_spat = self.conv2.weight.squeeze(-1).transpose(1, 2) # (spat, chans, time)
311
+ weight = w_spat @ self.conv1.weight.flatten(1) # (spat, chans, kernel)
312
+ bias = self.conv2.weight.sum((2, 3)) @ bias_time + bias_spat
313
+ x = F.conv1d(x, weight, bias).unsqueeze(2)
306
314
  x = self.bn(x)
307
315
  x = self.elu(x)
308
316
  x = self.pool(x)
309
317
  x = self.dropout(x)
310
318
  x = self.projection(x)
311
- return x.flatten(start_dim=2).transpose(1, 2)
319
+ # Contiguous tokens: each residual add takes its first operand's
320
+ # layout, so a transposed view here would keep every add and layer
321
+ # norm of the encoder reading strided memory.
322
+ return x.flatten(start_dim=2).transpose(1, 2).contiguous()
312
323
 
313
324
 
314
325
  class _ResidualAdd(nn.Module):
@@ -5,6 +5,7 @@ from typing import Tuple, Type, Union
5
5
 
6
6
  import torch
7
7
  import torch.nn as nn
8
+ import torch.nn.functional as F
8
9
  from einops.layers.torch import Rearrange
9
10
 
10
11
  from braindecode.models.base import EEGModuleMixin, _too_short_input_error
@@ -286,6 +287,120 @@ class _TSConv(nn.Sequential):
286
287
  nn.Dropout(drop_prob),
287
288
  )
288
289
 
290
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
291
+ if not torch.is_grad_enabled() and x.device.type == "hpu":
292
+ # On HPU without autograd the grouped convolution's forward is the
293
+ # faster one.
294
+ x = self[2](self[1](self[0](x)))
295
+ elif x.numel() * self[0].weight.shape[0] >= 2**26:
296
+ # ponytail: size heuristic. The spatial-first form adds ~50 small ops
297
+ # per branch; they pay off once the (batch, filters, chans, times)
298
+ # tensor it avoids reaches 2**26 elements (Gaudi lazy-mode crossover;
299
+ # eager mode and CPU gain from smaller inputs already).
300
+ x = self._spatial_first(x)
301
+ else:
302
+ # The depthwise (n_channels, 1) convolution as a matmul over the
303
+ # channel axis: same values, a faster backward than the grouped
304
+ # convolution's.
305
+ x = self[1](self[0](x))
306
+ b, f, c, t = x.shape
307
+ x = torch.matmul(self[2].weight.view(f, -1, c), x).view(b, -1, 1, t)
308
+ for i, layer in enumerate(self):
309
+ if i > 2:
310
+ x = layer(x)
311
+ return x
312
+
313
+ def _spatial_first(self, x: torch.Tensor) -> torch.Tensor:
314
+ """Temporal conv, batch norm and depthwise spatial conv (layers 0-2).
315
+
316
+ The three are linear per filter, so the spatial weights project the
317
+ input first and each filter's temporal kernel then runs on its
318
+ projections; in training the batch norm's statistics come from
319
+ :func:`_same_conv_moments`. The (batch, filters, chans, times) tensor
320
+ is never built.
321
+ """
322
+ b, _, c, t = x.shape
323
+ w = self[0].weight.flatten(1)
324
+ f, k = w.shape
325
+ w2 = self[2].weight.view(-1, c)
326
+ d = w2.shape[0] // f
327
+ if self[1].training or self[1].running_mean is None:
328
+ mean, var = _same_conv_moments(x.reshape(b * c, t), w)
329
+ if self[1].training and self[1].track_running_stats:
330
+ self[1].num_batches_tracked.add_(1)
331
+ momentum = self[1].momentum
332
+ if momentum is None:
333
+ factor = 1.0 / float(self[1].num_batches_tracked)
334
+ else:
335
+ factor = momentum
336
+ n = b * c * t
337
+ self[1].running_mean.mul_(1 - factor).add_(mean.detach(), alpha=factor)
338
+ self[1].running_var.mul_(1 - factor).add_(
339
+ var.detach(), alpha=factor * n / (n - 1)
340
+ )
341
+ else:
342
+ mean, var = self[1].running_mean, self[1].running_var
343
+ scale = self[1].weight * torch.rsqrt(var + self[1].eps)
344
+ shift = (self[1].bias - mean * scale).unsqueeze(1) * w2.sum(1).view(f, d)
345
+ y = F.conv1d(
346
+ torch.matmul(w2, x.reshape(b, c, t)),
347
+ w.unsqueeze(1).expand(f, d, k).reshape(f * d, 1, k),
348
+ padding="same",
349
+ groups=f * d,
350
+ )
351
+ scale = scale.unsqueeze(1).expand(f, d).reshape(-1, 1)
352
+ return torch.addcmul(shift.view(-1, 1), y, scale).unsqueeze(2)
353
+
354
+
355
+ def _same_conv_moments(
356
+ x: torch.Tensor, w: torch.Tensor
357
+ ) -> Tuple[torch.Tensor, torch.Tensor]:
358
+ """Mean and biased variance per filter of ``conv1d(x, w, padding="same")``.
359
+
360
+ Over all rows and times, for ``x`` of shape (rows, times) and ``w`` of shape
361
+ (filters, k), without building the (rows, filters, times) output: the sum of
362
+ squares is the filter's autocorrelation against the input's (one matmul over
363
+ blocks of k samples), minus the outputs that "same" crops at both ends. The
364
+ input is centred first so the variance does not cancel against a large mean.
365
+ """
366
+ rows, t = x.shape
367
+ f, k = w.shape
368
+ n = rows * t
369
+ m = x.mean()
370
+ x = x - m
371
+ # a[l] = sum over rows and s of x[s] x[s + l], for l < k
372
+ nb = (t + k - 1) // k
373
+ blk = F.pad(x, (0, (nb + 1) * k - t)).view(rows, nb + 1, k)
374
+ nxt = torch.cat([blk[:, :nb], blk[:, 1:, : k - 1]], 2).reshape(-1, 2 * k - 1)
375
+ a = blk[:, :nb].reshape(-1, k).t() @ nxt
376
+ a = F.pad(a.reshape(-1), (0, k)).view(k, 2 * k)[:, :k].sum(0)
377
+ # sum of squares over every output of the full (uncropped) correlation
378
+ ww = F.conv1d(w.unsqueeze(0), w.unsqueeze(1), padding=k - 1, groups=f)[0]
379
+ sq = torch.mv(ww, torch.cat([a[1:].flip([0]), a]))
380
+ if k > 1:
381
+ right = k - 1 - (k - 1) // 2
382
+ pad = max(0, k - 1 - t)
383
+ ends = torch.cat(
384
+ [
385
+ F.pad(x[:, : k - 1], (k - 1, pad)),
386
+ F.pad(x[:, t - min(t, k - 1) :], (pad, k - 1)),
387
+ ]
388
+ )
389
+ ends = F.conv1d(ends.unsqueeze(1), w.unsqueeze(1)).view(2, rows, f, k - 1)
390
+ ends = ends.square().sum(1)
391
+ sq = sq - ends[0, :, :right].sum(1) - ends[1, :, right:].sum(1)
392
+ # undo the centring: conv(x + m) = conv(x) + m * v, v = conv(ones)
393
+ u = F.conv1d(x.sum(0).view(1, 1, t), w.unsqueeze(1), padding="same")[0]
394
+ v = F.conv1d(torch.ones_like(x[:1]).unsqueeze(0), w.unsqueeze(1), padding="same")[0]
395
+ mean_c = u.sum(1) / n
396
+ dv = v - v.mean(1, keepdim=True)
397
+ var = (
398
+ sq / n
399
+ - mean_c.square()
400
+ + m * (m * dv.square().mean(1) + 2 * (u * dv).sum(1) / n)
401
+ )
402
+ return mean_c + m * v.mean(1), var
403
+
289
404
 
290
405
  class _PositionalEncoding(nn.Module):
291
406
  r"""
@@ -16,6 +16,7 @@ from torch import Tensor, nn
16
16
 
17
17
  from braindecode.models.base import EEGModuleMixin
18
18
  from braindecode.models.labram import _Attention
19
+ from braindecode.models.signal_jepa import _GroupNorm
19
20
  from braindecode.modules import MLP, DropPath
20
21
 
21
22
  # Channel order used to train NeuroRVQ-EEG v1. Keep in sync with the released
@@ -281,7 +282,7 @@ class _MultiScaleTemporalConv(nn.Module):
281
282
  f"conv1_{i}",
282
283
  nn.Conv2d(1, out_chans, (1, kernel), padding=(0, kernel // 2)),
283
284
  )
284
- setattr(self, f"norm1_{i}", nn.GroupNorm(4, out_chans))
285
+ setattr(self, f"norm1_{i}", _GroupNorm(4, out_chans))
285
286
  setattr(self, f"pool1_{i}", nn.AvgPool2d((1, 2)))
286
287
  for i, kernel in enumerate(kernels[1], start=1):
287
288
  setattr(
@@ -289,7 +290,7 @@ class _MultiScaleTemporalConv(nn.Module):
289
290
  f"conv2_{i}",
290
291
  nn.Conv2d(out_chans, out_chans, (1, kernel), padding=(0, kernel // 2)),
291
292
  )
292
- setattr(self, f"norm2_{i}", nn.GroupNorm(4, out_chans))
293
+ setattr(self, f"norm2_{i}", _GroupNorm(4, out_chans))
293
294
  setattr(self, f"pool2_{i}", nn.AvgPool2d((1, 4)))
294
295
  self.gelu1 = activation()
295
296
  self.gelu2 = activation()
@@ -0,0 +1 @@
1
+ __version__ = "1.8.1.dev174649576"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: braindecode
3
- Version: 1.8.1.dev174425547
3
+ Version: 1.8.1.dev174649576
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>
@@ -33,12 +33,20 @@ Enhancements
33
33
  - :class:`braindecode.models.AXON` computes its banded and full temporal attention from one score matrix: both softmaxes share the query-key product, and one product with the values and one ``temporal_out`` projection serve their scale-gated mixture (the gate weights sum to one). Gaudi train step 1.10x faster in lazy mode and 1.17x in eager mode, CPU 1.05x (21 channels x 6000 samples, batch 64); outputs and gradients differ from before by float rounding of the new summation order, up to 1.6x master's own float32-vs-float64 difference on the outputs (more on the ~1e-9 gate-bias gradients), argmax unchanged; the attention-dropout and no-band paths are unchanged (:gh:`1359` by `Bruno Aristimunha`_).
34
34
  - :class:`braindecode.models.EEGInceptionMI` takes the channels-last copy for its max pooling only on CPU: on Intel Gaudi (HPU) the layout copies made the eager train step 2.6x slower than in 1.8.1 (now back to 1.8.1's time); CPU unchanged (:gh:`1344` by `Bruno Aristimunha`_).
35
35
  - :class:`braindecode.models.SignalJEPA`, :class:`braindecode.models.SignalJEPA_Contextual`, :class:`braindecode.models.SignalJEPA_PreLocal` and :class:`braindecode.models.SignalJEPA_PostLocal` compute the group norm of their feature encoder from mean and variance in HPU eager mode on Intel Gaudi: torch's group norm costs 120-190 ms per forward and backward there whatever the shape. Gaudi eager train step 0.10x (PreLocal) and 0.17x (PostLocal) at 21 channels x 6000 samples, 0.34x for SignalJEPA at 22 x 1000; same code as before on CPU, CUDA and in HPU lazy mode (:gh:`1364` by `Bruno Aristimunha`_).
36
+ - :class:`braindecode.models.EEGSym` runs its temporal ``(1, k, 1)`` convolutions on Intel Gaudi (HPU) as ``conv1d`` on a time-last copy of the input: Gaudi's conv3d along time, which is not the innermost axis of EEGSym's 5-D activations, is 10-50x slower than that conv1d. Gaudi train step 0.47x in eager and 0.57x in lazy mode at 21 channels x 6000 samples; same code as before on CPU and CUDA, same state dict (:gh:`1375` by `Bruno Aristimunha`_).
36
37
  - :func:`braindecode.functional.fft_conv1d` runs on Intel Gaudi (HPU) as overlap-save blocks with the DFT as real matmuls instead of a host FFT, and :func:`braindecode.functional.prefer_fft_conv` picks it there from 8 input channels and ``batch_size * n_times * kernel_size >= 8e6``: Gaudi eager train step of :class:`braindecode.models.EEGInceptionMI` 1.4-2.3x faster and :class:`braindecode.models.EEGNeX` 2.1x faster on 60-s windows at 100 Hz, batch 64; CPU unchanged; Gaudi outputs and gradients change by float rounding only (:gh:`1341` by `Bruno Aristimunha`_).
37
38
  - :class:`braindecode.models.EEGNeX` keeps its long temporal convolution direct on Intel Gaudi (HPU) when no gradient is computed: the FFT path pays off only through the backward, so evaluation and inference on Gaudi were 1.8x (eager) and 2.2x (lazy) slower than in 1.8.1 on 60-s windows at 100 Hz, batch 64; now back to 1.8.1's time; training, CPU and GPU unchanged; Gaudi outputs change by float rounding only (:gh:`1363` by `Bruno Aristimunha`_).
38
39
  - :class:`braindecode.models.SignalJEPA` and :class:`braindecode.models.SignalJEPA_Contextual` run their transformer encoder in training with the attention through the shared SDPA helper (no ``_safe_softmax`` pass of torch's math path, :gh:`1361`), the layers otherwise op for op as torch's: Gaudi eager train step 0.86x at 21 channels x 6000 samples; bit-identical on CPU, same dropout draws; eval, HPU lazy mode and TorchScript unchanged (:gh:`1365` by `Bruno Aristimunha`_).
40
+ - :class:`braindecode.models.CTNet` computes the depthwise spatial convolution of its patch embedding as a matmul over the channel axis: same forward values on CPU (bit-identical outputs and batch-norm statistics), a faster backward than the grouped-convolution kernels. Train step 0.90x on CPU and 0.92x (eager) / 0.81x (lazy) on Intel Gaudi at 21 channels x 6000 samples, batch 64; 0.85x on CPU at 22 x 1000, batch 32; parameters and state dict unchanged, gradients change by float rounding (:gh:`1374` by `Bruno Aristimunha`_).
39
41
  - :class:`braindecode.models.CSBrain` runs its region embedding and the region means of every encoder layer for all regions at once (a 0/1 neighbour-selection matmul and one batched matmul per kernel; one ``index_add_``) instead of one convolution and one mean per region: about half the operators per forward, CPU forward and train step 1.14-1.17x faster, Gaudi forward 1.30-1.45x and train step 1.36-1.56x faster; outputs change by float rounding only (:gh:`1335` by `Bruno Aristimunha`_).
42
+ - :class:`braindecode.models.EEGSym` runs its batch norms on Intel Gaudi (HPU) on the ``(batch, filters, -1)`` view of its 5-D activations: Gaudi's 5-D batch norm backward with the 12 electrodes innermost is 2-7x slower than the 3-D one. Gaudi eager train step 0.75x on top of :gh:`1375` at 21 channels x 6000 samples (lazy 0.95x); same ``batch_norm`` call as before on CPU and CUDA, same state dict (:gh:`1376` by `Bruno Aristimunha`_).
40
43
  - :class:`braindecode.models.DIVER1` computes the amplitude spectrum of its spectral embedding on the device on accelerators without complex tensors (Intel Gaudi / HPU) instead of a host FFT round trip: Gaudi forward 1.02-1.12x and train step 1.02-1.10x faster; CPU unchanged (:gh:`1334` by `Bruno Aristimunha`_).
41
44
  - :class:`braindecode.models.DIVER1` builds and overlap-adds its STCPE sliding windows with one gather and one ``index_add`` instead of ``unfold``/``fold``: Gaudi forward 1.25-1.36x and train step 1.13-1.32x faster, CPU 0-1 % faster; outputs and released-checkpoint outputs unchanged, gradients change by float rounding only (:gh:`1333` by `Bruno Aristimunha`_).
45
+ - :class:`braindecode.models.EEGConformer` runs the temporal and the spatial convolution of its patch embedding as one convolution over the channels with the composed weight and bias (the two are linear with nothing in between): no (batch, filters, channels, time) intermediate and 3.4x fewer stem FLOPs per train step. Train step 0.58x on CPU and 0.68x (eager) / 0.74x (lazy) on Intel Gaudi at 21 channels x 6000 samples, batch 64; 0.41x on CPU at 22 x 1000, batch 32; parameters and state dict unchanged, outputs change by float rounding (:gh:`1373` by `Bruno Aristimunha`_).
46
+ - :class:`braindecode.models.MIRepNet` runs the temporal and the spatial convolution of its patch embedding as one convolution over the channels with the composed weight and bias (the two are linear with nothing in between): no (batch, filters, channels, time) intermediate and 4.3x fewer stem FLOPs per train step. Train step 0.65x on CPU and 0.63x (eager) / 0.54x (lazy) on Intel Gaudi at 21 channels x 6000 samples, batch 64; 0.60x on CPU at 22 x 1000, batch 32; parameters and state dict unchanged, outputs change by float rounding (:gh:`1377` by `Bruno Aristimunha`_).
47
+ - :class:`braindecode.models.LUNA` computes the three group norms of its patch embedding from mean and variance in HPU eager mode on Intel Gaudi, with the group norm of :class:`braindecode.models.SignalJEPA` (:gh:`1364`): torch's group-norm backward was about half of each eager train step there. Gaudi eager train step 0.53x at 21 channels x 6000 samples (batch 64) and 0.31x at 22 x 1000 (batch 32); CPU, CUDA and Gaudi lazy mode run the same ``group_norm`` call as before (bit-identical on CPU), same state dict (:gh:`1379` by `Bruno Aristimunha`_).
48
+ - :class:`braindecode.models.MIRepNet` makes the tokens of its patch embedding contiguous. The transposed view carried through every residual add of the encoder (a sum takes the memory layout of its first operand), so each add and layer norm read strided memory. Gaudi eager train step 0.92x at 21 channels x 6000 samples, batch 64 (CPU 0.98x, lazy unchanged); outputs change by float rounding (:gh:`1378` by `Bruno Aristimunha`_).
49
+ - :class:`braindecode.models.NeuroRVQ` and :class:`braindecode.models.NeuroRVQTokenizer` compute the group norms of their multi-scale patch embedding from mean and variance in HPU eager mode on Intel Gaudi, as :class:`braindecode.models.SignalJEPA` does (:gh:`1364`): the backward of torch's group norm compiled new graphs at every call there (8 per train step, about 70 ms each). Gaudi eager train step 0.22x (NeuroRVQ) and 0.39x (NeuroRVQTokenizer) at 21 channels x 800 samples, batch 64; same code as before on CPU, CUDA and in HPU lazy mode (:gh:`1382` by `Bruno Aristimunha`_).
42
50
  - :class:`braindecode.models.REVE` computes the 4-D position embedding of its default channel positions once per forward and broadcasts it over the batch instead of computing it for one identical copy per example: 3 ms instead of 10-12 ms of each Gaudi train step (21 channels x 6000 samples, batch 64; step 1.01x); explicit ``pos`` inputs are unchanged (:gh:`1347` by `Bruno Aristimunha`_).
43
51
  - :class:`braindecode.models.ContraWR` computes its STFT magnitude on the device on accelerators without complex tensors (Intel Gaudi / HPU) instead of a host STFT and a host-to-device copy of the spectrogram: Gaudi forward 4.2-7.1x and train step 2.4-5.2x faster; CPU unchanged (:gh:`1332` by `Bruno Aristimunha`_).
44
52
  - :class:`braindecode.models.NeuroRVQTokenizer` sums the per-code counts and vectors of its EMA codebook update with ``index_add_`` instead of a dense one-hot matrix and GEMM: CPU train step 1.3x faster (22 channels, batch 32, 2 threads), Gaudi unchanged; outputs, gradients and token ids unchanged, the updated codebooks change by float rounding only (:gh:`1308` by `Bruno Aristimunha`_).
@@ -68,6 +76,8 @@ Enhancements
68
76
  - :class:`braindecode.models.DANCE` skips the taps of its dilated convolutions that only ever read the zero padding (kernel offset at or beyond the input length): CPU train step 0.92x and Gaudi eager 0.97x (21 channels x 6000 samples, batch 64); outputs change by float rounding only (:gh:`1343` by `Bruno Aristimunha`_).
69
77
  - :class:`braindecode.modules.ChannelMerger` (DANCE, ``BrainModule(use_merger=True)``) computes its channel mix as ``(x^T @ weights^T)^T`` on HPU, where Gaudi's lazy-mode graph compiler failed on ``weights @ x`` feeding a convolution's backward: DANCE now trains in Gaudi lazy mode (train step 622 ms vs 844 ms in eager mode, 21 channels x 6000 samples, batch 64); other devices run the same code as before (:gh:`1351` by `Bruno Aristimunha`_).
70
78
  - :class:`braindecode.models.BrainModule` computes its GLU gates as ``a * sigmoid(b)`` in Intel Gaudi (HPU) lazy mode, where the graph compiler failed on ``aten.glu`` after the gate's convolution: BrainModule now trains in Gaudi lazy mode (train step 306 ms vs 554 ms in eager mode, 21 channels x 6000 samples, batch 64); eager mode and other devices run the same code as before (:gh:`1371` by `Bruno Aristimunha`_).
79
+ - :class:`braindecode.models.MSVTNet` computes the depthwise spatial convolution of each branch as a matmul over the channel axis when gradients are computed (and on CPU): same values, a faster backward than the grouped convolution's. Gaudi train step 0.86x in eager and 0.87x in lazy mode, CPU 0.88x at 22 channels x 1000 samples (batch 32) and 0.98x at 21 x 6000 (batch 64); evaluation on Gaudi keeps the grouped convolution; outputs and batch-norm statistics unchanged on CPU, gradients change by float rounding (:gh:`1380` by `Bruno Aristimunha`_).
80
+ - :class:`braindecode.models.MSVTNet` with large inputs (when a branch's (batch, filters, channels, times) activation would reach 2**26 elements, e.g. 21 channels x 6000 samples at batch 64) applies each branch's spatial weights to the input first and runs each filter's temporal kernel on its projections, with the first batch norm's statistics computed from the input's autocorrelation, so that activation is never built: same function and state dict, numerical differences only. Train step at 21 x 6000, batch 64: Intel Gaudi 0.57x in eager mode and 0.78x in lazy mode, CPU 0.23x (:gh:`1384` by `Bruno Aristimunha`_).
71
81
  - :class:`braindecode.models.Labram` and :class:`braindecode.models.BaRISTA` run attention through the Gaudi bridge's fused SDPA kernel in HPU eager mode (without a mask or attention dropout; lazy mode, CPU and other devices unchanged): Gaudi eager train step Labram 8 % and BaRISTA 5 % faster (21 channels x 6000 samples), differences within the Gaudi float32 error (:gh:`1342` by `Bruno Aristimunha`_).
72
82
  - :class:`braindecode.models.DANCE` runs its Perceiver attention through the same Gaudi fused SDPA path in HPU eager mode (torch's SDPA there computes the full score matrix op by op, which made the DANCE Gaudi eager train step 8 % slower than in 1.8.1): Gaudi eager train step 848 -> 763 ms (21 channels x 6000 samples, batch 64); CPU and Gaudi lazy mode unchanged (:gh:`1340` by `Bruno Aristimunha`_).
73
83
  - :class:`braindecode.models.REVE` runs its attention through the same helper, so HPU eager mode uses the Gaudi bridge's fused SDPA kernel instead of torch's op-by-op SDPA through the full score matrix (lazy mode, CPU and other devices unchanged): Gaudi eager train step 1.42x faster (21 channels x 6000 samples, batch 64); differences within the Gaudi float32 error (:gh:`1345` by `Bruno Aristimunha`_).
@@ -1 +0,0 @@
1
- __version__ = "1.8.1.dev174425547"