braindecode 1.8.1.dev169698056__tar.gz → 1.8.1.dev169869285__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. {braindecode-1.8.1.dev169698056/braindecode.egg-info → braindecode-1.8.1.dev169869285}/PKG-INFO +1 -1
  2. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/functional/__init__.py +19 -1
  3. braindecode-1.8.1.dev169869285/braindecode/functional/attention.py +152 -0
  4. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/functional/functions.py +106 -1
  5. braindecode-1.8.1.dev169869285/braindecode/functional/initialization.py +139 -0
  6. braindecode-1.8.1.dev169869285/braindecode/functional/patches.py +105 -0
  7. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/atcnet.py +10 -14
  8. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/attn_sleep.py +9 -13
  9. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/axon.py +11 -4
  10. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/barista.py +27 -26
  11. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/base.py +53 -0
  12. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/bendr.py +20 -12
  13. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/brainbert.py +9 -8
  14. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/brainmodule.py +1 -1
  15. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/brainomni.py +23 -16
  16. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/brant.py +3 -3
  17. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/cbramod.py +12 -11
  18. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/codebrain.py +1 -1
  19. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/csbrain.py +14 -7
  20. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/ctnet.py +3 -30
  21. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/dance.py +6 -11
  22. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/deep4.py +6 -2
  23. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/diver1.py +11 -8
  24. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/duin.py +23 -14
  25. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/eegconformer.py +3 -15
  26. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/eegdino.py +12 -48
  27. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/eeginception_erp.py +4 -0
  28. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/eegminer.py +4 -0
  29. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/eegnet.py +4 -0
  30. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/eegpt.py +21 -270
  31. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/epint.py +26 -10
  32. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/ifnet.py +20 -24
  33. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/labram.py +7 -32
  34. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/luna.py +25 -72
  35. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/mapa.py +22 -14
  36. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/medformer.py +12 -6
  37. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/mirepnet.py +3 -12
  38. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/mscformer.py +3 -31
  39. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/mvpformer.py +18 -10
  40. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/neuropose.py +18 -18
  41. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/neurorvq.py +8 -12
  42. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/neurorvq_tokenizer.py +7 -3
  43. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/patchedtransformer.py +37 -22
  44. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/popt.py +2 -8
  45. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/reve.py +10 -10
  46. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/sensingdynamics.py +18 -19
  47. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/shallow_fbcsp.py +6 -2
  48. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/signal_jepa.py +24 -12
  49. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/sleepfm.py +3 -3
  50. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/sparcnet.py +14 -10
  51. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/steegformer.py +18 -30
  52. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/tcformer.py +37 -37
  53. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/tidnet.py +13 -4
  54. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/tmsanet.py +9 -9
  55. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/util.py +19 -3
  56. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/vemg2pose.py +20 -22
  57. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/zuna.py +2 -2
  58. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/__init__.py +8 -0
  59. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/attention.py +102 -84
  60. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/blocks.py +42 -61
  61. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/dance_modules.py +5 -3
  62. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/layers.py +47 -0
  63. braindecode-1.8.1.dev169869285/braindecode/version.py +1 -0
  64. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285/braindecode.egg-info}/PKG-INFO +1 -1
  65. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode.egg-info/SOURCES.txt +2 -0
  66. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/api.rst +13 -0
  67. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/whats_new.rst +16 -0
  68. braindecode-1.8.1.dev169698056/braindecode/functional/initialization.py +0 -52
  69. braindecode-1.8.1.dev169698056/braindecode/version.py +0 -1
  70. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/LICENSE.txt +0 -0
  71. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/MANIFEST.in +0 -0
  72. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/NOTICE.txt +0 -0
  73. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/README.rst +0 -0
  74. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/__init__.py +0 -0
  75. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/augmentation/__init__.py +0 -0
  76. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/augmentation/base.py +0 -0
  77. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/augmentation/functional.py +0 -0
  78. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/augmentation/transforms.py +0 -0
  79. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/classifier.py +0 -0
  80. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/__init__.py +0 -0
  81. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/_notebook_viewer.py +0 -0
  82. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/base.py +0 -0
  83. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/bbci.py +0 -0
  84. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/bcicomp.py +0 -0
  85. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/bids/__init__.py +0 -0
  86. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/bids/datasets.py +0 -0
  87. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/bids/hub.py +0 -0
  88. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/bids/hub_format.py +0 -0
  89. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/bids/hub_io.py +0 -0
  90. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/bids/hub_validation.py +0 -0
  91. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/bids/iterable.py +0 -0
  92. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/chb_mit.py +0 -0
  93. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/collate.py +0 -0
  94. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/mne.py +0 -0
  95. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/moabb.py +0 -0
  96. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/nmt.py +0 -0
  97. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/registry.py +0 -0
  98. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/siena.py +0 -0
  99. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/sleep_physio_challe_18.py +0 -0
  100. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/sleep_physionet.py +0 -0
  101. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/tuh.py +0 -0
  102. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/utils.py +0 -0
  103. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datasets/xy.py +0 -0
  104. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datautil/__init__.py +0 -0
  105. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datautil/channel_utils.py +0 -0
  106. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datautil/hub_formats.py +0 -0
  107. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datautil/serialization.py +0 -0
  108. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/datautil/util.py +0 -0
  109. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/eegneuralnet.py +0 -0
  110. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/functional/_real_dft.py +0 -0
  111. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/__init__.py +0 -0
  112. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/attentionbasenet.py +0 -0
  113. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/biot.py +0 -0
  114. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/config.py +0 -0
  115. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/contrawr.py +0 -0
  116. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/deepsleepnet.py +0 -0
  117. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/dgcnn.py +0 -0
  118. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/eeg_clip.py +0 -0
  119. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/eeginception_mi.py +0 -0
  120. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/eegitnet.py +0 -0
  121. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/eegnex.py +0 -0
  122. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/eegsimpleconv.py +0 -0
  123. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/eegsym.py +0 -0
  124. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/eegtcnet.py +0 -0
  125. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/emg2qwerty.py +0 -0
  126. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/fbcnet.py +0 -0
  127. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/fblightconvnet.py +0 -0
  128. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/fbmsnet.py +0 -0
  129. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/gcnsnet.py +0 -0
  130. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/guetschel2026.py +0 -0
  131. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/hybrid.py +0 -0
  132. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/meta_neuromotor.py +0 -0
  133. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/msvtnet.py +0 -0
  134. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/sccnet.py +0 -0
  135. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/seizure_transformer.py +0 -0
  136. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/sinc_shallow.py +0 -0
  137. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/sleep_stager_blanco_2020.py +0 -0
  138. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/sleep_stager_chambon_2018.py +0 -0
  139. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/sstdpn.py +0 -0
  140. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/summary.csv +0 -0
  141. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/syncnet.py +0 -0
  142. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/tcn.py +0 -0
  143. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/tfm_tokenizer.py +0 -0
  144. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/tsinception.py +0 -0
  145. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/models/usleep.py +0 -0
  146. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/activation.py +0 -0
  147. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/channels.py +0 -0
  148. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/convolution.py +0 -0
  149. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/filter.py +0 -0
  150. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/linear.py +0 -0
  151. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/linear_attention.py +0 -0
  152. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/parametrization.py +0 -0
  153. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/quantization.py +0 -0
  154. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/stats.py +0 -0
  155. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/util.py +0 -0
  156. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/modules/wrapper.py +0 -0
  157. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/preprocessing/__init__.py +0 -0
  158. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/preprocessing/eegprep_preprocess.py +0 -0
  159. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/preprocessing/mne_preprocess.py +0 -0
  160. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/preprocessing/preprocess.py +0 -0
  161. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/preprocessing/util.py +0 -0
  162. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/preprocessing/windowers.py +0 -0
  163. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/regressor.py +0 -0
  164. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/samplers/__init__.py +0 -0
  165. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/samplers/base.py +0 -0
  166. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/samplers/ssl.py +0 -0
  167. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/training/__init__.py +0 -0
  168. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/training/callbacks.py +0 -0
  169. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/training/losses.py +0 -0
  170. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/training/scoring.py +0 -0
  171. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/util.py +0 -0
  172. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/visualization/__init__.py +0 -0
  173. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/visualization/activations.py +0 -0
  174. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/visualization/attribution.py +0 -0
  175. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/visualization/confusion_matrices.py +0 -0
  176. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/visualization/frequency.py +0 -0
  177. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/visualization/metrics.py +0 -0
  178. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/visualization/sanity.py +0 -0
  179. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode/visualization/topology.py +0 -0
  180. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode.egg-info/dependency_links.txt +0 -0
  181. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode.egg-info/requires.txt +0 -0
  182. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/braindecode.egg-info/top_level.txt +0 -0
  183. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/Makefile +0 -0
  184. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/_templates/autosummary/class.rst +0 -0
  185. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/_templates/autosummary/class_in_subdir.rst +0 -0
  186. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/_templates/autosummary/function.rst +0 -0
  187. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/_templates/autosummary/function_in_subdir.rst +0 -0
  188. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/agent_docs.rst +0 -0
  189. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/cite.rst +0 -0
  190. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/conf.py +0 -0
  191. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/help.rst +0 -0
  192. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/index.rst +0 -0
  193. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/install/install.rst +0 -0
  194. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/install/install_pip.rst +0 -0
  195. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/install/install_source.rst +0 -0
  196. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/models/categorization/attention.rst +0 -0
  197. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/models/categorization/channel.rst +0 -0
  198. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/models/categorization/convolution.rst +0 -0
  199. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/models/categorization/filterbank.rst +0 -0
  200. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/models/categorization/gnn.rst +0 -0
  201. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/models/categorization/interpretable.rst +0 -0
  202. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/models/categorization/lbm.rst +0 -0
  203. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/models/categorization/recurrent.rst +0 -0
  204. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/models/categorization/spd.rst +0 -0
  205. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/models/models.rst +0 -0
  206. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/models/models_categorization.rst +0 -0
  207. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/models/models_table.rst +0 -0
  208. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/models/models_visualization.rst +0 -0
  209. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/sg_execution_times.rst +0 -0
  210. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/docs/user_guide/channel_strategies.rst +0 -0
  211. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/pyproject.toml +0 -0
  212. {braindecode-1.8.1.dev169698056 → braindecode-1.8.1.dev169869285}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: braindecode
