Braindecode 1.8.1.dev181512403__tar.gz → 1.8.1.dev181570120__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. {braindecode-1.8.1.dev181512403/braindecode.egg-info → braindecode-1.8.1.dev181570120}/PKG-INFO +1 -1
  2. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/base.py +3 -46
  3. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/functional/_real_dft.py +0 -55
  4. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/functional/functions.py +5 -13
  5. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/barista.py +2 -2
  6. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/codebrain.py +11 -18
  7. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eeginception_mi.py +3 -7
  8. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eegnex.py +1 -1
  9. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eegpt.py +1 -3
  10. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/labram.py +9 -19
  11. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/luna.py +1 -3
  12. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/patchedtransformer.py +7 -3
  13. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/reve.py +4 -16
  14. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/zuna.py +9 -11
  15. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/attention.py +6 -53
  16. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/dance_modules.py +3 -16
  17. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/layers.py +2 -41
  18. braindecode-1.8.1.dev181570120/braindecode/version.py +1 -0
  19. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120/braindecode.egg-info}/PKG-INFO +1 -1
  20. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/whats_new.rst +0 -17
  21. braindecode-1.8.1.dev181512403/braindecode/version.py +0 -1
  22. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/LICENSE.txt +0 -0
  23. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/MANIFEST.in +0 -0
  24. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/NOTICE.txt +0 -0
  25. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/README.rst +0 -0
  26. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/__init__.py +0 -0
  27. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/augmentation/__init__.py +0 -0
  28. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/augmentation/base.py +0 -0
  29. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/augmentation/functional.py +0 -0
  30. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/augmentation/transforms.py +0 -0
  31. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/classifier.py +0 -0
  32. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/__init__.py +0 -0
  33. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/_notebook_viewer.py +0 -0
  34. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/bbci.py +0 -0
  35. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/bcicomp.py +0 -0
  36. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/bids/__init__.py +0 -0
  37. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/bids/datasets.py +0 -0
  38. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/bids/format.py +0 -0
  39. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/bids/hub.py +0 -0
  40. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/bids/hub_format.py +0 -0
  41. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/bids/hub_io.py +0 -0
  42. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/bids/hub_validation.py +0 -0
  43. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/bids/iterable.py +0 -0
  44. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/chb_mit.py +0 -0
  45. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/collate.py +0 -0
  46. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/mne.py +0 -0
  47. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/moabb.py +0 -0
  48. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/nmt.py +0 -0
  49. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/registry.py +0 -0
  50. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/siena.py +0 -0
  51. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/sleep_physio_challe_18.py +0 -0
  52. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/sleep_physionet.py +0 -0
  53. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/tuh.py +0 -0
  54. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/utils.py +0 -0
  55. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datasets/xy.py +0 -0
  56. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datautil/__init__.py +0 -0
  57. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datautil/channel_utils.py +0 -0
  58. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datautil/hub_formats.py +0 -0
  59. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datautil/serialization.py +0 -0
  60. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/datautil/util.py +0 -0
  61. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/eegneuralnet.py +0 -0
  62. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/functional/__init__.py +0 -0
  63. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/functional/initialization.py +0 -0
  64. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/__init__.py +0 -0
  65. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/atcnet.py +0 -0
  66. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/attentionbasenet.py +0 -0
  67. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/attn_sleep.py +0 -0
  68. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/axon.py +0 -0
  69. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/base.py +0 -0
  70. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/bendr.py +0 -0
  71. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/biot.py +0 -0
  72. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/brainbert.py +0 -0
  73. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/brainmodule.py +0 -0
  74. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/brainomni.py +0 -0
  75. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/brant.py +0 -0
  76. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/cbramod.py +0 -0
  77. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/config.py +0 -0
  78. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/contrawr.py +0 -0
  79. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/csbrain.py +0 -0
  80. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/ctnet.py +0 -0
  81. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/dance.py +0 -0
  82. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/deep4.py +0 -0
  83. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/deepsleepnet.py +0 -0
  84. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/dgcnn.py +0 -0
  85. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/diver1.py +0 -0
  86. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eeg_clip.py +0 -0
  87. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eegconformer.py +0 -0
  88. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eegdino.py +0 -0
  89. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eeginception_erp.py +0 -0
  90. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eegitnet.py +0 -0
  91. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eegminer.py +0 -0
  92. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eegnet.py +0 -0
  93. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eegsimpleconv.py +0 -0
  94. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eegsym.py +0 -0
  95. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/eegtcnet.py +0 -0
  96. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/emg2qwerty.py +0 -0
  97. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/fbcnet.py +0 -0
  98. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/fblightconvnet.py +0 -0
  99. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/fbmsnet.py +0 -0
  100. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/guetschel2026.py +0 -0
  101. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/hybrid.py +0 -0
  102. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/ifnet.py +0 -0
  103. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/mapa.py +0 -0
  104. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/medformer.py +0 -0
  105. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/meta_neuromotor.py +0 -0
  106. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/mirepnet.py +0 -0
  107. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/mscformer.py +0 -0
  108. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/msvtnet.py +0 -0
  109. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/mvpformer.py +0 -0
  110. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/neuropose.py +0 -0
  111. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/neurorvq.py +0 -0
  112. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/neurorvq_tokenizer.py +0 -0
  113. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/popt.py +0 -0
  114. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/sccnet.py +0 -0
  115. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/seizure_transformer.py +0 -0
  116. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/sensingdynamics.py +0 -0
  117. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/shallow_fbcsp.py +0 -0
  118. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/signal_jepa.py +0 -0
  119. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/sinc_shallow.py +0 -0
  120. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/sleep_stager_blanco_2020.py +0 -0
  121. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/sleep_stager_chambon_2018.py +0 -0
  122. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/sleepfm.py +0 -0
  123. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/sparcnet.py +0 -0
  124. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/sstdpn.py +0 -0
  125. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/steegformer.py +0 -0
  126. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/summary.csv +0 -0
  127. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/syncnet.py +0 -0
  128. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/tcformer.py +0 -0
  129. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/tcn.py +0 -0
  130. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/tfm_tokenizer.py +0 -0
  131. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/tidnet.py +0 -0
  132. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/tmsanet.py +0 -0
  133. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/tsinception.py +0 -0
  134. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/usleep.py +0 -0
  135. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/util.py +0 -0
  136. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/models/vemg2pose.py +0 -0
  137. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/__init__.py +0 -0
  138. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/activation.py +0 -0
  139. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/blocks.py +0 -0
  140. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/channels.py +0 -0
  141. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/convolution.py +0 -0
  142. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/filter.py +0 -0
  143. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/linear.py +0 -0
  144. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/linear_attention.py +0 -0
  145. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/parametrization.py +0 -0
  146. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/popt_modules.py +0 -0
  147. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/quantization.py +0 -0
  148. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/stats.py +0 -0
  149. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/util.py +0 -0
  150. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/modules/wrapper.py +0 -0
  151. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/preprocessing/__init__.py +0 -0
  152. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/preprocessing/eegprep_preprocess.py +0 -0
  153. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/preprocessing/mne_preprocess.py +0 -0
  154. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/preprocessing/preprocess.py +0 -0
  155. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/preprocessing/util.py +0 -0
  156. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/preprocessing/windowers.py +0 -0
  157. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/regressor.py +0 -0
  158. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/samplers/__init__.py +0 -0
  159. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/samplers/base.py +0 -0
  160. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/samplers/ssl.py +0 -0
  161. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/training/__init__.py +0 -0
  162. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/training/callbacks.py +0 -0
  163. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/training/losses.py +0 -0
  164. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/training/scoring.py +0 -0
  165. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/util.py +0 -0
  166. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/visualization/__init__.py +0 -0
  167. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/visualization/activations.py +0 -0
  168. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/visualization/attribution.py +0 -0
  169. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/visualization/confusion_matrices.py +0 -0
  170. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/visualization/frequency.py +0 -0
  171. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/visualization/metrics.py +0 -0
  172. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/visualization/sanity.py +0 -0
  173. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode/visualization/topology.py +0 -0
  174. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode.egg-info/SOURCES.txt +0 -0
  175. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode.egg-info/dependency_links.txt +0 -0
  176. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode.egg-info/requires.txt +0 -0
  177. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/braindecode.egg-info/top_level.txt +0 -0
  178. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/Makefile +0 -0
  179. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/_templates/autosummary/class.rst +0 -0
  180. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/_templates/autosummary/class_in_subdir.rst +0 -0
  181. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/_templates/autosummary/function.rst +0 -0
  182. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/_templates/autosummary/function_in_subdir.rst +0 -0
  183. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/agent_docs.rst +0 -0
  184. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/api.rst +0 -0
  185. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/cite.rst +0 -0
  186. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/conf.py +0 -0
  187. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/help.rst +0 -0
  188. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/index.rst +0 -0
  189. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/install/install.rst +0 -0
  190. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/install/install_pip.rst +0 -0
  191. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/install/install_source.rst +0 -0
  192. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/models/categorization/attention.rst +0 -0
  193. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/models/categorization/channel.rst +0 -0
  194. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/models/categorization/convolution.rst +0 -0
  195. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/models/categorization/filterbank.rst +0 -0
  196. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/models/categorization/gnn.rst +0 -0
  197. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/models/categorization/interpretable.rst +0 -0
  198. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/models/categorization/lbm.rst +0 -0
  199. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/models/categorization/recurrent.rst +0 -0
  200. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/models/categorization/spd.rst +0 -0
  201. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/models/models.rst +0 -0
  202. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/models/models_categorization.rst +0 -0
  203. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/models/models_table.rst +0 -0
  204. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/models/models_visualization.rst +0 -0
  205. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/sg_execution_times.rst +0 -0
  206. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/docs/user_guide/channel_strategies.rst +0 -0
  207. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/pyproject.toml +0 -0
  208. {braindecode-1.8.1.dev181512403 → braindecode-1.8.1.dev181570120}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: braindecode
