Braindecode 1.8.1.dev169814997__tar.gz → 1.8.1.dev169869285__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 (211) hide show
  1. {braindecode-1.8.1.dev169814997/braindecode.egg-info → braindecode-1.8.1.dev169869285}/PKG-INFO +1 -2
  2. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/biot.py +56 -6
  3. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/ctnet.py +150 -42
  4. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/eegconformer.py +75 -20
  5. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/eegdino.py +30 -16
  6. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/eegpt.py +90 -19
  7. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/luna.py +46 -19
  8. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/medformer.py +20 -11
  9. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/mirepnet.py +79 -27
  10. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/mscformer.py +161 -42
  11. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/neurorvq.py +58 -36
  12. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/neurorvq_tokenizer.py +2 -2
  13. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/modules/__init__.py +0 -10
  14. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/modules/layers.py +2 -187
  15. braindecode-1.8.1.dev169869285/braindecode/version.py +1 -0
  16. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/visualization/frequency.py +7 -11
  17. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285/braindecode.egg-info}/PKG-INFO +1 -2
  18. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode.egg-info/requires.txt +0 -1
  19. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/api.rst +0 -5
  20. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/whats_new.rst +0 -21
  21. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/pyproject.toml +0 -6
  22. braindecode-1.8.1.dev169814997/braindecode/version.py +0 -1
  23. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/LICENSE.txt +0 -0
  24. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/MANIFEST.in +0 -0
  25. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/NOTICE.txt +0 -0
  26. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/README.rst +0 -0
  27. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/__init__.py +0 -0
  28. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/augmentation/__init__.py +0 -0
  29. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/augmentation/base.py +0 -0
  30. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/augmentation/functional.py +0 -0
  31. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/augmentation/transforms.py +0 -0
  32. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/classifier.py +0 -0
  33. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datasets/__init__.py +0 -0
  34. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datasets/_notebook_viewer.py +0 -0
  35. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datasets/base.py +0 -0
  36. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datasets/bbci.py +0 -0
  37. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datasets/bcicomp.py +0 -0
  38. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datasets/bids/__init__.py +0 -0
  39. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datasets/bids/datasets.py +0 -0
  40. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datasets/bids/hub.py +0 -0
  41. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datasets/bids/hub_format.py +0 -0
  42. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datasets/bids/hub_io.py +0 -0
  43. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datasets/bids/hub_validation.py +0 -0
  44. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datasets/bids/iterable.py +0 -0
  45. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datasets/chb_mit.py +0 -0
  46. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datasets/collate.py +0 -0
  47. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datasets/mne.py +0 -0
  48. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datasets/moabb.py +0 -0
  49. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datasets/nmt.py +0 -0
  50. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datasets/registry.py +0 -0
  51. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datasets/siena.py +0 -0
  52. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datasets/sleep_physio_challe_18.py +0 -0
  53. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datasets/sleep_physionet.py +0 -0
  54. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datasets/tuh.py +0 -0
  55. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datasets/utils.py +0 -0
  56. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datasets/xy.py +0 -0
  57. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datautil/__init__.py +0 -0
  58. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datautil/channel_utils.py +0 -0
  59. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datautil/hub_formats.py +0 -0
  60. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datautil/serialization.py +0 -0
  61. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/datautil/util.py +0 -0
  62. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/eegneuralnet.py +0 -0
  63. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/functional/__init__.py +0 -0
  64. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/functional/_real_dft.py +0 -0
  65. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/functional/attention.py +0 -0
  66. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/functional/functions.py +0 -0
  67. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/functional/initialization.py +0 -0
  68. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/functional/patches.py +0 -0
  69. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/__init__.py +0 -0
  70. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/atcnet.py +0 -0
  71. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/attentionbasenet.py +0 -0
  72. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/attn_sleep.py +0 -0
  73. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/axon.py +0 -0
  74. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/barista.py +0 -0
  75. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/base.py +0 -0
  76. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/bendr.py +0 -0
  77. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/brainbert.py +0 -0
  78. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/brainmodule.py +0 -0
  79. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/brainomni.py +0 -0
  80. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/brant.py +0 -0
  81. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/cbramod.py +0 -0
  82. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/codebrain.py +0 -0
  83. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/config.py +0 -0
  84. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/contrawr.py +0 -0
  85. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/csbrain.py +0 -0
  86. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/dance.py +0 -0
  87. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/deep4.py +0 -0
  88. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/deepsleepnet.py +0 -0
  89. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/dgcnn.py +0 -0
  90. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/diver1.py +0 -0
  91. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/duin.py +0 -0
  92. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/eeg_clip.py +0 -0
  93. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/eeginception_erp.py +0 -0
  94. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/eeginception_mi.py +0 -0
  95. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/eegitnet.py +0 -0
  96. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/eegminer.py +0 -0
  97. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/eegnet.py +0 -0
  98. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/eegnex.py +0 -0
  99. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/eegsimpleconv.py +0 -0
  100. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/eegsym.py +0 -0
  101. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/eegtcnet.py +0 -0
  102. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/emg2qwerty.py +0 -0
  103. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/epint.py +0 -0
  104. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/fbcnet.py +0 -0
  105. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/fblightconvnet.py +0 -0
  106. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/fbmsnet.py +0 -0
  107. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/gcnsnet.py +0 -0
  108. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/guetschel2026.py +0 -0
  109. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/hybrid.py +0 -0
  110. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/ifnet.py +0 -0
  111. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/labram.py +0 -0
  112. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/mapa.py +0 -0
  113. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/meta_neuromotor.py +0 -0
  114. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/msvtnet.py +0 -0
  115. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/mvpformer.py +0 -0
  116. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/neuropose.py +0 -0
  117. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/patchedtransformer.py +0 -0
  118. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/popt.py +0 -0
  119. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/reve.py +0 -0
  120. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/sccnet.py +0 -0
  121. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/seizure_transformer.py +0 -0
  122. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/sensingdynamics.py +0 -0
  123. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/shallow_fbcsp.py +0 -0
  124. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/signal_jepa.py +0 -0
  125. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/sinc_shallow.py +0 -0
  126. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/sleep_stager_blanco_2020.py +0 -0
  127. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/sleep_stager_chambon_2018.py +0 -0
  128. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/sleepfm.py +0 -0
  129. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/sparcnet.py +0 -0
  130. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/sstdpn.py +0 -0
  131. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/steegformer.py +0 -0
  132. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/summary.csv +0 -0
  133. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/syncnet.py +0 -0
  134. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/tcformer.py +0 -0
  135. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/tcn.py +0 -0
  136. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/tfm_tokenizer.py +0 -0
  137. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/tidnet.py +0 -0
  138. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/tmsanet.py +0 -0
  139. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/tsinception.py +0 -0
  140. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/usleep.py +0 -0
  141. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/util.py +0 -0
  142. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/vemg2pose.py +0 -0
  143. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/models/zuna.py +0 -0
  144. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/modules/activation.py +0 -0
  145. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/modules/attention.py +0 -0
  146. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/modules/blocks.py +0 -0
  147. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/modules/channels.py +0 -0
  148. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/modules/convolution.py +0 -0
  149. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/modules/dance_modules.py +0 -0
  150. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/modules/filter.py +0 -0
  151. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/modules/linear.py +0 -0
  152. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/modules/linear_attention.py +0 -0
  153. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/modules/parametrization.py +0 -0
  154. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/modules/quantization.py +0 -0
  155. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/modules/stats.py +0 -0
  156. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/modules/util.py +0 -0
  157. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/modules/wrapper.py +0 -0
  158. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/preprocessing/__init__.py +0 -0
  159. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/preprocessing/eegprep_preprocess.py +0 -0
  160. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/preprocessing/mne_preprocess.py +0 -0
  161. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/preprocessing/preprocess.py +0 -0
  162. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/preprocessing/util.py +0 -0
  163. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/preprocessing/windowers.py +0 -0
  164. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/regressor.py +0 -0
  165. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/samplers/__init__.py +0 -0
  166. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/samplers/base.py +0 -0
  167. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/samplers/ssl.py +0 -0
  168. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/training/__init__.py +0 -0
  169. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/training/callbacks.py +0 -0
  170. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/training/losses.py +0 -0
  171. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/training/scoring.py +0 -0
  172. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/util.py +0 -0
  173. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/visualization/__init__.py +0 -0
  174. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/visualization/activations.py +0 -0
  175. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/visualization/attribution.py +0 -0
  176. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/visualization/confusion_matrices.py +0 -0
  177. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/visualization/metrics.py +0 -0
  178. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/visualization/sanity.py +0 -0
  179. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode/visualization/topology.py +0 -0
  180. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode.egg-info/SOURCES.txt +0 -0
  181. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode.egg-info/dependency_links.txt +0 -0
  182. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/braindecode.egg-info/top_level.txt +0 -0
  183. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/Makefile +0 -0
  184. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/_templates/autosummary/class.rst +0 -0
  185. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/_templates/autosummary/class_in_subdir.rst +0 -0
  186. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/_templates/autosummary/function.rst +0 -0
  187. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/_templates/autosummary/function_in_subdir.rst +0 -0
  188. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/agent_docs.rst +0 -0
  189. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/cite.rst +0 -0
  190. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/conf.py +0 -0
  191. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/help.rst +0 -0
  192. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/index.rst +0 -0
  193. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/install/install.rst +0 -0
  194. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/install/install_pip.rst +0 -0
  195. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/install/install_source.rst +0 -0
  196. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/models/categorization/attention.rst +0 -0
  197. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/models/categorization/channel.rst +0 -0
  198. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/models/categorization/convolution.rst +0 -0
  199. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/models/categorization/filterbank.rst +0 -0
  200. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/models/categorization/gnn.rst +0 -0
  201. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/models/categorization/interpretable.rst +0 -0
  202. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/models/categorization/lbm.rst +0 -0
  203. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/models/categorization/recurrent.rst +0 -0
  204. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/models/categorization/spd.rst +0 -0
  205. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/models/models.rst +0 -0
  206. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/models/models_categorization.rst +0 -0
  207. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/models/models_table.rst +0 -0
  208. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/models/models_visualization.rst +0 -0
  209. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/sg_execution_times.rst +0 -0
  210. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/docs/user_guide/channel_strategies.rst +0 -0
  211. {braindecode-1.8.1.dev169814997 → braindecode-1.8.1.dev169869285}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: braindecode