3
- Version: 1.8.1.dev169698056
3
+ Version: 1.8.1.dev169869285
4
4
  Summary: Deep learning software to decode EEG, ECG or MEG signals
5
5
  Author-email: Robin Tibor Schirrmeister <robintibor@gmail.com>, Bruno Aristimunha Pinto <b.aristimunha@gmail.com>, Alexandre Gramfort <agramfort@meta.com>
6
6
  Maintainer-email: Alexandre Gramfort <agramfort@meta.com>, Bruno Aristimunha Pinto <b.aristimunha@gmail.com>, Robin Tibor Schirrmeister <robintibor@gmail.com>
@@ -1,5 +1,7 @@
1
+ from .attention import scaled_dot_product_attention
1
2
  from .functions import (
2
3
  _get_gaussian_kernel1d,
4
+ apply_rotary,
3
5
  daubechies_filters,
4
6
  drop_path,
5
7
  dwt_max_level,
@@ -10,6 +12,9 @@ from .functions import (
10
12
  pairwise_iou_1d,
11
13
  plv_time,
12
14
  prefer_fft_conv,
15
+ rotary_angles,
16
+ rotary_frequencies,
17
+ rotate_half,
13
18
  rotate_pairs,
14
19
  safe_log,
15
20
  sinusoidal_positional_encoding,
@@ -17,10 +22,16 @@ from .functions import (
17
22
  square,
18
23
  wavelet_decomposition,
19
24
  )
20
- from .initialization import glorot_weight_zero_bias, rescale_parameter
25
+ from .initialization import (
26
+ glorot_weight_zero_bias,
27
+ init_weights_,
28
+ rescale_parameter,
29
+ )
30
+ from .patches import pad_or_crop_to_patches, patch_count
21
31
 
22
32
  __all__ = [
23
33
  "_get_gaussian_kernel1d",
34
+ "apply_rotary",
24
35
  "daubechies_filters",
25
36
  "drop_path",
26
37
  "dwt_max_level",
@@ -28,15 +39,22 @@ __all__ = [
28
39
  "hilbert_freq",
29
40
  "identity",
30
41
  "iou_1d",
42
+ "pad_or_crop_to_patches",
31
43
  "pairwise_iou_1d",
44
+ "patch_count",
32
45
  "plv_time",
33
46
  "prefer_fft_conv",
47
+ "rotary_angles",
48
+ "rotary_frequencies",
49
+ "rotate_half",
34
50
  "rotate_pairs",
35
51
  "safe_log",
52
+ "scaled_dot_product_attention",
36
53
  "sinusoidal_positional_encoding",
37
54
  "spectral_input",
38
55
  "square",
39
56
  "wavelet_decomposition",
40
57
  "glorot_weight_zero_bias",
41
58
  "rescale_parameter",
59
+ "init_weights_",
42
60
  ]
@@ -0,0 +1,152 @@
1
+ """Scaled dot-product attention with the device-specific paths in one place."""
2
+
3
+ # Authors: Bruno Aristimunha <b.aristimunha@gmail.com>
4
+ #
5
+ # License: BSD (3-clause)
6
+
7
+ import math
8
+ from typing import Optional
9
+
10
+ import torch
11
+ import torch.nn.functional as F
12
+ from torch import Tensor
13
+
14
+
15
+ @torch.jit.unused
16
+ def _hpu_eager_fused_sdpa(
17
+ query: Tensor,
18
+ key: Tensor,
19
+ value: Tensor,
20
+ scale: Optional[float] = None,
21
+ fused_in_lazy: bool = False,
22
+ ) -> Optional[Tensor]:
23
+ # Lazy mode: None, the graph compiler already fuses torch's SDPA there
24
+ # (unless the caller measured the fused kernel faster for its shapes).
25
+ from habana_frameworks.torch.utils.internal import is_lazy
26
+
27
+ if is_lazy() and not fused_in_lazy:
28
+ return None
29
+ from habana_frameworks.torch.hpex.kernels import FusedSDPA
30
+
31
+ # Strided q/k/v views (heads split off a projection) give wrong outputs and
32
+ # gradients at some shapes; contiguous copies give the right result.
33
+ query, key, value = query.contiguous(), key.contiguous(), value.contiguous()
34
+ return FusedSDPA.apply(query, key, value, None, 0.0, False, scale, "None", False)
35
+
36
+
37
+ @torch.jit.unused
38
+ def _hpu_lazy() -> bool:
39
+ from habana_frameworks.torch.utils.internal import is_lazy
40
+
41
+ return is_lazy()
42
+
43
+
44
+ def _sdpa_math_dropout(
45
+ query: Tensor,
46
+ key: Tensor,
47
+ value: Tensor,
48
+ dropout_p: float,
49
+ scale: Optional[float] = None,
50
+ ) -> Tensor:
51
+ # torch's math path for SDPA with dropout, op for op, without the pass of
52
+ # ``_safe_softmax`` that zeroes fully masked rows (none without a mask):
53
+ # same values, same dropout draws.
54
+ if scale is None:
55
+ scale = 1.0 / math.sqrt(query.size(-1))
56
+ half = math.sqrt(scale)
57
+ attn = torch.matmul(query * half, key.transpose(-2, -1) * half)
58
+ attn = F.dropout(attn.softmax(-1), dropout_p, True)
59
+ return torch.matmul(attn, value)
60
+
61
+
62
+ def scaled_dot_product_attention(
63
+ query: Tensor,
64
+ key: Tensor,
65
+ value: Tensor,
66
+ attn_mask: Optional[Tensor] = None,
67
+ dropout_p: float = 0.0,
68
+ scale: Optional[float] = None,
69
+ fused_in_lazy: bool = False,
70
+ exact: bool = False,
71
+ ) -> Tensor:
72
+ """``F.scaled_dot_product_attention``; Gaudi's fused kernel on HPU.
73
+
74
+ Parameters
75
+ ----------
76
+ query, key, value : torch.Tensor
77
+ Shape ``(..., seq, head_dim)``; ``key``/``value`` may have another
78
+ sequence length.
79
+ attn_mask : torch.Tensor, optional
80
+ Boolean (``True`` takes part) or additive mask, as in torch.
81
+ dropout_p : float, default=0.0
82
+ Dropout on the attention weights; pass ``0.0`` in eval mode.
83
+ scale : float, optional
84
+ Score scale; ``None`` is ``1 / sqrt(head_dim)``.
85
+ fused_in_lazy : bool, default=False
86
+ Use Gaudi's fused kernel in HPU lazy mode too.
87
+ exact : bool, default=False
88
+ Run the textbook op order instead of torch's kernels:
89
+ ``softmax((q @ k^T) / sqrt(d)) @ v``, or ``softmax((q @ k^T) * scale) @ v``
90
+ when ``scale`` is given, with dropout on the weights. Bit-identical to
91
+ a hand-written attention; torch's kernels round differently (its math
92
+ path scales ``q`` and ``k`` by ``sqrt(scale)`` each before the matmul,
93
+ its fused CPU kernel runs a blocked softmax), about 1e-6 apart.
94
+
95
+ Returns
96
+ -------
97
+ torch.Tensor
98
+ Shape ``(..., seq, head_dim)``.
99
+
100
+ In HPU eager mode, torch's SDPA runs op by op (the full
101
+ ``(batch, heads, seq, seq)`` scores in device memory), 2-3.5x slower than
102
+ the bridge's fused kernel on long sequences. The fused kernel is used
103
+ without a mask or dropout (its dropout would draw other masks). In lazy
104
+ mode only with ``fused_in_lazy=True``: the graph compiler fuses torch's
105
+ SDPA too, faster on long sequences, slower on short ones.
106
+ """
107
+ if exact:
108
+ scores = torch.matmul(query, key.transpose(-2, -1))
109
+ if scale is None:
110
+ scores = scores / math.sqrt(query.size(-1))
111
+ else:
112
+ scores = scores * scale
113
+ if attn_mask is not None:
114
+ if attn_mask.dtype == torch.bool:
115
+ scores = scores.masked_fill(~attn_mask, float("-inf"))
116
+ else:
117
+ scores = scores + attn_mask
118
+ weights = scores.softmax(dim=-1)
119
+ if dropout_p > 0.0:
120
+ weights = F.dropout(weights, dropout_p, True)
121
+ return torch.matmul(weights, value)
122
+ if (
123
+ not torch.jit.is_scripting()
124
+ and query.device.type == "hpu"
125
+ and attn_mask is None
126
+ and dropout_p == 0.0
127
+ and (query.dtype == torch.float32 or query.dtype == torch.bfloat16)
128
+ ):
129
+ out = _hpu_eager_fused_sdpa(
130
+ query, key, value, scale=scale, fused_in_lazy=fused_in_lazy
131
+ )
132
+ if out is not None:
133
+ return out
134
+ if (
135
+ not torch.jit.is_scripting()
136
+ and dropout_p > 0.0
137
+ and attn_mask is None
138
+ and (query.dtype == torch.float32 or query.dtype == torch.float64)
139
+ and (
140
+ query.device.type == "cpu"
141
+ or (query.device.type == "hpu" and not _hpu_lazy())
142
+ )
143
+ ):
144
+ # CPU and HPU eager run SDPA with dropout through the math path.
145
+ return _sdpa_math_dropout(query, key, value, dropout_p, scale)
146
+ if scale is None: # torch 2.0's signature has no ``scale``
147
+ return F.scaled_dot_product_attention(
148
+ query, key, value, attn_mask=attn_mask, dropout_p=dropout_p
149
+ )
150
+ return F.scaled_dot_product_attention(
151
+ query, key, value, attn_mask=attn_mask, dropout_p=dropout_p, scale=scale
152
+ )
@@ -588,6 +588,7 @@ def sinusoidal_positional_encoding(
588
588
  dim: int,
589
589
  device: torch.device | None = None,
590
590
  dtype: torch.dtype = torch.float32,
591
+ base: float = 10000.0,
591
592
  ) -> torch.Tensor:
592
593
  r"""Fixed sine/cosine positional-encoding table of shape ``(n_positions, dim)``.
593
594
 
@@ -609,6 +610,9 @@ def sinusoidal_positional_encoding(
609
610
  Device of the table (default: CPU), for tables built inside ``forward``.
610
611
  dtype : torch.dtype
611
612
  Floating dtype the table is computed in.
613
+ base : float, default=10000.0
614
+ Longest wavelength, the ``10000`` of Vaswani et al.; SignalJEPA uses the
615
+ largest number of time samples it encodes.
612
616
 
613
617
  Returns
614
618
  -------
@@ -620,7 +624,7 @@ def sinusoidal_positional_encoding(
620
624
  position = torch.arange(n_positions, device=device).unsqueeze(1).to(dtype)
621
625
  div_term = torch.exp(
622
626
  torch.arange(0, dim_even, 2, device=device).to(dtype)
623
- * (-math.log(10000.0) / dim_even)
627
+ * (-math.log(base) / dim_even)
624
628
  )
625
629
  pe = torch.zeros(n_positions, dim_even, device=device, dtype=dtype)
626
630
  pe[:, 0::2] = torch.sin(position * div_term)
@@ -646,3 +650,104 @@ def rotate_pairs(x: torch.Tensor) -> torch.Tensor:
646
650
  """
647
651
  pairs = x.unflatten(-1, (-1, 2))
648
652
  return torch.stack((-pairs[..., 1], pairs[..., 0]), dim=-1).flatten(-2)
653
+
654
+
655
+ def rotate_half(x: torch.Tensor) -> torch.Tensor:
656
+ """Rotate the two feature halves from ``(a, b)`` to ``(-b, a)``.
657
+
658
+ The half-split layout of GPT-NeoX / LLaMA rotary embeddings; see
659
+ :func:`rotate_pairs` for the interleaved layout.
660
+
661
+ Parameters
662
+ ----------
663
+ x : torch.Tensor
664
+ Tensor of shape ``(..., features)`` with an even final dimension.
665
+
666
+ Returns
667
+ -------
668
+ torch.Tensor
669
+ Same shape, device and dtype as ``x``.
670
+ """
671
+ first, second = x.chunk(2, dim=-1)
672
+ return torch.cat((-second, first), dim=-1)
673
+
674
+
675
+ def rotary_frequencies(
676
+ head_dim: int,
677
+ base: float = 10000.0,
678
+ device: Optional[torch.device] = None,
679
+ dtype: torch.dtype = torch.float32,
680
+ ) -> torch.Tensor:
681
+ """Inverse frequencies of a rotary embedding, ``1 / base ** (2 i / head_dim)``.
682
+
683
+ Parameters
684
+ ----------
685
+ head_dim : int
686
+ Even feature dimension that is rotated.
687
+ base : float, default=10000.0
688
+ Base period (``theta``).
689
+ device : torch.device, optional
690
+ dtype : torch.dtype, default=torch.float32
691
+ Precision of the table; the angles inherit it.
692
+
693
+ Returns
694
+ -------
695
+ torch.Tensor
696
+ Shape ``(head_dim // 2,)``.
697
+ """
698
+ exponent = torch.arange(0, head_dim, 2, device=device, dtype=dtype) / head_dim
699
+ return 1.0 / (base**exponent)
700
+
701
+
702
+ def rotary_angles(
703
+ positions: torch.Tensor, inv_freq: torch.Tensor, interleaved: bool = True
704
+ ) -> torch.Tensor:
705
+ """Rotation angles of each position, laid out to match the feature layout.
706
+
707
+ Parameters
708
+ ----------
709
+ positions : torch.Tensor
710
+ Shape ``(...,)``; same dtype as ``inv_freq`` for exact angles.
711
+ inv_freq : torch.Tensor
712
+ Shape ``(head_dim // 2,)``, from :func:`rotary_frequencies`.
713
+ interleaved : bool, default=True
714
+ ``True`` repeats each angle for its adjacent pair (:func:`rotate_pairs`);
715
+ ``False`` concatenates the angles twice (:func:`rotate_half`).
716
+
717
+ Returns
718
+ -------
719
+ torch.Tensor
720
+ Shape ``(..., head_dim)``; pass ``.cos()`` and ``.sin()`` to
721
+ :func:`apply_rotary`.
722
+ """
723
+ angles = positions.unsqueeze(-1) * inv_freq
724
+ if interleaved:
725
+ return angles.repeat_interleave(2, dim=-1)
726
+ return torch.cat((angles, angles), dim=-1)
727
+
728
+
729
+ def apply_rotary(
730
+ x: torch.Tensor, cos: torch.Tensor, sin: torch.Tensor, interleaved: bool = True
731
+ ) -> torch.Tensor:
732
+ """Rotate ``x`` by the angles whose cosine and sine are given.
733
+
734
+ ``x * cos + rotate(x) * sin``, where ``rotate`` is :func:`rotate_pairs`
735
+ (``interleaved=True``) or :func:`rotate_half`. ``cos`` and ``sin`` must
736
+ broadcast to ``x``; casting is left to the caller.
737
+
738
+ Parameters
739
+ ----------
740
+ x : torch.Tensor
741
+ Shape ``(..., head_dim)``.
742
+ cos, sin : torch.Tensor
743
+ From :func:`rotary_angles`.
744
+ interleaved : bool, default=True
745
+ Feature layout, as in :func:`rotary_angles`.
746
+
747
+ Returns
748
+ -------
749
+ torch.Tensor
750
+ Same shape as ``x``.
751
+ """
752
+ rotated = rotate_pairs(x) if interleaved else rotate_half(x)
753
+ return x * cos + rotated * sin
@@ -0,0 +1,139 @@
1
+ import math
2
+
3
+ import torch
4
+ from torch import nn
5
+ from torch.nn.utils import parametrize
6
+
7
+
8
+ def glorot_weight_zero_bias(model):
9
+ """Set the weights of BatchNorm layers to one and all biases to zero.
10
+
11
+ Despite its name, this function does not apply the Glorot (Xavier)
12
+ initialization: other weights keep the initialization of their layer
13
+ (PyTorch's default, or Xavier uniform for the max-norm constrained layers
14
+ such as :class:`braindecode.modules.Conv2dWithConstraint`). The name is
15
+ kept for backward compatibility.
16
+
17
+ Parameters
18
+ ----------
19
+ model : Module
20
+ """
21
+ for module in model.modules():
22
+ # ``weight``/``bias`` can be None (e.g. BatchNorm with affine=False)
23
+ weight = getattr(module, "weight", None)
24
+ if isinstance(weight, torch.Tensor) and "BatchNorm" in type(module).__name__:
25
+ nn.init.constant_(weight, 1)
26
+ bias = getattr(module, "bias", None)
27
+ if isinstance(bias, torch.Tensor):
28
+ nn.init.constant_(bias, 0)
29
+
30
+
31
+ def rescale_parameter(param, layer_id):
32
+ r"""Recaling the l-th transformer layer.
33
+
34
+ Rescales the parameter tensor by the inverse square root of the layer id.
35
+ Made inplace. :math:`\frac{1}{\sqrt{2 \cdot \text{layer\_id}}}` [Beit2022]
36
+
37
+ In the labram, this is used to rescale the output matrices
38
+ (i.e., the last linear projection within each sub-layer) of the
39
+ self-attention module.
40
+
41
+ Parameters
42
+ ----------
43
+ param: :class:`torch.Tensor`
44
+ tensor to be rescaled
45
+ layer_id: int
46
+ layer id in the neural network
47
+
48
+ References
49
+ ----------
50
+ [Beit2022] Hangbo Bao, Li Dong, Songhao Piao, Furu We (2022). BEIT: BERT
51
+ Pre-Training of Image Transformers.
52
+ """
53
+ param.div_(math.sqrt(2.0 * layer_id))
54
+
55
+
56
+ def init_weights_(
57
+ module,
58
+ weights=None,
59
+ norms=(nn.LayerNorm,),
60
+ init_parametrized_original=False,
61
+ ):
62
+ """Initialize one module by layer type; apply to a model with ``model.apply``.
63
+
64
+ The first entry of ``weights`` whose type matches ``module`` gives its rule,
65
+ as in an ``if``/``elif`` chain; modules of a type in ``norms`` get a unit
66
+ weight and a zero bias; nothing else is touched. The default is the
67
+ timm/ViT scheme (truncated-normal ``nn.Linear`` weights with std 0.02,
68
+ unit/zero ``nn.LayerNorm``). Models pass their own rules to reproduce their
69
+ reference initialization exactly.
70
+
71
+ Parameters
72
+ ----------
73
+ module : torch.nn.Module
74
+ weights : dict or None
75
+ ``{layer type or tuple of types: rule}``. A rule is a function applied
76
+ to the ``weight`` (the ``bias`` is then set to zero), or a pair
77
+ ``(weight_fn, bias_fn)`` where either may be ``None`` to leave that
78
+ tensor as it is. For a layer without a ``weight`` attribute (e.g.
79
+ ``nn.LSTM``) the functions apply to every parameter whose name contains
80
+ ``"weight"`` / ``"bias"``. ``None`` uses
81
+ ``{nn.Linear: partial(nn.init.trunc_normal_, std=0.02)}``.
82
+ norms : tuple of type
83
+ Normalization layer types set to weight 1 and bias 0 (missing affine
84
+ parameters are skipped). ``()`` leaves normalization layers alone.
85
+ init_parametrized_original : bool
86
+ For a layer whose ``weight`` is parametrized (e.g. max-norm), initialize
87
+ the unconstrained ``parametrizations.weight.original`` instead of the
88
+ computed ``weight``.
89
+
90
+ Examples
91
+ --------
92
+ >>> from functools import partial
93
+ >>> from torch import nn
94
+ >>> model = nn.Sequential(nn.Linear(4, 4), nn.LayerNorm(4))
95
+ >>> _ = model.apply(init_weights_) # timm/ViT default
96
+ >>> kaiming = partial(nn.init.kaiming_normal_, mode="fan_out")
97
+ >>> rule = {nn.Linear: (kaiming, None)} # keep the default bias
98
+ >>> _ = model.apply(partial(init_weights_, weights=rule, norms=()))
99
+ """
100
+ if weights is None:
101
+ weights = {nn.Linear: _trunc_normal_002}
102
+ for types, rule in weights.items():
103
+ if isinstance(module, types):
104
+ weight_fn, bias_fn = (
105
+ rule if isinstance(rule, tuple) else (rule, nn.init.zeros_)
106
+ )
107
+ if not hasattr(module, "weight"): # e.g. nn.LSTM: weight_ih_l0, ...
108
+ for name, param in module.named_parameters(recurse=False):
109
+ fn = (
110
+ weight_fn
111
+ if "weight" in name
112
+ else bias_fn
113
+ if "bias" in name
114
+ else None
115
+ )
116
+ if fn is not None:
117
+ fn(param)
118
+ return
119
+ if isinstance(module.weight, nn.parameter.UninitializedParameter):
120
+ return # lazy layer: initialized when it gets its shape
121
+ if weight_fn is not None:
122
+ weight = module.weight
123
+ if init_parametrized_original and parametrize.is_parametrized(
124
+ module, "weight"
125
+ ):
126
+ weight = module.parametrizations.weight.original
127
+ weight_fn(weight)
128
+ if bias_fn is not None and getattr(module, "bias", None) is not None:
129
+ bias_fn(module.bias)
130
+ return
131
+ if norms and isinstance(module, norms):
132
+ if getattr(module, "weight", None) is not None:
133
+ nn.init.ones_(module.weight)
134
+ if getattr(module, "bias", None) is not None:
135
+ nn.init.zeros_(module.bias)
136
+
137
+
138
+ def _trunc_normal_002(tensor):
139
+ return nn.init.trunc_normal_(tensor, std=0.02)
@@ -0,0 +1,105 @@
1
+ """Cutting a time axis into patches: how many, and padding or cropping to fit."""
2
+
3
+ # Authors: Bruno Aristimunha <b.aristimunha@gmail.com>
4
+ #
5
+ # License: BSD (3-clause)
6
+
7
+ import torch
8
+ import torch.nn.functional as F
9
+
10
+ _ON_NON_DIVISIBLE = ("pad", "crop", "error")
11
+
12
+
13
+ def _check_on_non_divisible(on_non_divisible: str) -> None:
14
+ """Raise a ``ValueError`` for an unknown ``on_non_divisible`` value."""
15
+ if on_non_divisible not in _ON_NON_DIVISIBLE:
16
+ raise ValueError(
17
+ "on_non_divisible must be 'pad', 'crop', or 'error', "
18
+ f"got {on_non_divisible!r}."
19
+ )
20
+
21
+
22
+ def patch_count(
23
+ n_times: int, patch_size: int, on_non_divisible: str = "pad", step: int = 0
24
+ ) -> int:
25
+ """Number of patches cut from ``n_times`` samples.
26
+
27
+ Parameters
28
+ ----------
29
+ n_times : int
30
+ Length of the axis that is patched.
31
+ patch_size : int
32
+ Samples per patch.
33
+ on_non_divisible : {"pad", "crop", "error"}, default="pad"
34
+ A last, incomplete patch is zero-padded (``"pad"``), dropped
35
+ (``"crop"``) or raises a ``ValueError``.
36
+ step : int, default=0
37
+ Distance between patch starts; ``0`` means ``patch_size``
38
+ (non-overlapping).
39
+
40
+ Returns
41
+ -------
42
+ int
43
+ Number of patches.
44
+ """
45
+ if step <= 0:
46
+ step = patch_size
47
+ if n_times < 1:
48
+ raise ValueError(f"n_times must be positive, got {n_times}.")
49
+ if n_times < patch_size:
50
+ if on_non_divisible == "pad":
51
+ return 1
52
+ if on_non_divisible == "crop":
53
+ raise ValueError(
54
+ f"Need at least one full patch of {patch_size} samples, got {n_times}."
55
+ )
56
+ elif (n_times - patch_size) % step == 0:
57
+ return (n_times - patch_size) // step + 1
58
+ elif on_non_divisible != "error":
59
+ return (n_times - patch_size) // step + 1 + (on_non_divisible == "pad")
60
+ raise ValueError(
61
+ f"Time dimension ({n_times}) is not divisible by patch_size ({patch_size})"
62
+ + ("." if step == patch_size else f" with patch step {step}.")
63
+ )
64
+
65
+
66
+ def pad_or_crop_to_patches(
67
+ x: torch.Tensor,
68
+ patch_size: int,
69
+ on_non_divisible: str = "pad",
70
+ step: int = 0,
71
+ min_patches: int = 1,
72
+ center: bool = False,
73
+ ) -> torch.Tensor:
74
+ """Right zero-pad or crop the last axis so the patches tile it.
75
+
76
+ A tiled axis is returned as is. An axis short of ``min_patches`` patches is
77
+ zero-padded up to that many, with half the missing ones (whole steps)
78
+ before it if ``center``.
79
+
80
+ Parameters
81
+ ----------
82
+ x : torch.Tensor
83
+ Shape ``(..., n_times)``.
84
+ patch_size, on_non_divisible, step
85
+ As in :func:`patch_count`.
86
+ min_patches : int, default=1
87
+ Least number of patches on the returned axis.
88
+ center : bool, default=False
89
+ Pad half the missing patches on the left.
90
+
91
+ Returns
92
+ -------
93
+ torch.Tensor
94
+ Shape ``(..., patch_size + (n_patches - 1) * step)``.
95
+ """
96
+ n_patches = patch_count(x.shape[-1], patch_size, on_non_divisible, step)
97
+ step = step if step > 0 else patch_size
98
+ left = 0
99
+ if n_patches < min_patches:
100
+ left = (min_patches - n_patches) // 2 * step if center else 0
101
+ n_patches = min_patches
102
+ target = patch_size + (n_patches - 1) * step
103
+ if target > x.shape[-1]:
104
+ return F.pad(x, (left, target - x.shape[-1] - left))
105
+ return x[..., :target]
@@ -1,7 +1,6 @@
1
1
  # Authors: Cedric Rommel <cedric.rommel@inria.fr>
2
2
  #
3
3
  # License: BSD (3-clause)
4
- import math
5
4
  from typing import Optional
6
5
 
7
6
  import torch
@@ -10,6 +9,7 @@ from mne.utils import warn
10
9
  from torch import nn
11
10
  from torch.nn.utils.parametrize import is_parametrized, register_parametrization
12
11
 
12
+ from braindecode.functional import scaled_dot_product_attention
13
13
  from braindecode.models.base import EEGModuleMixin
14
14
  from braindecode.modules import (
15
15
  CausalConv1d,
@@ -826,6 +826,12 @@ class _TCNResidualBlock(nn.Module):
826
826
  # (reshaping_conv may be nn.Identity, which the helper skips).
827
827
  _register_max_norm(conv_max_norm, self.conv1, self.conv2, self.reshaping_conv)
828
828
 
829
+ def reset_parameters(self) -> None:
830
+ """Initialize this block's weights (the constructor initializes each
831
+ convolution as it builds it)."""
832
+ nn.init.kaiming_uniform_(self.conv1.weight)
833
+ nn.init.kaiming_uniform_(self.conv2.weight)
834
+
829
835
  def forward(self, X):
830
836
  # Dimension: (batch_size, F2, Tw)
831
837
  # ----- Double dilated convolutions -----
@@ -928,20 +934,10 @@ class _MHA(nn.Module):
928
934
  K_ = torch.cat(K.split(self.head_dim, -1), 0) # (B', S, D')
929
935
  V_ = torch.cat(V.split(self.head_dim, -1), 0) # (B', S, D')
930
936
 
931
- # Attention weights of size (num_heads * batch_size, n, m):
932
- # measures how similar each pair of Q and K is.
933
- W = torch.softmax(
934
- Q_.bmm(K_.transpose(-2, -1)) / math.sqrt(self.head_dim),
935
- -1, # (B', D', S)
936
- ) # (B', N, M)
937
-
938
- # Multihead output (batch_size, seq_len, dim):
939
- # weighted sum of V where a value gets more weight if its corresponding
940
- # key has larger dot product with the query.
937
+ # Multihead output (batch_size, seq_len, dim): softmax(Q K^T / sqrt(d)) V
938
+ # per head, heads merged back along the feature axis.
941
939
  H = torch.cat(
942
- (W.bmm(V_)).split( # (B', S, S) # (B', S, D')
943
- batch_size, 0
944
- ), # [(B, S, D')] * num_heads
940
+ scaled_dot_product_attention(Q_, K_, V_, exact=True).split(batch_size, 0),
945
941
  -1,
946
942
  ) # (B, S, D)
947
943