3
- Version: 1.8.1.dev181512403
3
+ Version: 1.8.1.dev181570120
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>
@@ -279,7 +279,7 @@ def _compact_fif_tags(inst):
279
279
  return inst
280
280
 
281
281
 
282
- def _read_fif_window(raw, start, stop, willneed=False):
282
+ def _read_fif_window(raw, start, stop):
283
283
  """Samples ``start:stop`` of a lazy FIF raw, copied from the file in one go.
284
284
 
285
285
  mne reads, casts and calibrates the FIF data buffers of a range one at a
@@ -290,10 +290,6 @@ def _read_fif_window(raw, start, stop, willneed=False):
290
290
  times ``raw._cals``), so the values equal ``raw._getitem``'s. Returns None
291
291
  (the caller uses mne) unless ``raw`` is a lazy, single-file, uncompressed
292
292
  FIF raw of float32 buffers without projector, compensation or gaps.
293
-
294
- With ``willneed=True`` nothing is read and None is returned: the OS is
295
- only asked to start reading the window's bytes into the page cache in the
296
- background (``posix_fadvise(POSIX_FADV_WILLNEED)``).
297
293
  """
298
294
  if (
299
295
  not isinstance(raw, mne.io.Raw)
@@ -320,18 +316,6 @@ def _read_fif_window(raw, start, stop, willneed=False):
320
316
  if not len(rows) or (rows[:, 1] != FIFF.FIFFT_FLOAT).any():
321
317
  return None
322
318
  size, pos = rows[:, 2].tolist(), rows[:, 4].tolist()
323
- if willneed: # only a hint: any error is left to the read itself
324
- try:
325
- with open(fname, "rb") as f:
326
- os.posix_fadvise(
327
- f.fileno(),
328
- pos[0],
329
- pos[-1] + 16 + size[-1] - pos[0],
330
- os.POSIX_FADV_WILLNEED,
331
- )
332
- except OSError:
333
- pass
334
- return None
335
319
  # mmap: no copy through a 4 MB read buffer, and a cold file is read around
336
320
  # the window by the kernel (as mne's 4 MB reads did), not window by window
337
321
  with open(fname, "rb") as f, mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as m:
@@ -1378,8 +1362,7 @@ class BaseConcatDataset(ConcatDataset, HubDatasetMixin, Generic[T]):
1378
1362
  def __len__(self):
1379
1363
  return self._ensure_cumulative_sizes()[-1]
1380
1364
 
1381
- def _locate(self, idx: int):
1382
- """The dataset that holds item ``idx`` and the item's index in it."""
1365
+ def _get_single_item(self, idx: int):
1383
1366
  if idx < 0:
1384
1367
  if -idx > len(self):
1385
1368
  raise ValueError(
@@ -1393,33 +1376,7 @@ class BaseConcatDataset(ConcatDataset, HubDatasetMixin, Generic[T]):
1393
1376
  sample_idx = idx
1394
1377
  else:
1395
1378
  sample_idx = idx - cumulative_sizes[dataset_idx - 1]
1396
- return self.datasets[dataset_idx], sample_idx
1397
-
1398
- def _get_single_item(self, idx: int):
1399
- ds, i = self._locate(idx)
1400
- return ds[i]
1401
-
1402
- def __getitems__(self, indices):
1403
- """Items ``indices``, as ``[self[i] for i in indices]``.
1404
-
1405
- A :class:`~torch.utils.data.DataLoader` fetches each batch through
1406
- this. The lazy FIF windows of the batch are first requested from the
1407
- OS all at once (``posix_fadvise(POSIX_FADV_WILLNEED)``, where it
1408
- exists), so their reads from disk overlap instead of running one after
1409
- another: on a network file system a batch read from cold files then
1410
- costs about one round trip, not one per window.
1411
- """
1412
- # ponytail: advises the whole batch at once; chunk it if a batch's
1413
- # windows ever outgrow the page cache
1414
- if hasattr(os, "posix_fadvise"):
1415
- for idx in indices:
1416
- if not isinstance(idx, (int, np.integer)):
1417
- continue # e.g. a SequenceSampler tuple: read, not advised
1418
- ds, i = self._locate(idx)
1419
- if isinstance(ds, EEGWindowsDataset) and ds._zarr_data is None:
1420
- _, start, stop = ds.crop_inds[i].tolist()
1421
- _read_fif_window(ds.raw, start, stop, willneed=True)
1422
- return [self[idx] for idx in indices]
1379
+ return self.datasets[dataset_idx][sample_idx]
1423
1380
 
1424
1381
  def __getitem__(self, idx: int | list):
1425
1382
  """
@@ -12,10 +12,8 @@ never downcast, so callers wrap the numerically sensitive parts with
12
12
  #
13
13
  # License: BSD (3-clause)
14
14
  import functools
15
- from typing import Optional
16
15
 
17
16
  import torch
18
- from torch import nn
19
17
 
20
18
 
21
19
  def needs_real_dft(x: torch.Tensor) -> bool:
@@ -138,56 +136,3 @@ def hilbert_freq_real(x: torch.Tensor, forward_fourier: bool) -> torch.Tensor:
138
136
  return torch.stack((out_real, out_imag), dim=-1)
139
137
 
140
138
  return compute(x)
141
-
142
-
143
- @torch.jit.unused
144
- def fft_conv1d_real(
145
- x: torch.Tensor, weight: torch.Tensor, bias: Optional[torch.Tensor]
146
- ) -> torch.Tensor:
147
- """Real-valued equivalent of :func:`braindecode.functional.fft_conv1d`.
148
-
149
- Overlap-save: the input is cut into blocks of ``n`` samples (the power of
150
- two ``>= 2 * kernel_size``) that advance by ``n - kernel_size + 1`` outputs,
151
- each block's DFT is a matmul against the cosine/sine basis, and per
152
- frequency the complex product with the kernels, summed over the input
153
- channels, is one real matmul.
154
- """
155
-
156
- @fp32_island
157
- def compute(x, weight):
158
- n_times, kernel_size = x.shape[-1], weight.shape[-1]
159
- n = 1 << (2 * kernel_size - 1).bit_length()
160
- hop = n - kernel_size + 1
161
- n_blocks = -(-n_times // hop)
162
- n_freqs = n // 2 + 1
163
- # "same" alignment: torch pads the extra zero of an even kernel on the right
164
- left = (kernel_size - 1) // 2
165
- x = nn.functional.pad(x, (left, (n_blocks + 1) * hop - n_times - left))
166
- hops = x.unflatten(-1, (n_blocks + 1, hop))
167
- # block i = hop i + the first kernel_size - 1 samples of hop i + 1
168
- blocks = torch.cat([hops[:, :, :-1], hops[:, :, 1:, : kernel_size - 1]], -1)
169
- cosine, sine = real_dft_basis(n, device=x.device, dtype=x.dtype)
170
- basis = torch.cat([cosine, -sine]).transpose(0, 1) # -> [Re | Im] of rfft
171
- x_f = blocks @ basis # (batch, in, blocks, 2 * n_freqs)
172
- w_f = nn.functional.pad(weight.to(x), (0, n - kernel_size)) @ basis
173
- w_re, w_im = w_f[..., :n_freqs], w_f[..., n_freqs:]
174
- # conv1d is a cross-correlation: x_f * conj(w_f), summed over the input
175
- # channels. Per frequency [Re x, Im x] @ [[Re w, -Im w], [Im w, Re w]].
176
- w_f = torch.cat([torch.cat([w_re, -w_im]), torch.cat([w_im, w_re])], 1)
177
- x_f = x_f.unflatten(-1, (2, n_freqs)).permute(4, 0, 2, 3, 1).flatten(1, 2)
178
- y_f = torch.bmm(x_f.flatten(2), w_f.permute(2, 1, 0)) # (freq, ., 2 * out)
179
- y_f = y_f.unflatten(1, (x.shape[0], n_blocks)).unflatten(-1, (2, -1))
180
- y_f = y_f.permute(1, 4, 2, 3, 0).flatten(
181
- -2
182
- ) # (batch, out, blocks, 2 * n_freqs)
183
- # inverse DFT of the first `hop` samples, the ones without wrap-around
184
- scale = torch.full((n_freqs, 1), 2.0 / n, dtype=x.dtype, device=x.device)
185
- scale[0] = 1.0 / n
186
- scale[-1] = 1.0 / n # Nyquist (n is even)
187
- inverse = torch.cat([scale * cosine[:, :hop], -scale * sine[:, :hop]])
188
- return (y_f @ inverse).flatten(-2)[..., :n_times]
189
-
190
- y = compute(x, weight)
191
- if bias is not None:
192
- y = y + bias.to(y).unsqueeze(-1)
193
- return y.to(x)
@@ -62,10 +62,9 @@ def fft_conv1d(
62
62
 
63
63
  Equal to the direct convolution up to float rounding: the FFT is long
64
64
  enough for a linear (not circular) convolution. Its cost barely grows with
65
- the kernel size, so it is faster than the direct one for long kernels
66
- (see :func:`prefer_fft_conv`). float16/bfloat16 inputs are computed in
67
- float32 (:func:`spectral_input`) and cast back. On Intel Gaudi (HPU, no
68
- complex dtype) the DFTs are real matmuls over overlapping blocks.
65
+ the kernel size, so it is faster than the direct one for long kernels on
66
+ CPU (see :func:`prefer_fft_conv`). float16/bfloat16 inputs are computed in
67
+ float32 (:func:`spectral_input`) and cast back.
69
68
 
70
69
  Parameters
71
70
  ----------
@@ -83,8 +82,6 @@ def fft_conv1d(
83
82
  ``x``. For an even ``kernel_size`` it is aligned like torch's
84
83
  ``padding="same"`` (the extra zero padded on the right).
85
84
  """
86
- if _real_dft.needs_real_dft(x):
87
- return _real_dft.fft_conv1d_real(x, weight, bias)
88
85
  n_times, kernel_size = x.shape[-1], weight.shape[-1]
89
86
  # >= n_times + kernel_size - 1 (no circular wrap-around), even and
90
87
  # 5-smooth: the fast cases of a real FFT
@@ -118,11 +115,8 @@ def prefer_fft_conv(x: torch.Tensor, kernel_size: int) -> bool:
118
115
  and from ``batch_size * kernel_size >= 600`` if also
119
116
  ``in_channels * kernel_size >= 120``: with one or two input channels a
120
117
  float32 direct convolution stays cheaper up to k = 85 / 31 (13 long
121
- temporal convolutions of the model zoo, 22 channels x batch 32). On Intel
122
- Gaudi (HPU) a direct convolution costs about ``batch_size * n_times *
123
- kernel_size`` and the FFT about a fixed few milliseconds in eager mode: the
124
- FFT wins from 8 input channels and ``batch_size * n_times * kernel_size >=
125
- 8e6``. GPUs keep the direct convolution.
118
+ temporal convolutions of the model zoo, 22 channels x batch 32). GPUs and
119
+ HPUs (no complex dtype) keep the direct convolution.
126
120
 
127
121
  Parameters
128
122
  ----------
@@ -131,8 +125,6 @@ def prefer_fft_conv(x: torch.Tensor, kernel_size: int) -> bool:
131
125
  kernel_size : int
132
126
  Kernel length in samples.
133
127
  """
134
- if x.device.type == "hpu":
135
- return x.shape[1] >= 8 and x.shape[0] * x.shape[-1] * kernel_size >= 8e6
136
128
  return x.device.type == "cpu" and (
137
129
  x.element_size() == 2
138
130
  or (x.shape[0] * kernel_size >= 600 and x.shape[1] * kernel_size >= 120)
@@ -7,13 +7,13 @@ from __future__ import annotations
7
7
  from typing import Optional
8
8
 
9
9
  import torch
10
+ import torch.nn.functional as F
10
11
  from einops.layers.torch import Rearrange
11
12
  from torch import nn
12
13
 
13
14
  from braindecode.models.base import EEGModuleMixin
14
15
  from braindecode.models.util import extract_channel_locations_from_chs_info
15
16
  from braindecode.modules import GatedLinearUnit, PatchTokenizer
16
- from braindecode.modules.attention import _scaled_dot_product_attention
17
17
 
18
18
 
19
19
  class BaRISTA(EEGModuleMixin, nn.Module, license="other"):
@@ -689,7 +689,7 @@ class _RotarySelfAttention(nn.Module):
689
689
 
690
690
  # Dropout falls on the attention output rather than on the weights,
691
691
  # through dropout_p, because the reference disables the latter outright.
692
- attention = _scaled_dot_product_attention(query, key, value)
692
+ attention = F.scaled_dot_product_attention(query, key, value)
693
693
  attention = self.dropout(attention)
694
694
  attention = self.merge_heads(attention)
695
695
  return self.o_proj(attention)
@@ -703,15 +703,18 @@ class _ResidualBlock(nn.Module):
703
703
  # Sliding-window attention branch
704
704
  # (batch, 2*res_channels, seq_len) -> (batch, seq_len, 2*res_channels)
705
705
  h_attn = h_ssm.transpose(1, 2)
706
- if self.swa_window_size == 1 and h_attn.device.type == "cpu":
706
+ if (
707
+ self.swa_window_size == 1
708
+ and not self.training
709
+ and not torch.is_grad_enabled()
710
+ and h_attn.device.type == "cpu"
711
+ ):
707
712
  # A one-wide window keeps only the diagonal: the softmax weights are
708
- # exactly 1 and 0, so the attention returns its value projection,
709
- # times the weights' dropout in training (the same (batch * heads,
710
- # L, L) mask nn.MultiheadAttention draws, of which only the
711
- # diagonal reaches the output). Same projection calls as
712
- # nn.MultiheadAttention (on its (seq, batch, embed) view), so
713
- # outputs and gradients are unchanged bit for bit, and so is the
714
- # RNG stream. (On Gaudi the full attention was faster.)
713
+ # exactly 1 and 0, so the attention returns its value projection.
714
+ # Same projection calls as nn.MultiheadAttention (on its (seq,
715
+ # batch, embed) view), so the output is unchanged bit for bit. (In
716
+ # training the weights carry dropout; on Gaudi the full attention
717
+ # was faster.)
715
718
  # ponytail: the unused query/key projections are computed too, to
716
719
  # keep the rounding; in_proj_weight[2E:] alone is ~2x less GEMM.
717
720
  embed_dim = self.attention.embed_dim
@@ -719,16 +722,6 @@ class _ResidualBlock(nn.Module):
719
722
  value = F.linear(
720
723
  seq_first, self.attention.in_proj_weight, self.attention.in_proj_bias
721
724
  )[..., 2 * embed_dim :]
722
- p = self.attention.dropout
723
- if self.training and p > 0.0:
724
- n_rows = seq_first.shape[1] * self.attention.num_heads
725
- keep = (
726
- value.new_empty(n_rows, seq_len, seq_len)
727
- .bernoulli_(1 - p)
728
- .diagonal(dim1=1, dim2=2)
729
- .div(1 - p)
730
- )
731
- value = value.reshape(seq_len, n_rows, -1) * keep.t().unsqueeze(-1)
732
725
  h_attn = (
733
726
  self.attention.out_proj(value.reshape(-1, embed_dim))
734
727
  .view(seq_first.shape)
@@ -60,7 +60,7 @@ class EEGInceptionMI(EEGModuleMixin, nn.Module):
60
60
  (:func:`~braindecode.functional.fft_conv1d`: same parameters, equal up
61
61
  to float rounding) instead of a direct convolution. ``None`` (default)
62
62
  decides per input with :func:`~braindecode.functional.prefer_fft_conv`
63
- (FFT on CPU and HPU where it was faster in benchmarks, direct on GPU).
63
+ (FFT on CPU where it was faster in benchmarks, direct on GPU and HPU).
64
64
 
65
65
  References
66
66
  ----------
@@ -340,12 +340,8 @@ class _InceptionModuleMI(nn.Module):
340
340
  X1 = torch.cat([conv(X1) for conv in self.conv_list], 1)
341
341
 
342
342
  # channels_last: same values, but torch's CPU max pool then vectorises
343
- # over channels instead of looping over them. CPU only: on other
344
- # devices the two layout copies cost more than they save.
345
- X2 = X
346
- if X.device.type == "cpu":
347
- X2 = X.contiguous(memory_format=torch.channels_last)
348
- X2 = self.pooling(X2)
343
+ # over channels instead of looping over them.
344
+ X2 = self.pooling(X.contiguous(memory_format=torch.channels_last))
349
345
  # An even kernel_unit pools n_times + 1 samples: drop the last one.
350
346
  X2 = self.pooling_conv(X2.contiguous())[..., : X.shape[-1]]
351
347
 
@@ -356,7 +356,7 @@ class EEGNeX(EEGModuleMixin, nn.Module):
356
356
 
357
357
 
358
358
  class _TemporalConv(nn.Conv2d):
359
- """``(1, k)`` Conv2d with "same" output length; on CPU and HPU, through
359
+ """``(1, k)`` Conv2d with "same" output length; on CPU, through
360
360
  :func:`~braindecode.functional.fft_conv1d` where
361
361
  :func:`~braindecode.functional.prefer_fft_conv` expects it to be faster."""
362
362
 
@@ -908,9 +908,7 @@ class _Attention(nn.Module):
908
908
  # Reshape to (3, batch, num_heads, seq_len, head_dim)
909
909
  qkv = qkv.reshape(qkv.shape[0], qkv.shape[1], 3, self.num_heads, -1)
910
910
  qkv = qkv.permute(2, 0, 3, 1, 4)
911
- # unbind, not qkv[0..2]: the backward of three selects writes three
912
- # zero-filled copies of the whole qkv tensor and sums them.
913
- q, k, v = qkv.unbind(0) # batch, num_heads, seq_len, head_dim
911
+ q, k, v = qkv[0], qkv[1], qkv[2] # batch, num_heads, seq_len, head_dim
914
912
 
915
913
  # 1. Rotary Positional Embeddings (RoPE)
916
914
  # Unlike standard absolute positional encodings, RoPE rotates the
@@ -19,7 +19,6 @@ from torch.nn.init import trunc_normal_
19
19
  from braindecode.functional import rescale_parameter
20
20
  from braindecode.models.base import EEGModuleMixin
21
21
  from braindecode.modules import MLP, DropPath
22
- from braindecode.modules.attention import _hpu_eager_fused_sdpa
23
22
  from braindecode.modules.blocks import PatchTokenizer
24
23
 
25
24
  # -----------------------------------------------------------------------------
@@ -1430,24 +1429,17 @@ class _Attention(nn.Module):
1430
1429
  relative_position_bias.permute(2, 0, 1).contiguous().unsqueeze(0)
1431
1430
  ) # 1, nH, Wh*Ww, Wh*Ww