3
- Version: 1.8.1.dev169814997
3
+ Version: 1.8.1.dev169869285
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>
@@ -50,7 +50,6 @@ Provides-Extra: tests
50
50
  Requires-Dist: pytest<9.1; extra == "tests"
51
51
  Requires-Dist: pytest-cov; extra == "tests"
52
52
  Requires-Dist: pytest-xdist>=3.8.0; extra == "tests"
53
- Requires-Dist: pytest-timeout; extra == "tests"
54
53
  Requires-Dist: codecov; extra == "tests"
55
54
  Requires-Dist: pytest_cases; extra == "tests"
56
55
  Requires-Dist: mypy; extra == "tests"
@@ -4,10 +4,9 @@ from warnings import warn
4
4
  import torch
5
5
  import torch.nn as nn
6
6
 
7
- from braindecode.functional import spectral_input
7
+ from braindecode.functional import sinusoidal_positional_encoding, spectral_input
8
8
  from braindecode.models.base import EEGModuleMixin
9
9
  from braindecode.models.util import warn_if_sfreq_differs
10
- from braindecode.modules import SinusoidalPositionalEncoding
11
10
  from braindecode.modules.linear_attention import LinearAttentionTransformer
12
11
 
13
12
  # -----------------------------------------------------------------------------
@@ -356,6 +355,60 @@ class _ClassificationHead(nn.Sequential):
356
355
  return out
