braindecode 0.1.6.4__tar.gz → 0.1.7__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 (72) hide show
  1. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/Braindecode.egg-info/PKG-INFO +23 -1
  2. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/PKG-INFO +23 -1
  3. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/README.rst +22 -0
  4. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/datautil/signalproc.py +1 -0
  5. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/experiments/experiment.py +13 -6
  6. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/models/deep4.py +11 -11
  7. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/models/eegnet.py +5 -4
  8. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/models/util.py +14 -8
  9. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/torch_ext/util.py +17 -2
  10. Braindecode-0.1.7/braindecode/visualization/__init__.py +3 -0
  11. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/visualization/perturbation.py +28 -4
  12. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/visualization/plot.py +3 -2
  13. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/docs/index.rst +24 -0
  14. Braindecode-0.1.7/docs/notebooks/BBCI_Data.ipynb +845 -0
  15. Braindecode-0.1.7/docs/notebooks/BBCI_Data_Start_Stop.ipynb +802 -0
  16. Braindecode-0.1.7/docs/notebooks/BBCI_Data_Trialwise.ipynb +780 -0
  17. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/docs/notebooks/Cropped_Decoding.ipynb +27 -89
  18. Braindecode-0.1.7/docs/notebooks/Experiment_Class.ipynb +804 -0
  19. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/docs/notebooks/TrialWise_Decoding.ipynb +50 -116
  20. Braindecode-0.1.7/docs/notebooks/visualization/Perturbation.ipynb +743 -0
  21. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/setup.py +1 -1
  22. Braindecode-0.1.6.4/braindecode/visualization/__init__.py +0 -0
  23. Braindecode-0.1.6.4/docs/notebooks/BBCI_Data.ipynb +0 -933
  24. Braindecode-0.1.6.4/docs/notebooks/BBCI_Data_Start_Stop.ipynb +0 -842
  25. Braindecode-0.1.6.4/docs/notebooks/BBCI_Data_Trialwise.ipynb +0 -820
  26. Braindecode-0.1.6.4/docs/notebooks/Experiment_Class.ipynb +0 -807
  27. Braindecode-0.1.6.4/docs/notebooks/visualization/Perturbation.ipynb +0 -840
  28. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/Braindecode.egg-info/SOURCES.txt +0 -0
  29. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/Braindecode.egg-info/dependency_links.txt +0 -0
  30. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/Braindecode.egg-info/not-zip-safe +0 -0
  31. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/Braindecode.egg-info/requires.txt +0 -0
  32. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/Braindecode.egg-info/top_level.txt +0 -0
  33. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/LICENSE.txt +0 -0
  34. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/MANIFEST.in +0 -0
  35. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/__init__.py +0 -0
  36. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/datasets/__init__.py +0 -0
  37. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/datasets/bbci.py +0 -0
  38. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/datasets/bcic_iv_2a.py +0 -0
  39. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/datasets/multiple.py +0 -0
  40. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/datasets/sensor_positions.py +0 -0
  41. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/datautil/__init__.py +0 -0
  42. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/datautil/iterators.py +0 -0
  43. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/datautil/signal_target.py +0 -0
  44. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/datautil/splitters.py +0 -0
  45. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/datautil/trial_segment.py +0 -0
  46. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/datautil/util.py +0 -0
  47. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/experiments/__init__.py +0 -0
  48. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/experiments/monitors.py +0 -0
  49. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/experiments/stopcriteria.py +0 -0
  50. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/mne_ext/__init__.py +0 -0
  51. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/mne_ext/signalproc.py +0 -0
  52. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/models/__init__.py +0 -0
  53. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/models/shallow_fbcsp.py +0 -0
  54. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/torch_ext/__init__.py +0 -0
  55. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/torch_ext/constraints.py +0 -0
  56. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/torch_ext/functions.py +0 -0
  57. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/torch_ext/init.py +0 -0
  58. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/torch_ext/losses.py +0 -0
  59. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/torch_ext/modules.py +0 -0
  60. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/braindecode/util.py +0 -0
  61. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/docs/Makefile +0 -0
  62. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/docs/conf.py +0 -0
  63. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/docs/source/braindecode.datasets.rst +0 -0
  64. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/docs/source/braindecode.datautil.rst +0 -0
  65. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/docs/source/braindecode.experiments.rst +0 -0
  66. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/docs/source/braindecode.mne_ext.rst +0 -0
  67. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/docs/source/braindecode.models.rst +0 -0
  68. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/docs/source/braindecode.rst +0 -0
  69. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/docs/source/braindecode.torch_ext.rst +0 -0
  70. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/docs/source/braindecode.visualization.rst +0 -0
  71. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/docs/source/modules.rst +0 -0
  72. {Braindecode-0.1.6.4 → Braindecode-0.1.7}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.1