1432
1431
 
1433
- # Fused kernel, same math. Not with attention dropout in training (it
1434
- # would draw other masks). On Gaudi, torch's SDPA trains ~12 % slower
1435
- # than the plain ops; the bridge's own fused kernel (eager mode, no
1436
- # mask) is used instead.
1437
- fused = not return_attention and (self.attn_drop.p == 0.0 or not self.training)
1438
- out: Optional[torch.Tensor] = None
1439
- if fused and q.device.type != "hpu":
1440
- out = nn.functional.scaled_dot_product_attention(
1432
+ # Fused kernel, same math. Not on Gaudi (Labram trains ~12 % slower there)
1433
+ # nor with attention dropout in training (it would draw other masks).
1434
+ if (
1435
+ not return_attention
1436
+ and q.device.type != "hpu"
1437
+ and (self.attn_drop.p == 0.0 or not self.training)
1438
+ ):
1439
+ x = nn.functional.scaled_dot_product_attention(
1441
1440
  q, k, v, attn_mask=attn_mask, scale=self.scale
1442
1441
  )
1443
- elif (
1444
- fused
1445
- and attn_mask is None
1446
- and not torch.jit.is_scripting()
1447
- and (q.dtype == torch.float32 or q.dtype == torch.bfloat16)
1448
- ):
1449
- out = _hpu_eager_fused_sdpa(q, k, v, self.scale)
1450
- if out is None:
1442
+ else:
1451
1443
  attn = (q * self.scale) @ k.transpose(-2, -1)
1452
1444
  if attn_mask is not None:
1453
1445
  attn = attn + attn_mask
@@ -1455,8 +1447,6 @@ class _Attention(nn.Module):
1455
1447
  if return_attention:
1456
1448
  return attn
1457
1449
  x = attn @ v
1458
- else:
1459
- x = out
1460
1450
  x = x.transpose(1, 2).reshape(B, N, -1)
1461
1451
 
1462
1452
  x = self.proj(x)
@@ -601,9 +601,7 @@ class _RotarySelfAttentionBlock(nn.Module):
601
601
  .reshape(B, N, 3, self.num_heads, C // self.num_heads)
602
602
  .permute(2, 0, 3, 1, 4)
603
603
  ) # (K, B, H, N, D)
604
- # unbind, not qkv[0..2]: the backward of three selects writes three
605
- # zero-filled copies of the whole qkv tensor and sums them.
606
- q, k, v = qkv.unbind(0)
604
+ q, k, v = qkv[0], qkv[1], qkv[2]
607
605
  q = self._rotate_queries_or_keys(q)
608
606
  k = self._rotate_queries_or_keys(k)
609
607
  attn = F.scaled_dot_product_attention(
@@ -12,7 +12,6 @@ import torch.nn as nn
12
12
  import torch.nn.functional as F
13
13
 
14
14
  from braindecode.models.base import EEGModuleMixin
15
- from braindecode.modules.attention import _scaled_dot_product_attention
16
15
 
17
16
 
18
17
  class PBT(EEGModuleMixin, nn.Module):
@@ -412,8 +411,13 @@ class _MHSA(nn.Module):
412
411
  k = k.view(B, T, self.n_head, C // self.n_head).transpose(1, 2)
413
412
  v = v.view(B, T, self.n_head, C // self.n_head).transpose(1, 2)
414
413
 
415
- y = _scaled_dot_product_attention(
416
- q, k, v, dropout_p=self.drop_prob if self.training else 0.0
414
+ y = torch.nn.functional.scaled_dot_product_attention(
415
+ q,
416
+ k,
417
+ v,
418
+ attn_mask=None,
419
+ dropout_p=self.drop_prob if self.training else 0.0,
420
+ is_causal=False,
417
421
  )
418
422
 
419
423
  # re-assemble heads -> (B, T, C)
@@ -15,10 +15,9 @@ import torch
15
15
  import torch.nn.functional as F
16
16
  from mne.datasets.utils import _get_path
17
17
  from torch import nn
18
+ from torch.nn import RMSNorm
18
19
 
19
20
  from braindecode.models.base import EEGModuleMixin
20
- from braindecode.modules.attention import _scaled_dot_product_attention
21
- from braindecode.modules.layers import RMSNorm
22
21
 
23
22
  logger = logging.getLogger(__name__)
24
23
 
@@ -440,8 +439,7 @@ class REVE(EEGModuleMixin, nn.Module):
440
439
  raise ValueError(
441
440
  "No positions provided and no default positions available. Please provide channel positions."
442
441
  )
443
- # One copy for the whole batch: the embedding below broadcasts.
444
- pos = self.default_pos.unsqueeze(0).to(eeg.device)
442
+ pos = self.default_pos.expand(batch_size, -1, -1).to(eeg.device)
445
443
 
446
444
  pos = FourierEmb4D.add_time_patch(pos, n_patches)
447
445
  # Positions stay in float32 for the Fourier features; the embedding
@@ -520,7 +518,6 @@ class GEGLU(nn.Module):
520
518
  class FeedForward(nn.Module):
521
519
  def __init__(self, dim: int, hidden_dim: int, geglu: bool):
522
520
  super().__init__()
523
- self.geglu = geglu
524
521
  self.net = nn.Sequential(
525
522
  RMSNorm(dim, eps=1e-6),
526
523
  nn.Linear(dim, hidden_dim * 2 if geglu else hidden_dim, bias=False),
@@ -529,15 +526,7 @@ class FeedForward(nn.Module):
529
526
  )
530
527
 
531
528
  def forward(self, x: torch.Tensor) -> torch.Tensor:
532
- if not self.geglu:
533
- return self.net(x)
534
- # GEGLU halves as two matmuls on the weight's row halves: contiguous
535
- # outputs instead of strided views of one output (copied on HPU).
536
- x = self.net[0](x)
537
- weight = self.net[1].weight
538
- half = weight.shape[0] // 2
539
- x, gates = F.linear(x, weight[:half]), F.linear(x, weight[half:])
540
- return self.net[3](F.gelu(gates) * x)
529
+ return self.net(x)
541
530
 
542
531
 
543
532
  #################################################################################
@@ -565,8 +554,7 @@ class Attention(nn.Module):
565
554
  q = q.unflatten(-1, (self.heads, -1)).transpose(1, 2)
566
555
  k = k.unflatten(-1, (self.heads, -1)).transpose(1, 2)
567
556
  v = v.unflatten(-1, (self.heads, -1)).transpose(1, 2)
568
- # ~700-token sequences: the fused kernel also beats lazy mode's graph.
569
- out = _scaled_dot_product_attention(q, k, v, fused_in_lazy=True)
557
+ out = F.scaled_dot_product_attention(q, k, v)
570
558
  return self.to_out(out.transpose(1, 2).flatten(2))
571
559
 
572
560
 
@@ -12,12 +12,11 @@ import torch
12
12
  from einops import rearrange
13
13
  from einops.layers.torch import Rearrange
14
14
  from torch import nn
15
- from torch.nn import RMSNorm
15
+ from torch.nn import RMSNorm, functional
16
16
 
17
17
  from braindecode.models.base import EEGModuleMixin
18
18
  from braindecode.models.util import extract_channel_locations_from_chs_info
19
19
  from braindecode.modules import PatchTokenizer
20
- from braindecode.modules.attention import _scaled_dot_product_attention
21
20
 
22
21
 
23
22
  class ZUNA(EEGModuleMixin, nn.Module, license="apache-2.0"):
@@ -404,16 +403,18 @@ class _RotaryPositionEmbedding(nn.Module):
404
403
 
405
404
  batch_size, sequence_length, num_heads, head_dim = query.shape
406
405
  work = torch.promote_types(query.dtype, torch.float32)
407
- # Each (real, imaginary) pair (a, b) rotates to (-b, a): swap the pair
408
- # here; the sign is in ``rotary_sine`` (see _ZUNAEncoder).
409
406
  query_pairs = query.to(work).reshape(
410
407
  batch_size, sequence_length, num_heads, head_dim // 2, 2
411
408
  )
412
409
  key_pairs = key.to(work).reshape(
413
410
  batch_size, sequence_length, num_heads, head_dim // 2, 2
414
411
  )
415
- rotated_query = self.merge_rotary_pairs(query_pairs.flip(-1))
416
- rotated_key = self.merge_rotary_pairs(key_pairs.flip(-1))
412
+ rotated_query = self.merge_rotary_pairs(
413
+ torch.stack((-query_pairs[..., 1], query_pairs[..., 0]), dim=-1)
414
+ )
415
+ rotated_key = self.merge_rotary_pairs(
416
+ torch.stack((-key_pairs[..., 1], key_pairs[..., 0]), dim=-1)
417
+ )
417
418
 
418
419
  query = (query.to(work) * rotary_cosine + rotated_query * rotary_sine).type_as(
419
420
  query
@@ -464,7 +465,7 @@ class _Attention(nn.Module):
464
465
  value = self.wv(input_tensor).reshape(attention_shape)
465
466
  query, key = self.rotary_embedding(query, key, rotary_cosine, rotary_sine)
466
467
 
467
- attention_output = _scaled_dot_product_attention(
468
+ attention_output = functional.scaled_dot_product_attention(
468
469
  query.transpose(1, 2),
469
470
  key.transpose(1, 2),
470
471
  value.transpose(1, 2),
@@ -605,12 +606,9 @@ class _ZUNAEncoder(nn.Module):
605
606
  rotary_frequencies.cos(),
606
607
  persistent=False,
607
608
  )
608
- # Sine with the pair rotation's sign folded in: -sin on the real, +sin
609
- # on the imaginary component of every pair (exact, saves a negation).
610
- pair_sign = torch.tensor([-1.0, 1.0]).repeat(rotary_frequencies.shape[-1] // 2)
611
609
  self.register_buffer(
612
610
  "rotary_sine",
613
- rotary_frequencies.sin() * pair_sign,
611
+ rotary_frequencies.sin(),
614
612
  persistent=False,
615
613
  )
616
614
 
@@ -834,57 +834,6 @@ class CATLite(nn.Module):
834
834
  return channel_score * x
835
835
 
836
836
 
837
- @torch.jit.unused
838
- def _hpu_eager_fused_sdpa(
839
- query: Tensor,
840
- key: Tensor,
841
- value: Tensor,
842
- scale: Optional[float] = None,
843
- fused_in_lazy: bool = False,
844
- ) -> Optional[Tensor]:
845
- # Lazy mode: None, the graph compiler already fuses torch's SDPA there
846
- # (unless the caller measured the fused kernel faster for its shapes).
847
- from habana_frameworks.torch.utils.internal import is_lazy
848
-
849
- if is_lazy() and not fused_in_lazy:
850
- return None
851
- from habana_frameworks.torch.hpex.kernels import FusedSDPA
852
-
853
- return FusedSDPA.apply(query, key, value, None, 0.0, False, scale, "None", False)
854
-
855
-
856
- def _scaled_dot_product_attention(
857
- query: Tensor,
858
- key: Tensor,
859
- value: Tensor,
860
- attn_mask: Optional[Tensor] = None,
861
- dropout_p: float = 0.0,
862
- fused_in_lazy: bool = False,
863
- ) -> Tensor:
864
- """``F.scaled_dot_product_attention``; Gaudi's fused kernel on HPU.
865
-
866
- In HPU eager mode, torch's SDPA runs op by op (the full
867
- ``(batch, heads, seq, seq)`` scores in device memory), 2-3.5x slower than
868
- the bridge's fused kernel on long sequences. The fused kernel is used
869
- without a mask or dropout (its dropout would draw other masks). In lazy
870
- mode only with ``fused_in_lazy=True``: the graph compiler fuses torch's
871
- SDPA too, faster on long sequences, slower on short ones.
872
- """
873
- if (
874
- not torch.jit.is_scripting()
875
- and query.device.type == "hpu"
876
- and attn_mask is None
877
- and dropout_p == 0.0
878
- and (query.dtype == torch.float32 or query.dtype == torch.bfloat16)
879
- ):
880
- out = _hpu_eager_fused_sdpa(query, key, value, fused_in_lazy=fused_in_lazy)
881
- if out is not None:
882
- return out
883
- return F.scaled_dot_product_attention(
884
- query, key, value, attn_mask=attn_mask, dropout_p=dropout_p
885
- )
886
-
887
-
888
837
  class MultiHeadAttention(nn.Module):
889
838
  """Multi-head self-attention block.
890
839
 
@@ -958,8 +907,12 @@ class MultiHeadAttention(nn.Module):
958
907
  dp = self.att_drop if self.training else 0.0
959
908
  if self.scale is not None:
960
909
  queries = queries * (self.scale * self.head_dim**0.5)
961
- out = _scaled_dot_product_attention(
962
- queries, keys, values, attn_mask=mask, dropout_p=dp
910
+ out = F.scaled_dot_product_attention(
911
+ queries,
912
+ keys,
913
+ values,
914
+ attn_mask=mask,
915
+ dropout_p=dp,
963
916
  )
964
917
 
965
918
  out = self.rearrange_unstack(out)
@@ -10,11 +10,11 @@ import math
10
10
  from typing import Dict, Optional
11
11
 
12
12
  import torch
13
+ import torch.nn.functional as F
13
14
  from torch import nn
14
15
 
15
16
  from braindecode.functional import sinusoidal_positional_encoding
16
17
  from braindecode.modules.activation import GatedLinearUnit
17
- from braindecode.modules.attention import _scaled_dot_product_attention
18
18
  from braindecode.modules.layers import ChannelMerger
19
19
 
20
20
 
@@ -28,19 +28,7 @@ class _ConvBlock(nn.Module):
28
28
  self.act = None if last else activation()
29
29
 
30
30
  def forward(self, x):
31
- # Taps more than (T - 1) // dilation steps off-centre only ever read the
32
- # zero padding: drop them (the same sum without its zero terms, fewer
33
- # multiply-adds at long dilations).
34
- d = self.conv.dilation[0]
35
- half = self.conv.kernel_size[0] // 2
36
- reach = (x.shape[-1] - 1) // d
37
- if reach < half:
38
- weight = self.conv.weight[:, :, half - reach : half + reach + 1]
39
- x = nn.functional.conv1d(
40
- x, weight, self.conv.bias, padding=reach * d, dilation=d
41
- )
42
- else:
43
- x = self.conv(x)
31
+ x = self.conv(x)
44
32
  if self.act is not None:
45
33
  x = self.act(x)
46
34
  return x
@@ -189,8 +177,7 @@ class _Attention(nn.Module):
189
177
  q = q.unflatten(-1, (h, -1)).transpose(1, 2)
190
178
  k = k.unflatten(-1, (h, -1)).transpose(1, 2)
191
179
  v = v.unflatten(-1, (h, -1)).transpose(1, 2)
192
- # scale = dim_head ** -0.5 = SDPA's default 1 / sqrt(q.shape[-1])
193
- out = _scaled_dot_product_attention(q, k, v)
180
+ out = F.scaled_dot_product_attention(q, k, v, scale=self.scale)
194
181
  # (b, h, n, d) -> (b, n, h * d)
195
182
  return self.to_out(out.transpose(1, 2).flatten(2))
196
183