357
356
 
358
357
 
358
+ class _PositionalEncoding(nn.Module):
359
+ r"""
360
+ Positional Encoding.
361
+
362
+ We first create a `pe` zero matrix of shape (max_len, d_model) where max_len is the
363
+ the maximum length of the sequence, and emb_size is the size of the embedding.
364
+
365
+ Then we create a `position` tensor of shape (max_len, 1) with indices from 0 to max_len
366
+ and a `div_term` tensor of shape (d_model // 2) with the exponential of the
367
+ multiplication of the indices from 0 to d_model by -log(10000.0) / d_model.
368
+
369
+ For more details about the positional encoding, see the `Attention is All You Need` paper.
370
+
371
+ Parameters
372
+ ----------
373
+ emb_size: int
374
+ The size of the embedding layer
375
+ dropout: float
376
+ The dropout rate
377
+ max_len: int
378
+ The maximum length of the sequence
379
+ drop_prob : float, default=0.5
380
+ The dropout rate for regularization. Values should be between 0 and 1.
381
+
382
+ Returns
383
+ -------
384
+ out: Tensor
385
+ (batch, max_len, d_model)
386
+ """
387
+
388
+ def __init__(self, emb_size: int, drop_prob: float = 0.1, max_len: int = 1000):
389
+ super(_PositionalEncoding, self).__init__()
390
+
391
+ # Compute the positional encodings once (shared sinusoidal primitive).
392
+ pe = sinusoidal_positional_encoding(max_len, emb_size).unsqueeze(0)
393
+ self.register_buffer("pe", pe)
394
+ self.dropout = nn.Dropout(p=drop_prob)
395
+
396
+ def forward(self, x: torch.FloatTensor) -> torch.FloatTensor:
397
+ """
398
+ Parameters
399
+ ----------
400
+ x: FloatTensor
401
+ `embeddings,` shape (batch, max_len, d_model)
402
+
403
+ Returns
404
+ -------
405
+ Tensor
406
+ `encoder input`, shape (batch, max_len, d_model)
407
+ """
408
+ x = x + self.pe[:, : x.size(1)]
409
+ return self.dropout(x)
410
+
411
+
359
412
  class _BIOTEncoder(nn.Module):