2
2
  Name: Braindecode
3
- Version: 0.1.6.4
3
+ Version: 0.1.7
4
4
  Summary: A deep learning toolbox to decode raw time-domain EEG.
5
5
  Home-page: https://github.com/robintibor/braindecode
6
6
  Author: Robin Tibor Schirrmeister
@@ -52,6 +52,28 @@ Description: Note: The old braindecode repository has been moved to
52
52
 
53
53
  Documentation is online under https://robintibor.github.io/braindecode/
54
54
 
55
+
56
+ Citing
57
+ ======
58
+ If you use this code in a scientific publication, please cite us as:
59
+
60
+ .. code-block:: bibtex
61
+
62
+ @article {HBM:HBM23730,
63
+ author = {Schirrmeister, Robin Tibor and Springenberg, Jost Tobias and Fiederer,
64
+ Lukas Dominique Josef and Glasstetter, Martin and Eggensperger, Katharina and Tangermann, Michael and
65
+ Hutter, Frank and Burgard, Wolfram and Ball, Tonio},
66
+ title = {Deep learning with convolutional neural networks for EEG decoding and visualization},
67
+ journal = {Human Brain Mapping},
68
+ issn = {1097-0193},
69
+ url = {http://dx.doi.org/10.1002/hbm.23730},
70
+ doi = {10.1002/hbm.23730},
71
+ month = {aug},
72
+ year = {2017},
73
+ keywords = {electroencephalography, EEG analysis, machine learning, end-to-end learning, brain–machine interface,
74
+ brain–computer interface, model interpretability, brain mapping},
75
+ }
76
+
55
77
  Keywords: eeg deep-learning brain-state-decoding
56
78
  Platform: UNKNOWN
57
79
  Classifier: Development Status :: 3 - Alpha
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.1
2
2
  Name: Braindecode
3
- Version: 0.1.6.4
3
+ Version: 0.1.7
4
4
  Summary: A deep learning toolbox to decode raw time-domain EEG.
5
5
  Home-page: https://github.com/robintibor/braindecode
6
6
  Author: Robin Tibor Schirrmeister
@@ -52,6 +52,28 @@ Description: Note: The old braindecode repository has been moved to
52
52
 
53
53
  Documentation is online under https://robintibor.github.io/braindecode/
54
54
 
55
+
56
+ Citing
57
+ ======
58
+ If you use this code in a scientific publication, please cite us as:
59
+
60
+ .. code-block:: bibtex
61
+
62
+ @article {HBM:HBM23730,
63
+ author = {Schirrmeister, Robin Tibor and Springenberg, Jost Tobias and Fiederer,
64
+ Lukas Dominique Josef and Glasstetter, Martin and Eggensperger, Katharina and Tangermann, Michael and
65
+ Hutter, Frank and Burgard, Wolfram and Ball, Tonio},
66
+ title = {Deep learning with convolutional neural networks for EEG decoding and visualization},
67
+ journal = {Human Brain Mapping},
68
+ issn = {1097-0193},
69
+ url = {http://dx.doi.org/10.1002/hbm.23730},
70
+ doi = {10.1002/hbm.23730},
71
+ month = {aug},
72
+ year = {2017},
73
+ keywords = {electroencephalography, EEG analysis, machine learning, end-to-end learning, brain–machine interface,
74
+ brain–computer interface, model interpretability, brain mapping},
75
+ }
76
+
55
77
  Keywords: eeg deep-learning brain-state-decoding
56
78
  Platform: UNKNOWN
57
79
  Classifier: Development Status :: 3 - Alpha
@@ -43,3 +43,25 @@ Documentation
43
43
  =============
44
44
 
45
45
  Documentation is online under https://robintibor.github.io/braindecode/
46
+
47
+
48
+ Citing
49
+ ======
50
+ If you use this code in a scientific publication, please cite us as:
51
+
52
+ .. code-block:: bibtex
53
+
54
+ @article {HBM:HBM23730,
55
+ author = {Schirrmeister, Robin Tibor and Springenberg, Jost Tobias and Fiederer,
56
+ Lukas Dominique Josef and Glasstetter, Martin and Eggensperger, Katharina and Tangermann, Michael and
57
+ Hutter, Frank and Burgard, Wolfram and Ball, Tonio},
58
+ title = {Deep learning with convolutional neural networks for EEG decoding and visualization},
59
+ journal = {Human Brain Mapping},
60
+ issn = {1097-0193},
61
+ url = {http://dx.doi.org/10.1002/hbm.23730},
62
+ doi = {10.1002/hbm.23730},
63
+ month = {aug},
64
+ year = {2017},
65
+ keywords = {electroencephalography, EEG analysis, machine learning, end-to-end learning, brain–machine interface,
66
+ brain–computer interface, model interpretability, brain mapping},
67
+ }
@@ -3,6 +3,7 @@ import logging
3
3
  import pandas as pd
4
4
  import numpy as np
5
5
  import scipy
6
+ import scipy.signal
6
7
 
7
8
  log = logging.getLogger(__name__)
8
9
 
@@ -1,6 +1,7 @@
1
1
  import logging
2
2
  from collections import OrderedDict
3
3
  from copy import deepcopy
4
+ import time
4
5
 
5
6
  import pandas as pd
6
7
  import torch as th
@@ -131,6 +132,8 @@ class Experiment(object):
131
132
  augmentation
132
133
  cuda: bool, optional
133
134
  Whether to use cuda.
135
+ pin_memory: bool, optional
136
+ Whether to pin memory of inputs and targets of batch.
134
137
 
135
138
  Attributes
136
139
  ----------
@@ -142,7 +145,7 @@ class Experiment(object):
142
145
  monitors, stop_criterion, remember_best_column,
143
146
  run_after_early_stop,
144
147
  model_loss_function=None,
145
- batch_modifier=None, cuda=True):
148
+ batch_modifier=None, cuda=True, pin_memory=False):
146
149
  self.model = model
147
150
  self.datasets = OrderedDict(
148
151
  (('train', train_set), ('valid', valid_set), ('test', test_set)))
@@ -160,6 +163,7 @@ class Experiment(object):
160
163
  self.epochs_df = pd.DataFrame()
161
164
  self.before_stop_df = None
162
165
  self.rememberer = None
166
+ self.pin_memory = pin_memory
163
167
 
164
168
  def run(self):
165
169
  """
@@ -250,7 +254,7 @@ class Experiment(object):
250
254
  """
251
255
  batch_generator = self.iterator.get_batches(datasets['train'],
252
256
  shuffle=True)
253
- # TODO, add timing again?
257
+ start_train_epoch_time = time.time()
254
258
  for inputs, targets in batch_generator:
255
259
  if self.batch_modifier is not None:
256
260
  inputs, targets = self.batch_modifier.process(inputs,
@@ -258,6 +262,9 @@ class Experiment(object):
258
262
  # could happen that batch modifier has removed all inputs...
259
263
  if len(inputs) > 0:
260
264
  self.train_batch(inputs, targets)
265
+ end_train_epoch_time = time.time()
266
+ log.info("Time only for training updates: {:.2f}s".format(
267
+ end_train_epoch_time - start_train_epoch_time))
261
268
 
262
269
  self.monitor_epoch(datasets)
263
270
  self.print_epoch()
@@ -275,8 +282,8 @@ class Experiment(object):
275
282
  targets: `torch.autograd.Variable`
276
283
  """
277
284
  self.model.train()
278
- input_vars = np_to_var(inputs)
279
- target_vars = np_to_var(targets)
285
+ input_vars = np_to_var(inputs, pin_memory=self.pin_memory)
286
+ target_vars = np_to_var(targets, pin_memory=self.pin_memory)
280
287
  if self.cuda:
281
288
  input_vars = input_vars.cuda()
282
289
  target_vars = target_vars.cuda()
@@ -306,8 +313,8 @@ class Experiment(object):
306
313
 
307
314
  """
308
315
  self.model.eval()
309
- input_vars = np_to_var(inputs)
310
- target_vars = np_to_var(targets)
316
+ input_vars = np_to_var(inputs, pin_memory=self.pin_memory)
317
+ target_vars = np_to_var(targets, pin_memory=self.pin_memory)
311
318
  if self.cuda:
312
319
  input_vars = input_vars.cuda()
313
320
  target_vars = target_vars.cuda()
@@ -29,11 +29,11 @@ class Deep4Net(object):
29
29
  filter_time_length=10,
30
30
  pool_time_length=3,
31
31
  pool_time_stride=3,
32
- num_filters_2=50,
32
+ n_filters_2=50,
33
33
  filter_length_2=10,
34
- num_filters_3=100,
34
+ n_filters_3=100,
35
35
  filter_length_3=10,
36
- num_filters_4=200,
36
+ n_filters_4=200,
37
37
  filter_length_4=10,
38
38
  first_nonlin=elu,
39
39
  first_pool_mode='max',
@@ -89,18 +89,18 @@ class Deep4Net(object):
89
89
  stride=(self.pool_time_stride, 1)))
