Braindecode 1.8.1.dev180761562__tar.gz → 1.8.1.dev180835552__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.dev180761562/braindecode.egg-info → braindecode-1.8.1.dev180835552}/PKG-INFO +1 -1
  2. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/augmentation/__init__.py +2 -0
  3. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/augmentation/functional.py +96 -3
  4. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/augmentation/transforms.py +93 -0
  5. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/functional/initialization.py +14 -9
  6. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/atcnet.py +11 -8
  7. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/biot.py +4 -2
  8. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/ctnet.py +9 -3
  9. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/labram.py +11 -1
  10. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/luna.py +4 -1
  11. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/medformer.py +12 -15
  12. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/sinc_shallow.py +15 -0
  13. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/tmsanet.py +11 -0
  14. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/zuna.py +10 -10
  15. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/modules/attention.py +25 -10
  16. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/modules/blocks.py +5 -2
  17. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/regressor.py +6 -1
  18. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/training/scoring.py +4 -1
  19. braindecode-1.8.1.dev180835552/braindecode/version.py +1 -0
  20. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552/braindecode.egg-info}/PKG-INFO +1 -1
  21. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/api.rst +4 -0
  22. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/whats_new.rst +38 -0
  23. braindecode-1.8.1.dev180761562/braindecode/version.py +0 -1
  24. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/LICENSE.txt +0 -0
  25. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/MANIFEST.in +0 -0
  26. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/NOTICE.txt +0 -0
  27. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/README.rst +0 -0
  28. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/__init__.py +0 -0
  29. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/augmentation/base.py +0 -0
  30. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/classifier.py +0 -0
  31. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datasets/__init__.py +0 -0
  32. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datasets/_notebook_viewer.py +0 -0
  33. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datasets/base.py +0 -0
  34. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datasets/bbci.py +0 -0
  35. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datasets/bcicomp.py +0 -0
  36. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datasets/bids/__init__.py +0 -0
  37. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datasets/bids/datasets.py +0 -0
  38. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datasets/bids/format.py +0 -0
  39. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datasets/bids/hub.py +0 -0
  40. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datasets/bids/hub_format.py +0 -0
  41. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datasets/bids/hub_io.py +0 -0
  42. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datasets/bids/hub_validation.py +0 -0
  43. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datasets/bids/iterable.py +0 -0
  44. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datasets/chb_mit.py +0 -0
  45. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datasets/collate.py +0 -0
  46. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datasets/mne.py +0 -0
  47. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datasets/moabb.py +0 -0
  48. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datasets/nmt.py +0 -0
  49. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datasets/registry.py +0 -0
  50. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datasets/siena.py +0 -0
  51. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datasets/sleep_physio_challe_18.py +0 -0
  52. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datasets/sleep_physionet.py +0 -0
  53. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datasets/tuh.py +0 -0
  54. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datasets/utils.py +0 -0
  55. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datasets/xy.py +0 -0
  56. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datautil/__init__.py +0 -0
  57. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datautil/channel_utils.py +0 -0
  58. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datautil/hub_formats.py +0 -0
  59. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datautil/serialization.py +0 -0
  60. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/datautil/util.py +0 -0
  61. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/eegneuralnet.py +0 -0
  62. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/functional/__init__.py +0 -0
  63. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/functional/_real_dft.py +0 -0
  64. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/functional/functions.py +0 -0
  65. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/__init__.py +0 -0
  66. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/attentionbasenet.py +0 -0
  67. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/attn_sleep.py +0 -0
  68. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/axon.py +0 -0
  69. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/barista.py +0 -0
  70. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/base.py +0 -0
  71. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/bendr.py +0 -0
  72. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/brainbert.py +0 -0
  73. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/brainmodule.py +0 -0
  74. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/brainomni.py +0 -0
  75. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/brant.py +0 -0
  76. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/cbramod.py +0 -0
  77. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/codebrain.py +0 -0
  78. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/config.py +0 -0
  79. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/contrawr.py +0 -0
  80. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/csbrain.py +0 -0
  81. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/dance.py +0 -0
  82. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/deep4.py +0 -0
  83. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/deepsleepnet.py +0 -0
  84. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/dgcnn.py +0 -0
  85. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/diver1.py +0 -0
  86. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/duin.py +0 -0
  87. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/eeg_clip.py +0 -0
  88. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/eegconformer.py +0 -0
  89. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/eegdino.py +0 -0
  90. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/eeginception_erp.py +0 -0
  91. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/eeginception_mi.py +0 -0
  92. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/eegitnet.py +0 -0
  93. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/eegminer.py +0 -0
  94. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/eegnet.py +0 -0
  95. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/eegnex.py +0 -0
  96. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/eegpt.py +0 -0
  97. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/eegsimpleconv.py +0 -0
  98. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/eegsym.py +0 -0
  99. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/eegtcnet.py +0 -0
  100. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/emg2qwerty.py +0 -0
  101. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/epint.py +0 -0
  102. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/fbcnet.py +0 -0
  103. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/fblightconvnet.py +0 -0
  104. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/fbmsnet.py +0 -0
  105. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/gcnsnet.py +0 -0
  106. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/guetschel2026.py +0 -0
  107. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/hybrid.py +0 -0
  108. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/ifnet.py +0 -0
  109. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/mapa.py +0 -0
  110. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/meta_neuromotor.py +0 -0
  111. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/mirepnet.py +0 -0
  112. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/mscformer.py +0 -0
  113. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/msvtnet.py +0 -0
  114. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/mvpformer.py +0 -0
  115. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/neuropose.py +0 -0
  116. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/neurorvq.py +0 -0
  117. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/neurorvq_tokenizer.py +0 -0
  118. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/patchedtransformer.py +0 -0
  119. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/popt.py +0 -0
  120. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/reve.py +0 -0
  121. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/sccnet.py +0 -0
  122. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/seizure_transformer.py +0 -0
  123. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/sensingdynamics.py +0 -0
  124. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/shallow_fbcsp.py +0 -0
  125. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/signal_jepa.py +0 -0
  126. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/sleep_stager_blanco_2020.py +0 -0
  127. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/sleep_stager_chambon_2018.py +0 -0
  128. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/sleepfm.py +0 -0
  129. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/sparcnet.py +0 -0
  130. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/sstdpn.py +0 -0
  131. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/steegformer.py +0 -0
  132. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/summary.csv +0 -0
  133. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/syncnet.py +0 -0
  134. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/tcformer.py +0 -0
  135. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/tcn.py +0 -0
  136. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/tfm_tokenizer.py +0 -0
  137. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/tidnet.py +0 -0
  138. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/tsinception.py +0 -0
  139. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/usleep.py +0 -0
  140. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/util.py +0 -0
  141. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/models/vemg2pose.py +0 -0
  142. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/modules/__init__.py +0 -0
  143. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/modules/activation.py +0 -0
  144. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/modules/channels.py +0 -0
  145. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/modules/convolution.py +0 -0
  146. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/modules/dance_modules.py +0 -0
  147. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/modules/filter.py +0 -0
  148. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/modules/layers.py +0 -0
  149. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/modules/linear.py +0 -0
  150. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/modules/linear_attention.py +0 -0
  151. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/modules/parametrization.py +0 -0
  152. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/modules/popt_modules.py +0 -0
  153. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/modules/quantization.py +0 -0
  154. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/modules/stats.py +0 -0
  155. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/modules/util.py +0 -0
  156. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/modules/wrapper.py +0 -0
  157. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/preprocessing/__init__.py +0 -0
  158. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/preprocessing/eegprep_preprocess.py +0 -0
  159. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/preprocessing/mne_preprocess.py +0 -0
  160. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/preprocessing/preprocess.py +0 -0
  161. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/preprocessing/util.py +0 -0
  162. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/preprocessing/windowers.py +0 -0
  163. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/samplers/__init__.py +0 -0
  164. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/samplers/base.py +0 -0
  165. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/samplers/ssl.py +0 -0
  166. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/training/__init__.py +0 -0
  167. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/training/callbacks.py +0 -0
  168. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/training/losses.py +0 -0
  169. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/util.py +0 -0
  170. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/visualization/__init__.py +0 -0
  171. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/visualization/activations.py +0 -0
  172. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/visualization/attribution.py +0 -0
  173. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/visualization/confusion_matrices.py +0 -0
  174. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/visualization/frequency.py +0 -0
  175. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/visualization/metrics.py +0 -0
  176. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/visualization/sanity.py +0 -0
  177. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode/visualization/topology.py +0 -0
  178. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode.egg-info/SOURCES.txt +0 -0
  179. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode.egg-info/dependency_links.txt +0 -0
  180. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode.egg-info/requires.txt +0 -0
  181. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/braindecode.egg-info/top_level.txt +0 -0
  182. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/Makefile +0 -0
  183. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/_templates/autosummary/class.rst +0 -0
  184. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/_templates/autosummary/class_in_subdir.rst +0 -0
  185. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/_templates/autosummary/function.rst +0 -0
  186. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/_templates/autosummary/function_in_subdir.rst +0 -0
  187. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/agent_docs.rst +0 -0
  188. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/cite.rst +0 -0
  189. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/conf.py +0 -0
  190. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/help.rst +0 -0
  191. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/index.rst +0 -0
  192. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/install/install.rst +0 -0
  193. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/install/install_pip.rst +0 -0
  194. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/install/install_source.rst +0 -0
  195. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/models/categorization/attention.rst +0 -0
  196. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/models/categorization/channel.rst +0 -0
  197. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/models/categorization/convolution.rst +0 -0
  198. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/models/categorization/filterbank.rst +0 -0
  199. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/models/categorization/gnn.rst +0 -0
  200. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/models/categorization/interpretable.rst +0 -0
  201. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/models/categorization/lbm.rst +0 -0
  202. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/models/categorization/recurrent.rst +0 -0
  203. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/models/categorization/spd.rst +0 -0
  204. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/models/models.rst +0 -0
  205. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/models/models_categorization.rst +0 -0
  206. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/models/models_table.rst +0 -0
  207. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/models/models_visualization.rst +0 -0
  208. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/sg_execution_times.rst +0 -0
  209. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/docs/user_guide/channel_strategies.rst +0 -0
  210. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/pyproject.toml +0 -0
  211. {braindecode-1.8.1.dev180761562 → braindecode-1.8.1.dev180835552}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: braindecode