360
413
  r"""
361
414
  BIOT Encoder.
@@ -416,10 +469,7 @@ class _BIOTEncoder(nn.Module):
416
469
  depth=n_layers,
417
470
  attn_layer_dropout=attn_layer_dropout,
418
471
  )
419
- # persistent: released checkpoints carry the table
420
- self.positional_encoding = SinusoidalPositionalEncoding(
421
- 1000, emb_size, drop_prob, persistent=True
422
- )
472
+ self.positional_encoding = _PositionalEncoding(emb_size, drop_prob=drop_prob)
423
473
 
424
474
  # channel token, N_channels >= your actual channels
425
475
  self.channel_tokens = nn.Embedding(
@@ -10,7 +10,6 @@ classification from Wei Zhao et al. (2024).
10
10
  from __future__ import annotations
11
11
 
12
12
  import math
13
- from collections import OrderedDict
14
13
  from typing import Optional
15
14
 
16
15
  import torch
@@ -21,9 +20,8 @@ from torch import Tensor, nn
21
20
  from braindecode.models.base import EEGModuleMixin
22
21
  from braindecode.modules import (
23
22
  FeedForwardBlock,
24
- LearnedPositionalEncoding,
25
23
  MultiHeadAttention,
26
- PostNormTransformerBlock,
24
+ PostNormResidual,
27
25
  )
28
26
 
29
27
 
@@ -179,47 +177,19 @@ class CTNet(EEGModuleMixin, nn.Module, license="mit"):
179
177
  activation=self.activation_patch,
180
178
  )
181
179
 
182
- length = 100
183
- needed = max(
184
- int(self.n_times / (self.pool_size_1 * self.pool_size_1)),
185
- self.sequence_length or 0,
186
- )
187
- if needed > length:
188
- warn(
189
- "the temporal dimensional is too long for this default length. "
190
- "The length parameter will be automatically adjusted to "
191
- "avoid inference issues."
192
- )
193
- length = needed
194
- self.position = LearnedPositionalEncoding(
195
- length, self.embed_dim, self.att_positional_drop_prob
180
+ self.position = _PositionalEncoding(
181
+ emb_size=self.embed_dim,
182
+ drop_prob=self.att_positional_drop_prob,
183
+ n_times=self.n_times,
184
+ pool_size=self.pool_size_1,
185
+ sequence_length=self.sequence_length,
196
186
  )
197
187
 
198
- # ``layers`` and the ``Sequential`` around the attention keep the
199
- # parameter names of saved checkpoints.
200
- self.trans = nn.Sequential(
201
- OrderedDict(
202
- layers=nn.Sequential(
203
- *[
204
- PostNormTransformerBlock(
205
- self.embed_dim,
206
- nn.Sequential(
207
- MultiHeadAttention(self.embed_dim, self.num_heads, 0.5)
208
- ),
209
- nn.Sequential(
210
- FeedForwardBlock(
211
- self.embed_dim,
212
- expansion=4,
213
- drop_p=0.5,
214
- activation=self.activation_transformer,
215
- )
216
- ),
217
- 0.5,
218
- )
219
- for _ in range(self.num_layers)
220
- ]
221
- )
222
- )
188
+ self.trans = _TransformerEncoder(
189
+ self.num_heads,
190
+ self.num_layers,
191
+ self.embed_dim,
192
+ activation=self.activation_transformer,
223
193
  )
224
194
 
225
195
  self.flatten_drop_layer = nn.Sequential(
@@ -421,3 +391,141 @@ class _PatchEmbeddingEEGNet(nn.Module):
421
391
  x = layer(x)
422
392
  x = self.projection(x)
423
393
  return x
394
+
395
+
396
+ class _TransformerEncoderBlock(nn.Module):
397
+ def __init__(
398
+ self,
399
+ dim_feedforward: int,
400
+ num_heads: int = 4,
401
+ drop_prob: float = 0.5,
402
+ forward_expansion: int = 4,
403
+ forward_drop_p: float = 0.5,
404
+ activation: type[nn.Module] = nn.GELU,
405
+ ):
406
+ super().__init__()
407
+ self.attention = PostNormResidual(
408
+ nn.Sequential(
409
+ MultiHeadAttention(dim_feedforward, num_heads, drop_prob),
410
+ ),
411
+ dim_feedforward,
412
+ drop_prob,
413
+ )
414
+ self.feed_forward = PostNormResidual(
415
+ nn.Sequential(
416
+ FeedForwardBlock(
417
+ dim_feedforward,
418
+ expansion=forward_expansion,
419
+ drop_p=forward_drop_p,
420
+ activation=activation,
421
+ ),
422
+ ),
423
+ dim_feedforward,
424
+ drop_prob,
425
+ )
426
+
427
+ def forward(self, x: Tensor) -> Tensor:
428
+ """
429
+ Forward pass of the transformer encoder block.
430
+
431
+ Parameters
432
+ ----------
433
+ x : Tensor
434
+ Input tensor.
435
+ **kwargs : Any
436
+ Additional arguments.
437
+
438
+ Returns
439
+ -------
440
+ Tensor
441
+ Output tensor after transformer encoder block.
442
+ """
443
+ x = self.attention(x)
444
+ x = self.feed_forward(x)
445
+ return x
446
+
447
+
448
+ class _TransformerEncoder(nn.Module):
449
+ def __init__(
450
+ self,
451
+ nheads: int,
452
+ depth: int,
453
+ dim_feedforward: int,
454
+ activation: type[nn.Module] = nn.GELU,
455
+ ):
456
+ super().__init__()
457
+ self.layers = nn.Sequential(
458
+ *[
459
+ _TransformerEncoderBlock(
460
+ dim_feedforward=dim_feedforward,
461
+ num_heads=nheads,
462
+ activation=activation,
463
+ )
464
+ for _ in range(depth)
465
+ ]
466
+ )
467
+
468
+ def forward(self, x: Tensor) -> Tensor:
469
+ """
470
+ Forward pass of the transformer encoder.
471
+
472
+ Parameters
473
+ ----------
474
+ x : Tensor
475
+ Input tensor.
476
+
477
+ Returns
478
+ -------
479
+ Tensor
480
+ Output tensor after transformer encoder.
481
+ """
482
+ return self.layers(x)
483
+
484
+
485
+ class _PositionalEncoding(nn.Module):
486
+ def __init__(
487
+ self,
488
+ n_times: int,
489
+ emb_size: int,
490
+ length: int = 100,
491
+ drop_prob: float = 0.1,
492
+ pool_size: int = 8,
493
+ sequence_length: int | None = None,
494
+ ):
495
+ super().__init__()
496
+ self.pool_size = pool_size
497
+ self.n_times = n_times
498
+
499
+ # n_times / pool_size**2 is the sequence length only when both pooling
500
+ # sizes are equal; also cover the actual length (e.g. pool_size_2 <
501
+ # pool_size_1), so that the encoding is never shorter than the input
502
+ needed = max(int(n_times / (pool_size * pool_size)), sequence_length or 0)
503
+ if needed > length:
504
+ warn(
505
+ "the temporal dimensional is too long for this default length. "
506
+ "The length parameter will be automatically adjusted to "
507
+ "avoid inference issues."
508
+ )
509
+ length = needed
510
+
511
+ self.dropout = nn.Dropout(drop_prob)
512
+ self.encoding = nn.Parameter(torch.randn(1, length, emb_size))
513
+
514
+ def forward(self, x: Tensor) -> Tensor:
515
+ """
516
+ Forward pass of the positional encoding.
517
+
518
+ Parameters
519
+ ----------
520
+ x : Tensor
521
+ Input tensor of shape (batch_size, sequence_length, embedding_dim).
522
+
523
+ Returns
524
+ -------
525
+ Tensor
526
+ Tensor with positional encoding added.
527
+ """
528
+ seq_length = x.size(1)
529
+ encoding = self.encoding[:, :seq_length, :]
530
+ x = x + encoding
531
+ return self.dropout(x)
@@ -9,11 +9,7 @@ from einops.layers.torch import Rearrange
9
9
  from torch import Tensor, nn
10
10
 
11
11
  from braindecode.models.base import EEGModuleMixin, _too_short_input_error
12
- from braindecode.modules import (
13
- FeedForwardBlock,
14
- MultiHeadAttention,
15
- PreNormTransformerBlock,
16
- )
12
+ from braindecode.modules import FeedForwardBlock, MultiHeadAttention, Residual
17
13
 
18
14
 
19
15
  class EEGConformer(EEGModuleMixin, nn.Module):
@@ -254,21 +250,12 @@ class EEGConformer(EEGModuleMixin, nn.Module):
254
250
  else:
255
251
  self.final_fc_length = final_fc_length
256
252
 
257
- self.transformer = nn.Sequential(
258
- *[
259
- PreNormTransformerBlock(
260
- n_filters_time,
261
- MultiHeadAttention(n_filters_time, num_heads, att_drop_prob),
262
- FeedForwardBlock(
263
- n_filters_time,
264
- expansion=4,
265
- drop_p=att_drop_prob,
266
- activation=activation_transfor,
267
- ),
268
- att_drop_prob,
269
- )
270
- for _ in range(num_layers)
271
- ]
253
+ self.transformer = _TransformerEncoder(
254
+ num_layers=num_layers,
255
+ emb_size=n_filters_time,
256
+ num_heads=num_heads,
257
+ att_drop=att_drop_prob,
258
+ activation=activation_transfor,
272
259
  )
273
260
 
274
261
  self.fc = _FullyConnected(
@@ -377,6 +364,74 @@ class _PatchEmbedding(nn.Module):
377
364
  return x
378
365
 
379
366
 
367
+ class _TransformerEncoderBlock(nn.Sequential):
368
+ def __init__(
369
+ self,
370
+ emb_size,
371
+ num_heads,
372
+ att_drop,
373
+ forward_expansion=4,
374
+ activation: type[nn.Module] = nn.GELU,
375
+ ):
376
+ super().__init__(
377
+ Residual(
378
+ nn.Sequential(
379
+ nn.LayerNorm(emb_size),
380
+ MultiHeadAttention(emb_size, num_heads, att_drop),
381
+ nn.Dropout(att_drop),
382
+ )
383
+ ),
384
+ Residual(
385
+ nn.Sequential(
386
+ nn.LayerNorm(emb_size),
387
+ FeedForwardBlock(
388
+ emb_size,
389
+ expansion=forward_expansion,
390
+ drop_p=att_drop,
391
+ activation=activation,
392
+ ),
393
+ nn.Dropout(att_drop),
394
+ )
395
+ ),
396
+ )
397
+
398
+
399
+ class _TransformerEncoder(nn.Sequential):
400
+ r"""Transformer encoder module for the transformer encoder.
401
+
402
+ Similar to the layers used in ViT.
403
+
404
+ Parameters
405
+ ----------
406
+ num_layers : int
407
+ Number of transformer encoder blocks.
408
+ emb_size : int
409
+ Embedding size of the transformer encoder.
410
+ num_heads : int
411
+ Number of attention heads.
412
+ att_drop : float
413
+ Dropout probability for the attention layers.
414
+
415
+ """
416
+
417
+ def __init__(
418
+ self,
419
+ num_layers,
420
+ emb_size,
421
+ num_heads,
422
+ att_drop,
423
+ activation: type[nn.Module] = nn.GELU,
424
+ ):
425
+ super().__init__(
426
+ *[
427
+ _TransformerEncoderBlock(
428
+ emb_size, num_heads, att_drop, activation=activation
429
+ )
430
+ for _ in range(num_layers)
431
+ ]
432
+ )
433
+
434
+
380
435
  class _FullyConnected(nn.Module):
381
436
  def __init__(
382
437
  self,
@@ -13,7 +13,7 @@ from torch import nn
13
13
  from braindecode.functional import spectral_input
14
14
  from braindecode.models.base import EEGModuleMixin
15
15
  from braindecode.models.util import warn_if_sfreq_differs
16
- from braindecode.modules import PatchTokenizer, PreNormBlock, TimmAttention
16
+ from braindecode.modules import DropPath, PatchTokenizer, TimmAttention
17
17
 
18
18
 
19
19
  class EEGDINO(EEGModuleMixin, nn.Module):
@@ -236,21 +236,8 @@ class EEGDINO(EEGModuleMixin, nn.Module):
236
236
  self.emb_dim = self.patch_embedding.emb_dim
237
237
 
238
238
  self.encoder_layers = nn.ModuleList(
239
- PreNormBlock(
240
- self.emb_dim,
241
- # BEiT attention with q/v biases, in the reference op order
242
- TimmAttention(
243
- self.emb_dim,
244
- nhead,
245
- qv_bias=True,
246
- attn_drop=drop_prob,
247
- proj_drop=drop_prob,
248
- exact=True,
249
- ),
250
- _MLP(
251
- self.emb_dim, dim_feedforward, activation=activation, drop=drop_prob
252
- ),
253
- drop_path=drop_prob,
239
+ _TransformerEncoderLayer(
240
+ self.emb_dim, nhead, dim_feedforward, activation, drop_prob
254
241
  )
255
242
  for _ in range(n_layer)
256
243
  )
@@ -456,6 +443,33 @@ class _PatchEmbedding(nn.Module):
456
443
  return patch_emb + temporal_emb.permute(0, 2, 3, 1)
457
444
 
458
445
 
446
+ class _TransformerEncoderLayer(nn.Module):
447
+ """Pre-norm transformer block (no LayerScale, matching the released config)."""
448
+
449
+ def __init__(
450
+ self, emb_dim, nhead, dim_feedforward, activation=nn.GELU, drop_prob=0.1
451
+ ):
452
+ super().__init__()
453
+ self.norm1 = nn.LayerNorm(emb_dim)
454
+ # BEiT attention with q/v biases, in the reference op order
455
+ self.attn = TimmAttention(
456
+ emb_dim,
457
+ nhead,
458
+ qv_bias=True,
459
+ attn_drop=drop_prob,
460
+ proj_drop=drop_prob,
461
+ exact=True,
462
+ )
463
+ self.drop_path = DropPath(drop_prob) if drop_prob > 0.0 else nn.Identity()
464
+ self.norm2 = nn.LayerNorm(emb_dim)
465
+ self.mlp = _MLP(emb_dim, dim_feedforward, activation=activation, drop=drop_prob)
466
+
467
+ def forward(self, x):
468
+ x = x + self.drop_path(self.attn(self.norm1(x)))
469
+ x = x + self.drop_path(self.mlp(self.norm2(x)))
470
+ return x
471
+
472
+
459
473
  class _MLP(nn.Module):
460
474
  """Feed-forward block; ``fc1``/``fc2`` names match the released checkpoint."""
461
475
 
@@ -12,7 +12,7 @@ from torch import nn
12
12
 
13
13
  from braindecode.functional import init_weights_
14
14
  from braindecode.models.base import EEGModuleMixin
15
- from braindecode.modules import PreNormBlock, TimmAttention, TimmMlp
15
+ from braindecode.modules import DropPath, TimmAttention, TimmMlp
16
16
  from braindecode.modules.convolution import Conv1dWithConstraint
17
17
  from braindecode.modules.linear import LinearWithConstraint
18
18
  from braindecode.util import resolve_montage_name
@@ -734,6 +734,84 @@ def _apply_mask_t(mask_t, x):
734
734
  return masked_x
735
735
 
736
736
 
737
+ class _Block(nn.Module):
738
+ """
739
+ Transformer Block consisting of Self-Attention and MLP.
740
+
741
+ This is a standard Transformer encoder block that applies:
742
+ 1. Layer Normalization
743
+ 2. Multi-Head Self-Attention
744
+ 3. Residual Connection with DropPath
745
+ 4. Layer Normalization
746
+ 5. MLP
747
+ 6. Residual Connection with DropPath
748
+
749
+ Parameters
750
+ ----------
751
+ dim : int
752
+ Input and output embedding dimension.
753
+ num_heads : int
754
+ Number of attention heads.
755
+ mlp_ratio : float, default=4.0
756
+ Ratio of MLP hidden dimension to embedding dimension.
757
+ qkv_bias : bool, default=False
758
+ If True, add a learnable bias to query, key, value projections.
759
+ drop : float, default=0.0
760
+ Dropout probability for MLP and projection layers.
761
+ attn_drop : float, default=0.0
762
+ Dropout probability for attention weights.
763
+ drop_path : float, default=0.0
764
+ Stochastic depth rate.
765
+ act_layer : nn.Module, default=nn.GELU
766
+ Activation function.
767
+ norm_layer : nn.Module, default=nn.LayerNorm
768
+ Normalization layer.
769
+ return_attention : bool, default=False
770
+ If True, returns attention weights instead of the output tensor.
771
+ """
772
+
773
+ def __init__(
774
+ self,
775
+ dim,
776
+ num_heads,
777
+ mlp_ratio=4.0,
778
+ qkv_bias=False,
779
+ drop=0.0,
780
+ attn_drop=0.0,
781
+ drop_path=0.0,
782
+ act_layer=nn.GELU,
783
+ norm_layer=nn.LayerNorm,
784
+ return_attention=False,
785
+ ):
786
+ super().__init__()
787
+ self.return_attention = return_attention
788
+ self.norm1 = norm_layer(dim)
789
+ self.attn = TimmAttention(
790
+ dim,
791
+ num_heads=num_heads,
792
+ qkv_bias=qkv_bias,
793
+ attn_drop=attn_drop,
794
+ proj_drop=drop,
795
+ )
796
+ self.drop_path = DropPath(drop_path) if drop_path > 0.0 else nn.Identity()
797
+ self.norm2 = norm_layer(dim)
798
+ mlp_hidden_dim = int(dim * mlp_ratio)
799
+ self.mlp = TimmMlp(
800
+ in_features=dim,
801
+ hidden_features=mlp_hidden_dim,
802
+ act_layer=act_layer,
803
+ drop=drop,
804
+ )
805
+
806
+ def forward(self, x):
807
+ y = self.attn(self.norm1(x), need_weights=self.return_attention)
808
+ if self.return_attention:
809
+ return y
810
+ x = x + self.drop_path(y)
811
+ x = x + self.drop_path(self.mlp(self.norm2(x)))
812
+ return x
813
+
814
+
737
815
  class _PatchEmbed(nn.Module):
738
816
  """