90
90
  model.add_module('pool_nonlin', Expression(self.first_pool_nonlin))
91
91
 
92
- def add_conv_pool_block(model, num_filters_before,
93
- num_filters, filter_length, block_nr):
92
+ def add_conv_pool_block(model, n_filters_before,
93
+ n_filters, filter_length, block_nr):
94
94
  suffix = '_{:d}'.format(block_nr)
95
95
  model.add_module('drop' + suffix,
96
96
  nn.Dropout(p=self.drop_prob))
97
97
  model.add_module('conv' + suffix.format(block_nr),
98
- nn.Conv2d(num_filters_before, num_filters,
98
+ nn.Conv2d(n_filters_before, n_filters,
99
99
  (filter_length, 1),
100
100
  stride=1, bias=not self.batch_norm))
101
101
  if self.batch_norm:
102
102
  model.add_module('bnorm' + suffix,
103
- nn.BatchNorm2d(num_filters,
103
+ nn.BatchNorm2d(n_filters,
104
104
  momentum=self.batch_norm_alpha,
105
105
  affine=True,
106
106
  eps=1e-5))
@@ -114,11 +114,11 @@ class Deep4Net(object):
114
114
  model.add_module('pool_nonlin' + suffix,
115
115
  Expression(self.later_pool_nonlin))
116
116
 
117
- add_conv_pool_block(model, n_filters_conv, self.num_filters_2,
117
+ add_conv_pool_block(model, n_filters_conv, self.n_filters_2,
118
118
  self.filter_length_2, 2)
119
- add_conv_pool_block(model, self.num_filters_2, self.num_filters_3,
119
+ add_conv_pool_block(model, self.n_filters_2, self.n_filters_3,
120
120
  self.filter_length_3, 3)
121
- add_conv_pool_block(model, self.num_filters_3, self.num_filters_4,
121
+ add_conv_pool_block(model, self.n_filters_3, self.n_filters_4,
122
122
  self.filter_length_4, 4)
123
123
 
124
124
 
@@ -129,7 +129,7 @@ class Deep4Net(object):
129
129
  n_out_time = out.cpu().data.numpy().shape[2]
130
130
  self.final_conv_length = n_out_time
131
131
  model.add_module('conv_classifier',
132
- nn.Conv2d(self.num_filters_4, self.n_classes,
132
+ nn.Conv2d(self.n_filters_4, self.n_classes,
133
133
  (self.final_conv_length, 1), bias=True))
134
134
  model.add_module('softmax', nn.LogSoftmax())
135
135
  # remove empty dim at end and potentially remove empty time dim
@@ -56,13 +56,14 @@ class EEGNet(object):
56
56
  model.add_module('drop_1', nn.Dropout(p=self.drop_prob))
57
57
 
58
58
  n_filters_2 = 4
59
- # not clear to me how they did the padding
60
- # keras padds unequal padding more in front:
59
+ # keras padds unequal padding more in front, so padding
60
+ # too large should be ok.
61
+ # Not padding in time so that croped training makes sense
61
62
  # https://stackoverflow.com/questions/43994604/padding-with-even-kernel-size-in-a-convolutional-layer-in-keras-theano
62
63
 
63
64
  model.add_module('conv_2', nn.Conv2d(
64
65
  1, n_filters_2, self.second_kernel_size, stride=1,
65
- padding=(self.second_kernel_size[0] // 2, self.second_kernel_size[1] // 2),
66
+ padding=(self.second_kernel_size[0] // 2, 0),
66
67
  bias=True))
67
68
  model.add_module('bnorm_2',nn.BatchNorm2d(
68
69
  n_filters_2, momentum=0.01, affine=True, eps=1e-3),)
@@ -74,7 +75,7 @@ class EEGNet(object):
74
75
  n_filters_3 = 4
75
76
  model.add_module('conv_3', nn.Conv2d(
76
77
  n_filters_2, n_filters_3, self.third_kernel_size, stride=1,
77
- padding=(self.third_kernel_size[0] // 2, self.third_kernel_size[1] // 2),
78
+ padding=(self.third_kernel_size[0] // 2, 0),
78
79
  bias=True))
79
80
  model.add_module('bnorm_3',nn.BatchNorm2d(
80
81
  n_filters_3, momentum=0.01, affine=True, eps=1e-3),)
@@ -13,6 +13,12 @@ def to_dense_prediction_model(model, axis=(2, 3)):
13
13
  axis: int or (int,int)
14
14
  Axis to transform (in terms of intermediate output axes)
15
15
  can either be 2, 3, or (2,3).
16
+
17
+ Notes
18
+ -----
19
+ Does not yet work correctly for average pooling.
20
+ Prior to version 0.1.7, there had been a bug that could move strides
21
+ backwards one layer.
16
22
 
17
23
  """
18
24
  if not hasattr(axis, '__len__'):
@@ -21,14 +27,6 @@ def to_dense_prediction_model(model, axis=(2, 3)):
21
27
  axis = np.array(axis) - 2
22
28
  stride_so_far = np.array([1, 1])
23
29
  for module in model.modules():
24
- if hasattr(module, 'stride'):
25
- if not hasattr(module.stride, '__len__'):
26
- module.stride = (module.stride, module.stride)
27
- stride_so_far *= np.array(module.stride)
28
- new_stride = list(module.stride)
29
- for ax in axis:
30
- new_stride[ax] = 1
31
- module.stride = tuple(new_stride)
32
30
  if hasattr(module, 'dilation'):
33
31
  assert module.dilation == 1 or (module.dilation == (1, 1)), (
34
32
  "Dilation should equal 1 before conversion, maybe the model is "
@@ -37,3 +35,11 @@ def to_dense_prediction_model(model, axis=(2, 3)):
37
35
  for ax in axis:
38
36
  new_dilation[ax] = int(stride_so_far[ax])
39
37
  module.dilation = tuple(new_dilation)
38
+ if hasattr(module, 'stride'):
39
+ if not hasattr(module.stride, '__len__'):
40
+ module.stride = (module.stride, module.stride)
41
+ stride_so_far *= np.array(module.stride)
42
+ new_stride = list(module.stride)
43
+ for ax in axis:
44
+ new_stride[ax] = 1
45
+ module.stride = tuple(new_stride)
@@ -4,18 +4,33 @@ import numpy as np
4
4
  import random
5
5
 
6
6
 
7
- def np_to_var(X, requires_grad=False, **var_kwargs):
7
+ def np_to_var(X, requires_grad=False, dtype=None, pin_memory=False, **var_kwargs):
8
8
  """
9
9
  Convenience function to transform numpy array to `torch.autograd.Variable`.
10
10
 
11
11
  Converts `X` to ndarray using asarray if necessary.
12
12
 
13
+ Parameters
14
+ ----------
15
+ X: ndarray or list
16
+ Input arrays
17
+ requires_grad: bool
18
+ passed on to Variable constructor
19
+ dtype: numpy dtype, optional
20
+ var_kwargs:
21
+ passed on to Variable constructor
22
+
13
23
  Returns
14
24
  -------
15
25
  var: `torch.autograd.Variable`
16
26
  """
17
27
  X = np.asarray(X)
18
- return Variable(th.from_numpy(X), requires_grad=requires_grad, **var_kwargs)
28
+ if dtype is not None:
29
+ X = X.astype(dtype)
30
+ X_tensor = th.from_numpy(X)
31
+ if pin_memory:
32
+ X_tensor = X_tensor.pin_memory()
33
+ return Variable(X_tensor, requires_grad=requires_grad, **var_kwargs)
19
34
 
20
35
 
21
36
  def var_to_np(var):
@@ -0,0 +1,3 @@
1
+ """
2
+ Functions for visualisations, especially of the ConvNets.
3
+ """
@@ -10,7 +10,22 @@ log = logging.getLogger(__name__)
10
10
 
11
11
 
12
12
  def gaussian_perturbation(amps, rng):
13
- perturbation = rng.randn(*amps.shape)
13
+ """
14
+ Create gaussian noise tensor with same shape as amplitudes.
15
+
16
+ Parameters
17
+ ----------
18
+ amps: ndarray
19
+ Amplitudes.
20
+ rng: RandomState
21
+ Random generator.
22
+
23
+ Returns
24
+ -------
25
+ perturbation: ndarray
26
+ Perturbations to add to the amplitudes.
27
+ """
28
+ perturbation = rng.randn(*amps.shape).astype(np.float32)
14
29
  return perturbation
15
30
 
16
31
 
@@ -46,6 +61,15 @@ def compute_amplitude_prediction_correlations(pred_fn, examples, n_iterations,
46
61
  amplitude_pred_corrs: ndarray
47
62
  Correlations between amplitude perturbations and prediction changes
48
63
  for all sensors and frequency bins.
64
+
65
+ References
66
+ ----------
67
+
68
+ .. [EEGDeepLearning] Schirrmeister, R. T., Springenberg, J. T., Fiederer, L. D. J.,
69
+ Glasstetter, M., Eggensperger, K., Tangermann, M., ... & Ball, T. (2017).
70
+ Deep learning with convolutional neural networks for EEG decoding and
71
+ visualization.
72
+ arXiv preprint arXiv:1703.05051.
49
73
  """
50
74
  inds_per_batch = get_balanced_batches(
51
75
  n_trials=len(examples), rng=None, shuffle=False, batch_size=batch_size)
@@ -68,8 +92,8 @@ def compute_amplitude_prediction_correlations(pred_fn, examples, n_iterations,
68
92
  # zero
69
93
  perturbation = np.maximum(-amps, perturbation)
70
94
  new_amps = amps + perturbation
71
- log.info("Compute new complex inputs...")
72
- new_complex = amplitude_phase_to_complex(new_amps, phases)
95
+ log.info("Compute new complex inputs...")
96
+ new_complex = _amplitude_phase_to_complex(new_amps, phases)
73
97
  log.info("Compute new real inputs...")
74
98
  new_in = np.fft.irfft(new_complex, axis=2).astype(np.float32)
75
99
  log.info("Compute new predictions...")
@@ -88,5 +112,5 @@ def compute_amplitude_prediction_correlations(pred_fn, examples, n_iterations,
88
112
  return amp_pred_corrs
89
113
 
90
114
 
91
- def amplitude_phase_to_complex(amplitude, phase):
115
+ def _amplitude_phase_to_complex(amplitude, phase):
92
116
  return amplitude * np.cos(phase) + amplitude * np.sin(phase) * 1j
@@ -18,7 +18,8 @@ def ax_scalp(v, channels,
18
18
  scalp_line_width=1,
19
19
  scalp_line_style='solid',
20
20
  chan_pos_list=CHANNEL_10_20_APPROX,
21
- interpolation='bilinear'):
21
+ interpolation='bilinear',
22
+ fontsize=8):
22
23
  """Draw a scalp plot.
23
24
 
24
25
  Draws a scalp plot on an existing axes. The method takes an array of
@@ -138,7 +139,7 @@ def ax_scalp(v, channels,
138
139
  if annotate:
139
140
  for i in zip(channels, list(zip(x, y))):
140
141
  ax.annotate(" " + i[0], i[1], horizontalalignment="center",
141
- verticalalignment='center')
142
+ verticalalignment='center', fontsize=fontsize)
142
143
  ax.set_aspect(1)
143
144
  return image
144
145
 
@@ -63,6 +63,30 @@ API
63
63
  braindecode.mne_ext
64
64
  braindecode.models
65
65
  braindecode.torch_ext
66
+ braindecode.visualization
67
+
68
+
69
+ Citing
70
+ ======
71
+ If you use this code in a scientific publication, please cite us as:
72
+
73
+ .. code-block:: bibtex
74
+
75
+ @article {HBM:HBM23730,
76
+ author = {Schirrmeister, Robin Tibor and Springenberg, Jost Tobias and Fiederer,
77
+ Lukas Dominique Josef and Glasstetter, Martin and Eggensperger, Katharina and Tangermann, Michael and
78
+ Hutter, Frank and Burgard, Wolfram and Ball, Tonio},
79
+ title = {Deep learning with convolutional neural networks for EEG decoding and visualization},
80
+ journal = {Human Brain Mapping},
81
+ issn = {1097-0193},
82
+ url = {http://dx.doi.org/10.1002/hbm.23730},
83
+ doi = {10.1002/hbm.23730},
84
+ month = {aug},
85
+ year = {2017},
86
+ keywords = {electroencephalography, EEG analysis, machine learning, end-to-end learning, brain–machine interface,
87
+ brain–computer interface, model interpretability, brain mapping},
88
+ }
89
+
66
90
 
67
91
  Indices and tables
68
92
  ==================