3
- Version: 1.8.1.dev180761562
3
+ Version: 1.8.1.dev180835552
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>
@@ -14,6 +14,7 @@ from .transforms import (
14
14
  FrequencyShift,
15
15
  FTSurrogate,
16
16
  GaussianNoise,
17
+ LabelSmoothing,
17
18
  MaskEncoding,
18
19
  Mixup,
19
20
  SegmentationReconstruction,
@@ -40,6 +41,7 @@ __all__ = [
40
41
  "CutMix",
41
42
  "ChannelsDropout",
42
43
  "GaussianNoise",
44
+ "LabelSmoothing",
43
45
  "ChannelsSymmetry",
44
46
  "SmoothTimeMask",
45
47
  "BandstopFilter",
@@ -19,7 +19,7 @@ from mne.filter import notch_filter
19
19
  from scipy.interpolate import Rbf
20
20
  from sklearn.utils import check_random_state
21
21
  from torch.fft import fft, ifft
22
- from torch.nn.functional import pad
22
+ from torch.nn.functional import one_hot, pad
23
23
 
24
24
 
25
25
  def _max_float_dtype(device: torch.device | str) -> torch.dtype:
@@ -1089,10 +1089,12 @@ def mixup(
1089
1089
  Online: https://arxiv.org/abs/1710.09412
1090
1090
  .. [2] https://github.com/facebookresearch/mixup-cifar10/blob/master/train.py
1091
1091
  """
1092
- device = X.device
1093
1092
  batch_size, n_channels, n_times = X.shape
1094
1093
 
1095
- X_mix = torch.zeros((batch_size, n_channels, n_times)).to(device)
1094
+ X_mix = X.new_zeros(
1095
+ (batch_size, n_channels, n_times),
1096
+ dtype=X.dtype if X.is_floating_point() else torch.get_default_dtype(),
1097
+ )
1096
1098
  y_a = y.clone()
1097
1099
  y_b = y[idx_perm].clone()
1098
1100
 
@@ -1150,6 +1152,97 @@ def cutmix(
1150
1152
  return X_mix, (y.clone(), y[idx_perm].clone(), lam)
1151
1153
 
1152
1154
 
1155
+ def label_smoothing(
1156
+ X: torch.Tensor,
1157
+ y: torch.Tensor,
1158
+ epsilon: float,
1159
+ num_classes: int | None = None,
1160
+ ) -> tuple[torch.Tensor, torch.Tensor]:
1161
+ """Smooth targets toward the uniform distribution over the classes.
1162
+
1163
+ See [1]_ for details.
1164
+
1165
+ Parameters
1166
+ ----------
1167
+ X : torch.Tensor
1168
+ EEG data in form ``batch_size, n_channels, n_times``. Returned
1169
+ unchanged.
1170
+ y : torch.Tensor
1171
+ Target of length ``batch_size`` holding class indices (float values
1172
+ are accepted when they are integral), or a floating-point tensor of
1173
+ shape ``batch_size, num_classes`` holding target distributions.
1174
+ epsilon : float
1175
+ Smoothing parameter between 0 and 1: the weight of the uniform
1176
+ distribution mixed into the targets. ``0`` returns the unsmoothed
1177
+ targets.
1178
+ num_classes : int | None, optional
1179
+ Number of classes. Required when ``y`` holds class indices; when
1180
+ ``y`` already holds distributions, it must match the size of the
1181
+ last dimension of ``y``. Defaults to None.
1182
+
1183
+ Returns
1184
+ -------
1185
+ tuple
1186
+ ``X``, ``y``. Where ``X`` is unchanged and ``y`` is a
1187
+ floating-point tensor of shape ``batch_size, num_classes`` whose
1188
+ rows sum to one.
1189
+
1190
+ References
1191
+ ----------
1192
+ .. [1] Christian Szegedy, Vincent Vanhoucke, Jonathon Shlens and
1193
+ Zbigniew Wojna (2016). Rethinking the Inception Architecture for
1194
+ Computer Vision. In 2016 IEEE Conference on Computer Vision and
1195
+ Pattern Recognition (CVPR), pp. 2818-2826.
1196
+ Online: https://arxiv.org/abs/1512.00567
1197
+ """
1198
+ if not isinstance(epsilon, Real) or not 0.0 <= float(epsilon) <= 1.0:
1199
+ raise ValueError(
1200
+ f"epsilon should be a real number between 0 and 1. Got {epsilon!r}."
1201
+ )
1202
+ if num_classes is not None and (
1203
+ not isinstance(num_classes, int)
1204
+ or isinstance(num_classes, bool)
1205
+ or num_classes < 2
1206
+ ):
1207
+ raise ValueError(
1208
+ f"num_classes should be an integer of at least 2. Got {num_classes!r}."
1209
+ )
1210
+
1211
+ if y.dim() == 1:
1212
+ # class-index targets: smooth their one-hot encoding
1213
+ if num_classes is None:
1214
+ raise ValueError("num_classes is required when y holds class indices.")
1215
+ if not torch.all(y == y.floor()):
1216
+ raise ValueError(
1217
+ "y holds non-integral values; class-index targets should be "
1218
+ "integers or integral floats."
1219
+ )
1220
+ if y.numel() > 0 and (y.min() < 0 or y.max() >= num_classes):
1221
+ raise ValueError(f"y holds class indices outside [0, {num_classes}).")
1222
+ one_hot_y = one_hot(y.long(), num_classes).to(dtype=X.dtype)
1223
+ return X, one_hot_y * (1.0 - epsilon) + epsilon / num_classes
1224
+
1225
+ if y.is_floating_point() and y.dim() >= 2:
1226
+ # target distributions: interpolate them toward the uniform one
1227
+ n_classes = y.shape[-1]
1228
+ if num_classes is not None and num_classes != n_classes:
1229
+ raise ValueError(
1230
+ f"num_classes ({num_classes}) does not match the size of the "
1231
+ f"last dimension of y ({n_classes})."
1232
+ )
1233
+ if n_classes < 2:
1234
+ raise ValueError(
1235
+ f"y should hold distributions over at least 2 classes. Got {n_classes}."
1236
+ )
1237
+ return X, y * (1.0 - epsilon) + epsilon / n_classes
1238
+
1239
+ raise ValueError(
1240
+ "y should hold class indices or floating-point target distributions "
1241
+ f"with a class dimension; got dtype {y.dtype} and shape "
1242
+ f"{tuple(y.shape)}."
1243
+ )
1244
+
1245
+
1153
1246
  def segmentation_reconstruction(
1154
1247
  X: torch.Tensor,
1155
1248
  y: torch.Tensor,
@@ -30,6 +30,7 @@ from .functional import (
30
30
  frequency_shift,
31
31
  ft_surrogate,
32
32
  gaussian_noise,
33
+ label_smoothing,
33
34
  mask_encoding,
34
35
  mixup,
35
36
  segmentation_reconstruction,
@@ -1155,6 +1156,98 @@ class CutMix(Mixup):
1155
1156
  return dict(params, cut_t_start=start, cut_t_len=end - start)
1156
1157
 
1157
1158
 
1159
+ class LabelSmoothing(Transform):
1160
+ """Label smoothing from Szegedy et al. (2016) [1]_.
1161
+
1162
+ Replaces each target with its convex combination with the uniform
1163
+ distribution over the classes, penalizing over-confident predictions.
1164
+ The signals are returned unchanged; only the targets change.
1165
+
1166
+ The smoothed targets are floating-point distributions of shape
1167
+ ``batch_size, num_classes`` (each row sums to one), so the training
1168
+ loss must accept target distributions, e.g. soft cross-entropy
1169
+ ``-(y * torch.log_softmax(logits, dim=-1)).sum(-1).mean()`` or
1170
+ ``torch.nn.KLDivLoss``. The transform composes before target-mixing
1171
+ transforms such as :class:`braindecode.augmentation.Mixup`, whose
1172
+ fractional-target path then mixes the smoothed distributions. The
1173
+ fixed-expansion mode (``n_augmentation > 0``) of
1174
+ :class:`braindecode.augmentation.AugmentedDataLoader` is not supported:
1175
+ it cannot concatenate the unsmoothed original targets with the reshaped
1176
+ smoothed copies.
1177
+
1178
+ Parameters
1179
+ ----------
1180
+ epsilon : float
1181
+ Smoothing parameter between 0 and 1: the weight of the uniform
1182
+ distribution mixed into the targets. ``0`` disables smoothing.
1183
+ num_classes : int | None, optional
1184
+ Number of classes. Required when the targets are class indices;
1185
+ when the targets are already distributions of shape
1186
+ ``batch_size, num_classes``, it must match their last dimension.
1187
+ Defaults to None.
1188
+ random_state : int | numpy.random.Generator, optional
1189
+ Seed to be used to instantiate numpy random number generator
1190
+ instance. The transform is deterministic, so the seed only feeds
1191
+ the application-probability machinery, which is inactive here.
1192
+ Defaults to None.
1193
+
1194
+ References
1195
+ ----------
1196
+ .. [1] Christian Szegedy, Vincent Vanhoucke, Jonathon Shlens and
1197
+ Zbigniew Wojna (2016). Rethinking the Inception Architecture for
1198
+ Computer Vision. In 2016 IEEE Conference on Computer Vision and
1199
+ Pattern Recognition (CVPR), pp. 2818-2826.
1200
+ Online: https://arxiv.org/abs/1512.00567
1201
+ """
1202
+
1203
+ operation = staticmethod(label_smoothing) # type: ignore[assignment]
1204
+
1205
+ def __init__(self, epsilon, num_classes=None, random_state=None):
1206
+ super().__init__(
1207
+ probability=1.0, # LabelSmoothing has to be applied to whole batches
1208
+ random_state=random_state,
1209
+ )
1210
+ if not isinstance(epsilon, Real) or not 0.0 <= float(epsilon) <= 1.0:
1211
+ raise ValueError(
1212
+ f"epsilon should be a real number between 0 and 1. Got {epsilon!r}."
1213
+ )
1214
+ if num_classes is not None and (
1215
+ not isinstance(num_classes, int)
1216
+ or isinstance(num_classes, bool)
1217
+ or num_classes < 2
1218
+ ):
1219
+ raise ValueError(
1220
+ f"num_classes should be an integer of at least 2. Got {num_classes!r}."
1221
+ )
1222
+ self.epsilon = epsilon
1223
+ self.num_classes = num_classes
1224
+
1225
+ def get_augmentation_params(self, *batch):
1226
+ """Return transform parameters.
1227
+
1228
+ Parameters
1229
+ ----------
1230
+ X : tensor.Tensor
1231
+ The data.
1232
+ y : tensor.Tensor
1233
+ The labels.
1234
+
1235
+ Returns
1236
+ -------
1237
+ params : dict
1238
+ Contains
1239
+
1240
+ * epsilon : float
1241
+ Smoothing parameter between 0 and 1.
1242
+ * num_classes : int | None
1243
+ The number of classes.
1244
+ """
1245
+ return {
1246
+ "epsilon": self.epsilon,
1247
+ "num_classes": self.num_classes,
1248
+ }
1249
+
1250
+
1158
1251
  class SegmentationReconstruction(Transform):
1159
1252
  """Segmentation Reconstruction from Lotte (2015) [Lotte2015]_.
1160
1253
 
@@ -1,25 +1,30 @@
1
1
  import math
2
2
 
3
+ import torch
3
4
  from torch import nn
4
5
 
5
6
 
6
7
  def glorot_weight_zero_bias(model):
7
- """Initialize parameters of all modules by initializing weights with.
8
+ """Set the weights of BatchNorm layers to one and all biases to zero.
8
9
 
9
- glorot uniform/xavier initialization, and setting biases to zero. Weights from
10
- batch norm layers are set to 1.
10
+ Despite its name, this function does not apply the Glorot (Xavier)
11
+ initialization: other weights keep the initialization of their layer
12
+ (PyTorch's default, or Xavier uniform for the max-norm constrained layers
13
+ such as :class:`braindecode.modules.Conv2dWithConstraint`). The name is
14
+ kept for backward compatibility.
11
15
 
12
16
  Parameters
13
17
  ----------
14
18
  model : Module
15
19
  """
16
20
  for module in model.modules():
17
- if hasattr(module, "weight"):
18
- if "BatchNorm" in module.__class__.__name__:
19
- nn.init.constant_(module.weight, 1)
20
- if hasattr(module, "bias"):
21
- if module.bias is not None:
22
- nn.init.constant_(module.bias, 0)
21
+ # ``weight``/``bias`` can be None (e.g. BatchNorm with affine=False)
22
+ weight = getattr(module, "weight", None)
23
+ if isinstance(weight, torch.Tensor) and "BatchNorm" in type(module).__name__:
24
+ nn.init.constant_(weight, 1)
25
+ bias = getattr(module, "bias", None)
26
+ if isinstance(bias, torch.Tensor):
27
+ nn.init.constant_(bias, 0)
23
28
 
24
29
 
25
30
  def rescale_parameter(param, layer_id):
@@ -444,8 +444,10 @@ class ATCNet(EEGModuleMixin, nn.Module):
444
444
  # ----- Sliding window -----
445
445
  sw_concat: list[torch.Tensor] = [] # to store sliding window outputs
446
446
  # for w in range(self.n_windows):
447
- for idx, (attention, tcn_module, final_layer) in enumerate(
448
- zip(self.attention_blocks, self.temporal_conv_nets, self.final_layer)
447
+ # (final_layer is not zipped in: with concat=True it holds a single
448
+ # layer, which would stop the loop after the first window)
449
+ for idx, (attention, tcn_module) in enumerate(
450
+ zip(self.attention_blocks, self.temporal_conv_nets)
449
451
  ):
450
452
  conv_feat_w = conv_feat[..., idx : idx + self.Tw]
451
453
  # Dimension: (batch_size, F2, Tw)
@@ -458,14 +460,15 @@ class ATCNet(EEGModuleMixin, nn.Module):
458
460
  tcn_feat = tcn_module(att_feat)[..., -1]
459
461
  # Dimension: (batch_size, F2)
460
462
 
461
- # Outputs of sliding window can be either averaged after being
462
- # mapped by dense layer or concatenated then mapped by a dense
463
- # layer
464
- if not self.concat:
465
- tcn_feat = final_layer(tcn_feat)
466
-
467
463
  sw_concat.append(tcn_feat)
468
464
 
465
+ # Outputs of sliding window can be either averaged after being
466
+ # mapped by dense layer or concatenated then mapped by a dense
467
+ # layer
468
+ if not self.concat:
469
+ for idx, final_layer in enumerate(self.final_layer):
470
+ sw_concat[idx] = final_layer(sw_concat[idx])
471
+
469
472
  # ----- Aggregation and prediction -----
470
473
  if self.concat:
471
474
  sw_concat_agg = torch.cat(sw_concat, dim=1)
@@ -186,10 +186,12 @@ class BIOT(EEGModuleMixin, nn.Module):
186
186
  warn(
187
187
  "The hop length is larger than the sampling frequency. "
188
188
  + "This may cause aliasing. Consider using a smaller "
189
- "hop length.",
189
+ "hop length. Using sfreq // 2 instead.",
190
190
  UserWarning,
191
191
  )
192
- hop_length = self.sfreq // 2
192
+ # torch.stft needs an int, and sfreq is usually a float
193
+ hop_length = int(self.sfreq // 2)
194
+ self.hop_length = hop_length
193
195
 
194
196
  if self.input_window_seconds < 1.0:
195
197
  warning_msg = (
@@ -181,6 +181,7 @@ class CTNet(EEGModuleMixin, nn.Module, license="mit"):
181
181
  drop_prob=self.att_positional_drop_prob,
182
182
  n_times=self.n_times,
183
183
  pool_size=self.pool_size_1,
184
+ sequence_length=self.sequence_length,
184
185
  )
185
186
 
186
187
  self.trans = _TransformerEncoder(
@@ -220,7 +221,7 @@ class CTNet(EEGModuleMixin, nn.Module, license="mit"):
220
221
  cnn = self.position(cnn)
221
222
  trans = self.trans(cnn)
222
223
  features = cnn + trans
223
- flatten_feature = self.flatten(features)
224
+ flatten_feature = self.flatten_drop_layer(features)
224
225
  out = self.final_layer(flatten_feature)
225
226
  return out
226
227
 
@@ -516,18 +517,23 @@ class _PositionalEncoding(nn.Module):
516
517
  length: int = 100,
517
518
  drop_prob: float = 0.1,
518
519
  pool_size: int = 8,
520
+ sequence_length: int | None = None,
519
521
  ):
520
522
  super().__init__()
521
523
  self.pool_size = pool_size
522
524
  self.n_times = n_times
523
525
 
524
- if int(n_times / (pool_size * pool_size)) > length:
526
+ # n_times / pool_size**2 is the sequence length only when both pooling
527
+ # sizes are equal; also cover the actual length (e.g. pool_size_2 <
528
+ # pool_size_1), so that the encoding is never shorter than the input
529
+ needed = max(int(n_times / (pool_size * pool_size)), sequence_length or 0)
530
+ if needed > length:
525
531
  warn(
526
532
  "the temporal dimensional is too long for this default length. "
527
533
  "The length parameter will be automatically adjusted to "
528
534
  "avoid inference issues."
529
535
  )
530
- length = int(n_times / (pool_size * pool_size))
536
+ length = needed
531
537
 
532
538
  self.dropout = nn.Dropout(drop_prob)
533
539
  self.encoding = nn.Parameter(torch.randn(1, length, emb_size))
@@ -296,7 +296,9 @@ class Labram(EEGModuleMixin, nn.Module):
296
296
  learned_patcher : bool
297
297
  Whether to use a learned patch embedding (via a convolutional layer) or a fixed patch embedding (via rearrangement).
298
298
  embed_dim : int
299
- The dimension of the embedding.
299
+ The dimension of the embedding. In the Neural Tokenizer mode, it is
300
+ set by the temporal convolution (``conv_out_channels`` and
301
+ ``patch_size``), with a warning if the given value differs.
300
302
  conv_in_channels : int
301
303
  The number of convolutional input channels.
302
304
  conv_out_channels : int
@@ -515,6 +517,14 @@ class Labram(EEGModuleMixin, nn.Module):
515
517
  out = self.patch_embed(dummy)
516
518
  # out.shape for tokenizer: (1, n_chans, emb_dim)
517
519
  # for decoder: (1, n_patch, patch_size, emb_dim), but we want last dim
520
+ if neural_tokenizer and out.shape[-1] != self.embed_dim:
521
+ warn(
522
+ f"In the Neural Tokenizer mode the embedding dimension is set "
523
+ f"by the temporal convolution (conv_out_channels, patch_size): "
524
+ f"using embed_dim={out.shape[-1]} instead of the given "
525
+ f"embed_dim={self.embed_dim}.",
526
+ UserWarning,
527
+ )
518
528
  self.embed_dim = out.shape[-1]
519
529
  self.num_features = self.embed_dim
520
530
 
@@ -113,6 +113,9 @@ class LUNA(EEGModuleMixin, nn.Module, license="apache-2.0"):
113
113
  Normalization layer class. Default: nn.LayerNorm.
114
114
  drop_path : float
115
115
  Stochastic depth rate. Default: 0.0.
116
+ attn_drop : float
117
+ Dropout rate on the attention weights of the transformer encoder
118
+ blocks (the original LUNA uses 0). Default: 0.0.
116
119
 
117
120
  References
118
121
  ----------
@@ -222,7 +225,7 @@ class LUNA(EEGModuleMixin, nn.Module, license="apache-2.0"):
222
225
  mlp_ratio=self.mlp_ratio,
223
226
  qkv_bias=True,
224
227
  drop=0.0,
225
- attn_drop=0.0,
228
+ attn_drop=self.attn_drop,
226
229
  drop_path=self.drop_path,
227
230
  norm_layer=norm_layer,
228
231
  )
@@ -235,17 +235,18 @@ class MEDFormer(EEGModuleMixin, nn.Module, license="mit"):
235
235
  self.patch_len_list = patch_len_list
236
236
  stride_list = patch_len_list # Using the same values for strides.
237
237
  self.stride_list = stride_list
238
+ # patches run over time (one token per patch of samples)
238
239
  patch_num_list = [
239
- int((self.n_chans - patch_len) / stride + 2)
240
+ int((self.n_times - patch_len) / stride + 2)
240
241
  for patch_len, stride in zip(patch_len_list, stride_list)
241
242
  ]
242
243
  self.patch_num_list = patch_num_list
243
244
 
244
245
  # Initialize the embedding layer.
245
246
  self.enc_embedding = _ListPatchEmbedding(
246
- enc_in=self.n_times,
247
+ enc_in=self.n_chans,
247
248
  d_model=self.embed_dim,
248
- seq_len=self.n_chans,
249
+ seq_len=self.n_times,
249
250
  patch_len_list=self.patch_len_list,
250
251
  stride_list=self.stride_list,
251
252
  dropout=self.drop_prob,
@@ -362,7 +363,7 @@ class _CrossChannelTokenEmbedding(nn.Module):
362
363
  def forward(self, x: torch.Tensor) -> torch.Tensor:
363
364
  # The kernel spans all c_in rows and the patches do not overlap, so
364
365
  # the conv is one GEMM of its weight with the patch-reshaped input
365
- # (Gaudi2 rejects conv kernels taller than 256 rows, c_in = n_times).
366
+ # (Gaudi2 rejects conv kernels taller than 256 rows).
366
367
  l_patch = self.token_conv.kernel_size[1]
367
368
  n_patches = x.shape[-1] // l_patch
368
369
  x = x[:, 0, :, : n_patches * l_patch].reshape(
@@ -411,10 +412,9 @@ class _ListPatchEmbedding(nn.Module):
411
412
  ]
412
413
  self.value_embeddings = nn.ModuleList(linear_layers)
413
414
  self.position_embedding = _PositionalEmbedding(d_model=d_model)
414
- # One row per time sample: windows longer than 5000 samples need more.
415
- self.channel_embedding = _PositionalEmbedding(
416
- d_model=seq_len, max_len=max(5000, enc_in)
417
- )
415
+ # One sinusoidal code along time per channel, which tags each channel
416
+ # (the rows past enc_in that the original max_len=5000 adds are unused)
417
+ self.channel_embedding = _PositionalEmbedding(d_model=seq_len, max_len=enc_in)
418
418
  self.dropout = nn.Dropout(dropout)
419
419
 
420
420
  self.learnable_embeddings = nn.ParameterList(
@@ -423,15 +423,12 @@ class _ListPatchEmbedding(nn.Module):
423
423
 
424
424
  def forward(
425
425
  self, x: torch.Tensor
426
- ) -> List[torch.Tensor]: # (batch_size, seq_len, enc_in)
427
- x = x.permute(0, 2, 1) # (batch_size, enc_in, seq_len)
426
+ ) -> List[torch.Tensor]: # (batch_size, enc_in, seq_len) = (B, n_chans, n_times)
427
+ # The original code takes (batch_size, seq_len, enc_in) and permutes it
428
+ # to this layout; braindecode inputs already have it.
428
429
  if self.single_channel:
429
- # After permute: x.shape = (batch_size, n_times, n_chans)
430
- # We want to process each channel independently
430
+ # Treat each channel independently: (batch_size * n_chans, 1, n_times)
431
431
  batch_size = x.shape[0]
432
- # Permute to get channels in the middle: (batch_size, n_chans, n_times)
433
- x = x.permute(0, 2, 1)
434
- # Reshape to treat each channel independently: (batch_size * n_chans, 1, n_times)
435
432
  x = torch.reshape(x, (batch_size * self.n_chans, 1, self.n_times))
436
433
 
437
434
  # add positional embedding to tag each channel (only when not single_channel)
@@ -123,6 +123,12 @@ class SincShallowNet(EEGModuleMixin, nn.Module):
123
123
  if activation is None:
124
124
  activation = nn.ELU()
125
125
 
126
+ if self.n_times is None:
127
+ raise ValueError(
128
+ "SincShallowNet needs to know the input length: pass n_times "
129
+ "(or input_window_seconds and sfreq)."
130
+ )
131
+
126
132
  # Define low frequencies for the SincFilter
127
133
  low_freqs = torch.arange(
128
134
  first_freq,
@@ -139,6 +145,15 @@ class SincShallowNet(EEGModuleMixin, nn.Module):
139
145
  else:
140
146
  raise ValueError("Padding must be 'valid' or 'same'.")
141
147
 
148
+ if n_times_after_sinc_filter < pool_size:
149
+ raise ValueError(
150
+ f"n_times ({self.n_times}) leaves only {n_times_after_sinc_filter} "
151
+ f"samples after the temporal sinc filter, fewer than pool_size "
152
+ f"({pool_size}): the average pooling would produce no temporal "
153
+ "position. Increase n_times, or decrease pool_size (and "
154
+ "time_filter_len for padding='valid')."
155
+ )
156
+
142
157
  size_after_pooling = (
143
158
  (n_times_after_sinc_filter - pool_size) // pool_stride
144
159
  ) + 1
@@ -141,7 +141,18 @@ class TMSANet(EEGModuleMixin, nn.Module, license="mit"):
141
141
  )
142
142
  # The reference flattens (embed_dim, tokens), embedding-major.
143
143
  self.flatten = Rearrange("b n d -> b (d n)")
144
+ if self.n_times is None:
145
+ raise ValueError(
146
+ "TMSANet needs to know the input length: pass n_times "
147
+ "(or input_window_seconds and sfreq)."
148
+ )
144
149
  n_tokens = (self.n_times - pool_size) // pool_stride + 1
150
+ if n_tokens < 1:
151
+ raise ValueError(
152
+ f"n_times ({self.n_times}) must be at least pool_size ({pool_size}) "
153
+ f"so the average pooling keeps at least one temporal token "
154
+ f"(would keep {n_tokens})."
155
+ )
145
156
  self.final_layer = nn.Linear(embed_dim * n_tokens, self.n_outputs)
146
157
 
147
158
  def forward(self, x: Tensor) -> Tensor:
@@ -138,9 +138,11 @@ class ZUNA(EEGModuleMixin, nn.Module, license="apache-2.0"):
138
138
  latent_dim : int, optional
139
139
  Per-token output dimension of the encoder. The default is ``32``.
140
140
  max_seqlen : int, optional
141
- Length of the rotary frequency table. It must be at least
142
- ``max(pos_bins, the number of temporal patches)``. The default is
143
- ``256``.
141
+ Minimum length of the rotary frequency table. The table is extended to
142
+ ``max(pos_bins, the number of temporal patches)`` when the window needs
143
+ more rows, so longer windows than the release's 8192 samples are
144
+ accepted (positions past the pretraining range are extrapolated by the
145
+ rotary embedding). The default is ``256``.
144
146
  rope_theta : float, optional
145
147
  Base period of the rotary positional embedding. The default is
146
148
  ``10000.0``.
@@ -263,12 +265,6 @@ class ZUNA(EEGModuleMixin, nn.Module, license="apache-2.0"):
263
265
  raise ValueError("ZUNA requires finite 3D locations for every channel.")
264
266
  if head_dim % 8 != 0:
265
267
  raise ValueError("head_dim must be divisible by eight for 4D RoPE.")
266
- if coarse_time_points > max_seqlen:
267
- raise ValueError(
268
- f"n_times ({self.n_times}) gives {coarse_time_points} patches of "
269
- f"{fine_time_pts} samples; max_seqlen={max_seqlen} allows at most "
270
- f"{max_seqlen * fine_time_pts} samples."
271
- )
272
268
 
273
269
  # Layers
274
270
  self.patch_embedding = nn.Sequential(
@@ -298,7 +294,11 @@ class ZUNA(EEGModuleMixin, nn.Module, license="apache-2.0"):
298
294
  )
299
295
 
300
296
  rotary_frequency_table = _build_rotary_frequency_table(
301
- torch.arange(max_seqlen, dtype=torch.float32),
297
+ # RoPE is analytic and the tables are non-persistent buffers: extend the
298
+ # table to the window instead of capping it (rows < max_seqlen unchanged).
299
+ torch.arange(
300
+ max(max_seqlen, pos_bins, coarse_time_points), dtype=torch.float32
301
+ ),
302
302
  axis_dim=rotary_axis_dim,
303
303
  theta=rope_theta,
304
304
  )
@@ -1004,10 +1004,13 @@ class MultiHeadAttention(nn.Module):
1004
1004
  x : Tensor
1005
1005
  Input tensor of shape ``(batch, seq, emb_size)``.
1006
1006
  mask : Tensor, optional
1007
- Attention mask following PyTorch SDPA convention: for boolean
1008
- masks ``True`` means **ignore** that position; for float
1009
- masks the values are **added** to attention scores before
1010
- softmax.
1007
+ Attention mask following the convention of
1008
+ :func:`torch.nn.functional.scaled_dot_product_attention`: for
1009
+ boolean masks ``True`` means the position **takes part** in
1010
+ attention and ``False`` that it is ignored (the opposite of the
1011
+ ``key_padding_mask`` of :class:`torch.nn.MultiheadAttention`);
1012
+ for float masks the values are **added** to the attention scores
1013
+ before softmax.
1011
1014
  """
1012
1015
  queries = self.rearrange_stack(self.queries(x))
1013
1016
  keys = self.rearrange_stack(self.keys(x))
@@ -1086,14 +1089,16 @@ class CrissCrossTransformerEncoderLayer(nn.Module):
1086
1089
  nhead // 2,
1087
1090
  dropout=dropout,
1088
1091
  bias=bias,
1089
- batch_first=batch_first,
1092
+ # _sa_block always builds (batch, sequence, features) inputs
1093
+ batch_first=True,
1090
1094
  )
1091
1095
  self.self_attn_t = nn.MultiheadAttention(
1092
1096
  d_model // 2,
1093
1097
  nhead // 2,
1094
1098
  dropout=dropout,
1095
1099
  bias=bias,
1096
- batch_first=batch_first,
1100
+ # _sa_block always builds (batch, sequence, features) inputs
1101
+ batch_first=True,
1097
1102
  )
1098
1103
 
1099
1104
  # Implementation of Feedforward model
@@ -1101,6 +1106,9 @@ class CrissCrossTransformerEncoderLayer(nn.Module):
1101
1106
  self.dropout = nn.Dropout(dropout)
1102
1107
  self.linear2 = nn.Linear(dim_feedforward, d_model, bias=bias)
1103
1108
 
1109
+ # kept for the signature of nn.TransformerEncoderLayer: the input is
1110
+ # always (batch, channels, n_patches, patch_size)
1111
+ self.batch_first = batch_first
1104
1112
  self.norm_first = norm_first
1105
1113
  self.norm1 = nn.LayerNorm(d_model, eps=layer_norm_eps)
1106
1114
  self.norm2 = nn.LayerNorm(d_model, eps=layer_norm_eps)
@@ -1116,10 +1124,17 @@ class CrissCrossTransformerEncoderLayer(nn.Module):
1116
1124
  is_causal: bool = False,
1117
1125
  ) -> Tensor:
1118
1126
  x = src
1119
- x = x + self._sa_block(
1120
- self.norm1(x), src_mask, src_key_padding_mask, is_causal=is_causal
1121
- )
1122
- x = x + self._ff_block(self.norm2(x))
1127
+ if self.norm_first:
1128
+ x = x + self._sa_block(
1129
+ self.norm1(x), src_mask, src_key_padding_mask, is_causal=is_causal
1130
+ )
1131
+ x = x + self._ff_block(self.norm2(x))
1132
+ else:
1133
+ x = self.norm1(
1134
+ x
1135
+ + self._sa_block(x, src_mask, src_key_padding_mask, is_causal=is_causal)
1136
+ )
1137
+ x = self.norm2(x + self._ff_block(x))
1123
1138
  return x
1124
1139
 
1125
1140
  # self-attention block