739
817
  Splits the EEG signal into patches and embeds them.
@@ -930,7 +1008,6 @@ class _EEGTransformer(nn.Module):
930
1008
  self.embed_dim = embed_dim
931
1009
  self.embed_num = embed_num
932
1010
  self.num_heads = num_heads
933
- self.return_attention_layer = return_attention_layer
934
1011
 
935
1012
  self.patch_embed = patch_module(
936
1013
  n_chans=n_chans,
@@ -952,22 +1029,16 @@ class _EEGTransformer(nn.Module):
952
1029
 
953
1030
  self.blocks = nn.ModuleList(
954
1031
  [
955
- PreNormBlock(
956
- embed_dim,
957
- TimmAttention(
958
- embed_dim,
959
- num_heads=num_heads,
960
- qkv_bias=qkv_bias,
961
- attn_drop=attn_drop_rate,
962
- proj_drop=drop_rate,
963
- ),
964
- TimmMlp(
965
- in_features=embed_dim,
966
- hidden_features=int(embed_dim * mlp_ratio),
967
- drop=drop_rate,
968
- ),
969
- norm_layer=norm_layer,
1032
+ _Block(
1033
+ dim=embed_dim,
1034
+ num_heads=num_heads,
1035
+ mlp_ratio=mlp_ratio,
1036
+ qkv_bias=qkv_bias,
1037
+ drop=drop_rate,
1038
+ attn_drop=attn_drop_rate,
970
1039
  drop_path=dpr[i],
1040
+ norm_layer=norm_layer,
1041
+ return_attention=(i + 1) == return_attention_layer,
971
1042
  )
972
1043
  for i in range(depth)
973
1044
  ]
@@ -1092,9 +1163,9 @@ class _EEGTransformer(nn.Module):
1092
1163
 
1093
1164
  # -- fwd prop
1094
1165
  for i, blk in enumerate(self.blocks):
1095
- if i + 1 == self.return_attention_layer:
1096
- return blk.attn(blk.norm1(x), need_weights=True)
1097
1166
  x = blk(x)
1167
+ if blk.return_attention:
1168
+ return x
1098
1169
 
1099
1170
  # Extract only the summary tokens (used for global representation)
1100
1171
  # x shape: (batch * n_patches, embed_num, embed_dim)