braindecode 0.4.3__tar.gz → 0.4.5__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.
- {Braindecode-0.4.3 → Braindecode-0.4.5}/Braindecode.egg-info/PKG-INFO +1 -1
- {Braindecode-0.4.3 → Braindecode-0.4.5}/Braindecode.egg-info/SOURCES.txt +0 -1
- {Braindecode-0.4.3 → Braindecode-0.4.5}/PKG-INFO +1 -1
- Braindecode-0.4.5/braindecode/datautil/splitters.py +190 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/experiments/experiment.py +2 -7
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/models/base.py +16 -4
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/models/deep4.py +3 -3
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/models/eegnet.py +2 -2
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/models/hybrid.py +31 -14
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/models/shallow_fbcsp.py +3 -3
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/torch_ext/constraints.py +2 -2
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/torch_ext/init.py +1 -1
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/torch_ext/optimizers.py +1 -1
- Braindecode-0.4.5/braindecode/version.py +1 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/visualization/perturbation.py +12 -6
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/visualization/plot.py +2 -4
- {Braindecode-0.4.3 → Braindecode-0.4.5}/docs/notebooks/BBCI_Data.ipynb +1 -1
- {Braindecode-0.4.3 → Braindecode-0.4.5}/docs/notebooks/BBCI_Data_Start_Stop.ipynb +1 -1
- {Braindecode-0.4.3 → Braindecode-0.4.5}/docs/notebooks/BBCI_Data_Trialwise.ipynb +1 -1
- {Braindecode-0.4.3 → Braindecode-0.4.5}/docs/notebooks/Cropped_Manual_Training_Loop.ipynb +81 -73
- {Braindecode-0.4.3 → Braindecode-0.4.5}/docs/notebooks/Trialwise_Manual_Training_Loop.ipynb +6 -2
- {Braindecode-0.4.3 → Braindecode-0.4.5}/docs/notebooks/visualization/Perturbation.ipynb +260 -247
- Braindecode-0.4.3/braindecode/datautil/splitters.py +0 -106
- Braindecode-0.4.3/braindecode/models/deep4new.py +0 -228
- Braindecode-0.4.3/braindecode/version.py +0 -1
- {Braindecode-0.4.3 → Braindecode-0.4.5}/Braindecode.egg-info/dependency_links.txt +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/Braindecode.egg-info/not-zip-safe +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/Braindecode.egg-info/requires.txt +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/Braindecode.egg-info/top_level.txt +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/LICENSE.txt +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/MANIFEST.in +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/README.rst +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/__init__.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/datasets/__init__.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/datasets/bbci.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/datasets/bcic_iv_2a.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/datasets/multiple.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/datasets/sensor_positions.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/datautil/__init__.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/datautil/iterators.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/datautil/signal_target.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/datautil/signalproc.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/datautil/trial_segment.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/datautil/util.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/experiments/__init__.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/experiments/loggers.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/experiments/monitors.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/experiments/stopcriteria.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/mne_ext/__init__.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/mne_ext/signalproc.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/models/__init__.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/models/util.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/torch_ext/__init__.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/torch_ext/functions.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/torch_ext/losses.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/torch_ext/modules.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/torch_ext/schedulers.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/torch_ext/util.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/util.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/visualization/__init__.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/visualization/input_windows.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/braindecode/visualization/sinfit.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/docs/Makefile +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/docs/conf.py +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/docs/index.rst +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/docs/notebooks/Cropped_Decoding.ipynb +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/docs/notebooks/Cropped_Trialwise_Explanation_Figures.ipynb +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/docs/notebooks/Trialwise_Decoding.ipynb +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/docs/source/braindecode.datasets.rst +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/docs/source/braindecode.datautil.rst +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/docs/source/braindecode.experiments.rst +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/docs/source/braindecode.mne_ext.rst +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/docs/source/braindecode.models.rst +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/docs/source/braindecode.rst +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/docs/source/braindecode.torch_ext.rst +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/docs/source/braindecode.visualization.rst +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/docs/source/modules.rst +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/setup.cfg +0 -0
- {Braindecode-0.4.3 → Braindecode-0.4.5}/setup.py +0 -0
|
@@ -33,7 +33,6 @@ braindecode/mne_ext/signalproc.py
|
|
|
33
33
|
braindecode/models/__init__.py
|
|
34
34
|
braindecode/models/base.py
|
|
35
35
|
braindecode/models/deep4.py
|
|
36
|
-
braindecode/models/deep4new.py
|
|
37
36
|
braindecode/models/eegnet.py
|
|
38
37
|
braindecode/models/hybrid.py
|
|
39
38
|
braindecode/models/shallow_fbcsp.py
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from braindecode.datautil.iterators import get_balanced_batches
|
|
4
|
+
from braindecode.datautil.signal_target import apply_to_X_y, SignalAndTarget
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def concatenate_sets(sets):
|
|
8
|
+
"""
|
|
9
|
+
Concatenate all sets together.
|
|
10
|
+
|
|
11
|
+
Parameters
|
|
12
|
+
----------
|
|
13
|
+
sets: list of :class:`.SignalAndTarget`
|
|
14
|
+
|
|
15
|
+
Returns
|
|
16
|
+
-------
|
|
17
|
+
concatenated_set: :class:`.SignalAndTarget`
|
|
18
|
+
"""
|
|
19
|
+
concatenated_set = sets[0]
|
|
20
|
+
for s in sets[1:]:
|
|
21
|
+
concatenated_set = concatenate_two_sets(concatenated_set, s)
|
|
22
|
+
return concatenated_set
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def concatenate_two_sets(set_a, set_b):
|
|
26
|
+
"""
|
|
27
|
+
Concatenate two sets together.
|
|
28
|
+
|
|
29
|
+
Parameters
|
|
30
|
+
----------
|
|
31
|
+
set_a, set_b: :class:`.SignalAndTarget`
|
|
32
|
+
|
|
33
|
+
Returns
|
|
34
|
+
-------
|
|
35
|
+
concatenated_set: :class:`.SignalAndTarget`
|
|
36
|
+
"""
|
|
37
|
+
new_X = concatenate_np_array_or_add_lists(set_a.X, set_b.X)
|
|
38
|
+
new_y = concatenate_np_array_or_add_lists(set_a.y, set_b.y)
|
|
39
|
+
return SignalAndTarget(new_X, new_y)
|
|
40
|
+
|
|
41
|
+
def concatenate_np_array_or_add_lists(a, b):
|
|
42
|
+
if hasattr(a, 'ndim') and hasattr(b, 'ndim'):
|
|
43
|
+
new = np.concatenate((a, b), axis=0)
|
|
44
|
+
else:
|
|
45
|
+
if hasattr(a, 'ndim'):
|
|
46
|
+
a = a.tolist()
|
|
47
|
+
if hasattr(b, 'ndim'):
|
|
48
|
+
b = b.tolist()
|
|
49
|
+
new = a + b
|
|
50
|
+
return new
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def split_into_two_sets(dataset, first_set_fraction=None, n_first_set=None):
|
|
55
|
+
"""
|
|
56
|
+
Split set into two sets either by fraction of first set or by number
|
|
57
|
+
of trials in first set.
|
|
58
|
+
|
|
59
|
+
Parameters
|
|
60
|
+
----------
|
|
61
|
+
dataset: :class:`.SignalAndTarget`
|
|
62
|
+
first_set_fraction: float, optional
|
|
63
|
+
Fraction of trials in first set.
|
|
64
|
+
n_first_set: int, optional
|
|
65
|
+
Number of trials in first set
|
|
66
|
+
|
|
67
|
+
Returns
|
|
68
|
+
-------
|
|
69
|
+
first_set, second_set: :class:`.SignalAndTarget`
|
|
70
|
+
The two splitted sets.
|
|
71
|
+
"""
|
|
72
|
+
assert (first_set_fraction is None) != (n_first_set is None), (
|
|
73
|
+
"Pass either first_set_fraction or n_first_set")
|
|
74
|
+
if n_first_set is None:
|
|
75
|
+
n_first_set = int(round(len(dataset.X) * first_set_fraction))
|
|
76
|
+
assert n_first_set < len(dataset.X)
|
|
77
|
+
first_set = apply_to_X_y(lambda a: a[:n_first_set], dataset)
|
|
78
|
+
second_set = apply_to_X_y(lambda a: a[n_first_set:], dataset)
|
|
79
|
+
return first_set, second_set
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def select_examples(dataset, indices):
|
|
83
|
+
"""
|
|
84
|
+
Select examples from dataset.
|
|
85
|
+
|
|
86
|
+
Parameters
|
|
87
|
+
----------
|
|
88
|
+
dataset: :class:`.SignalAndTarget`
|
|
89
|
+
indices: list of int, 1d-array of int
|
|
90
|
+
Indices to select
|
|
91
|
+
|
|
92
|
+
Returns
|
|
93
|
+
-------
|
|
94
|
+
reduced_set: :class:`.SignalAndTarget`
|
|
95
|
+
Dataset with only examples selected.
|
|
96
|
+
"""
|
|
97
|
+
# probably not necessary
|
|
98
|
+
indices = np.array(indices)
|
|
99
|
+
if hasattr(dataset.X, 'ndim'):
|
|
100
|
+
# numpy array
|
|
101
|
+
new_X = np.array(dataset.X)[indices]
|
|
102
|
+
else:
|
|
103
|
+
# list
|
|
104
|
+
new_X = [dataset.X[i] for i in indices]
|
|
105
|
+
new_y = np.asarray(dataset.y)[indices]
|
|
106
|
+
return SignalAndTarget(new_X, new_y)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def split_into_train_valid_test(dataset, n_folds, i_test_fold, rng=None):
|
|
110
|
+
"""
|
|
111
|
+
Split datasets into folds, select one valid fold, one test fold and merge rest as train fold.
|
|
112
|
+
|
|
113
|
+
Parameters
|
|
114
|
+
----------
|
|
115
|
+
dataset: :class:`.SignalAndTarget`
|
|
116
|
+
n_folds: int
|
|
117
|
+
Number of folds to split dataset into.
|
|
118
|
+
i_test_fold: int
|
|
119
|
+
Index of the test fold (0-based). Validation fold will be immediately preceding fold.
|
|
120
|
+
rng: `numpy.random.RandomState`, optional
|
|
121
|
+
Random Generator for shuffling, None means no shuffling
|
|
122
|
+
|
|
123
|
+
Returns
|
|
124
|
+
-------
|
|
125
|
+
reduced_set: :class:`.SignalAndTarget`
|
|
126
|
+
Dataset with only examples selected.
|
|
127
|
+
"""
|
|
128
|
+
n_trials = len(dataset.X)
|
|
129
|
+
if n_trials < n_folds:
|
|
130
|
+
raise ValueError("Less Trials: {:d} than folds: {:d}".format(
|
|
131
|
+
n_trials, n_folds
|
|
132
|
+
))
|
|
133
|
+
shuffle = rng is not None
|
|
134
|
+
folds = get_balanced_batches(
|
|
135
|
+
n_trials, rng, shuffle, n_batches=n_folds)
|
|
136
|
+
test_inds = folds[i_test_fold]
|
|
137
|
+
valid_inds = folds[i_test_fold - 1]
|
|
138
|
+
all_inds = list(range(n_trials))
|
|
139
|
+
train_inds = np.setdiff1d(all_inds, np.union1d(test_inds, valid_inds))
|
|
140
|
+
assert np.intersect1d(train_inds, valid_inds).size == 0
|
|
141
|
+
assert np.intersect1d(train_inds, test_inds).size == 0
|
|
142
|
+
assert np.intersect1d(valid_inds, test_inds).size == 0
|
|
143
|
+
assert np.array_equal(np.sort(
|
|
144
|
+
np.union1d(train_inds, np.union1d(valid_inds, test_inds))),
|
|
145
|
+
all_inds)
|
|
146
|
+
|
|
147
|
+
train_set = select_examples(dataset, train_inds)
|
|
148
|
+
valid_set = select_examples(dataset, valid_inds)
|
|
149
|
+
test_set = select_examples(dataset, test_inds)
|
|
150
|
+
|
|
151
|
+
return train_set, valid_set, test_set
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def split_into_train_test(dataset, n_folds, i_test_fold, rng=None):
|
|
155
|
+
"""
|
|
156
|
+
Split datasets into folds, select one test fold and merge rest as train fold.
|
|
157
|
+
|
|
158
|
+
Parameters
|
|
159
|
+
----------
|
|
160
|
+
dataset: :class:`.SignalAndTarget`
|
|
161
|
+
n_folds: int
|
|
162
|
+
Number of folds to split dataset into.
|
|
163
|
+
i_test_fold: int
|
|
164
|
+
Index of the test fold (0-based)
|
|
165
|
+
rng: `numpy.random.RandomState`, optional
|
|
166
|
+
Random Generator for shuffling, None means no shuffling
|
|
167
|
+
|
|
168
|
+
Returns
|
|
169
|
+
-------
|
|
170
|
+
reduced_set: :class:`.SignalAndTarget`
|
|
171
|
+
Dataset with only examples selected.
|
|
172
|
+
"""
|
|
173
|
+
n_trials = len(dataset.X)
|
|
174
|
+
if n_trials < n_folds:
|
|
175
|
+
raise ValueError("Less Trials: {:d} than folds: {:d}".format(
|
|
176
|
+
n_trials, n_folds
|
|
177
|
+
))
|
|
178
|
+
shuffle = rng is not None
|
|
179
|
+
folds = get_balanced_batches(n_trials, rng, shuffle,
|
|
180
|
+
n_batches=n_folds)
|
|
181
|
+
test_inds = folds[i_test_fold]
|
|
182
|
+
all_inds = list(range(len(n_trials)))
|
|
183
|
+
train_inds = np.setdiff1d(all_inds, test_inds)
|
|
184
|
+
assert np.intersect1d(train_inds, test_inds).size == 0
|
|
185
|
+
assert np.array_equal(np.sort(np.union1d(train_inds, test_inds)),
|
|
186
|
+
all_inds)
|
|
187
|
+
|
|
188
|
+
train_set = select_examples(dataset, train_inds)
|
|
189
|
+
test_set = select_examples(dataset, test_inds)
|
|
190
|
+
return train_set, test_set
|
|
@@ -146,8 +146,6 @@ class Experiment(object):
|
|
|
146
146
|
start of training.
|
|
147
147
|
loggers: list of :class:`.Logger`
|
|
148
148
|
How to show computed metrics.
|
|
149
|
-
seed: int
|
|
150
|
-
Random seed for python random module numpy.random and torch.
|
|
151
149
|
|
|
152
150
|
Attributes
|
|
153
151
|
----------
|
|
@@ -163,8 +161,7 @@ class Experiment(object):
|
|
|
163
161
|
do_early_stop=True,
|
|
164
162
|
reset_after_second_run=False,
|
|
165
163
|
log_0_epoch=True,
|
|
166
|
-
loggers=('print',)
|
|
167
|
-
seed=2382938):
|
|
164
|
+
loggers=('print',)):
|
|
168
165
|
if run_after_early_stop or reset_after_second_run:
|
|
169
166
|
assert do_early_stop == True, ("Can only run after early stop or "
|
|
170
167
|
"reset after second run if doing an early stop")
|
|
@@ -199,7 +196,6 @@ class Experiment(object):
|
|
|
199
196
|
self.do_early_stop = do_early_stop
|
|
200
197
|
self.reset_after_second_run = reset_after_second_run
|
|
201
198
|
self.log_0_epoch = log_0_epoch
|
|
202
|
-
self.seed = seed
|
|
203
199
|
self.loggers = loggers
|
|
204
200
|
|
|
205
201
|
def run(self):
|
|
@@ -230,7 +226,7 @@ class Experiment(object):
|
|
|
230
226
|
|
|
231
227
|
def setup_training(self):
|
|
232
228
|
"""
|
|
233
|
-
Setup training, i.e.
|
|
229
|
+
Setup training, i.e. transform model to cuda,
|
|
234
230
|
initialize monitoring.
|
|
235
231
|
"""
|
|
236
232
|
# reset remember best extension in case you rerun some experiment
|
|
@@ -239,7 +235,6 @@ class Experiment(object):
|
|
|
239
235
|
if self.loggers == ('print',):
|
|
240
236
|
self.loggers = [Printer()]
|
|
241
237
|
self.epochs_df = pd.DataFrame()
|
|
242
|
-
set_random_seeds(seed=self.seed, cuda=self.cuda)
|
|
243
238
|
if self.cuda:
|
|
244
239
|
assert th.cuda.is_available(), "Cuda not available"
|
|
245
240
|
self.model.cuda()
|
|
@@ -15,6 +15,9 @@ from braindecode.datautil.signal_target import SignalAndTarget
|
|
|
15
15
|
from braindecode.models.util import to_dense_prediction_model
|
|
16
16
|
from braindecode.torch_ext.schedulers import CosineAnnealing, ScheduledOptimizer
|
|
17
17
|
from braindecode.torch_ext.util import np_to_var, var_to_np
|
|
18
|
+
import logging
|
|
19
|
+
|
|
20
|
+
log = logging.getLogger(__name__)
|
|
18
21
|
|
|
19
22
|
|
|
20
23
|
def find_optimizer(optimizer_name):
|
|
@@ -79,7 +82,14 @@ class BaseModel(object):
|
|
|
79
82
|
self.loss = loss
|
|
80
83
|
self._ensure_network_exists()
|
|
81
84
|
if cropped:
|
|
82
|
-
|
|
85
|
+
model_already_dense = np.any([
|
|
86
|
+
hasattr(m, 'dilation') and (m.dilation != 1) and
|
|
87
|
+
(m.dilation) != (1, 1) for m in self.network.modules()
|
|
88
|
+
])
|
|
89
|
+
if not model_already_dense:
|
|
90
|
+
to_dense_prediction_model(self.network)
|
|
91
|
+
else:
|
|
92
|
+
log.info("Seems model was already converted to dense model...")
|
|
83
93
|
if not hasattr(optimizer, 'step'):
|
|
84
94
|
optimizer_class = find_optimizer(optimizer)
|
|
85
95
|
optimizer = optimizer_class(self.network.parameters())
|
|
@@ -141,7 +151,9 @@ class BaseModel(object):
|
|
|
141
151
|
"the network in a single pass.")
|
|
142
152
|
if self.cropped:
|
|
143
153
|
self.network.eval()
|
|
144
|
-
test_input = np_to_var(
|
|
154
|
+
test_input = np_to_var(np.ones(
|
|
155
|
+
(1, train_X.shape[1], input_time_length,) + train_X.shape[3:],
|
|
156
|
+
dtype=np.float32))
|
|
145
157
|
while len(test_input.size()) < 4:
|
|
146
158
|
test_input = test_input.unsqueeze(-1)
|
|
147
159
|
if self.cuda:
|
|
@@ -151,11 +163,11 @@ class BaseModel(object):
|
|
|
151
163
|
self.iterator = CropsFromTrialsIterator(
|
|
152
164
|
batch_size=batch_size, input_time_length=input_time_length,
|
|
153
165
|
n_preds_per_input=n_preds_per_input,
|
|
154
|
-
seed=self.seed_rng.randint(0,
|
|
166
|
+
seed=self.seed_rng.randint(0, np.iinfo(np.int32).max-1))
|
|
155
167
|
else:
|
|
156
168
|
self.iterator = BalancedBatchSizeIterator(
|
|
157
169
|
batch_size=batch_size,
|
|
158
|
-
seed=self.seed_rng.randint(0,
|
|
170
|
+
seed=self.seed_rng.randint(0, np.iinfo(np.int32).max-1))
|
|
159
171
|
if log_0_epoch:
|
|
160
172
|
stop_criterion = MaxEpochs(epochs)
|
|
161
173
|
else:
|
|
@@ -17,10 +17,10 @@ class Deep4Net(BaseModel):
|
|
|
17
17
|
----------
|
|
18
18
|
|
|
19
19
|
.. [1] Schirrmeister, R. T., Springenberg, J. T., Fiederer, L. D. J.,
|
|
20
|
-
Glasstetter, M., Eggensperger, K., Tangermann, M.,
|
|
20
|
+
Glasstetter, M., Eggensperger, K., Tangermann, M., Hutter, F. & Ball, T. (2017).
|
|
21
21
|
Deep learning with convolutional neural networks for EEG decoding and
|
|
22
22
|
visualization.
|
|
23
|
-
|
|
23
|
+
Human Brain Mapping , Aug. 2017. Online: http://dx.doi.org/10.1002/hbm.23730
|
|
24
24
|
"""
|
|
25
25
|
def __init__(self, in_chans,
|
|
26
26
|
n_classes,
|
|
@@ -103,7 +103,7 @@ class Deep4Net(BaseModel):
|
|
|
103
103
|
suffix = '_{:d}'.format(block_nr)
|
|
104
104
|
model.add_module('drop' + suffix,
|
|
105
105
|
nn.Dropout(p=self.drop_prob))
|
|
106
|
-
model.add_module('conv' + suffix
|
|
106
|
+
model.add_module('conv' + suffix,
|
|
107
107
|
nn.Conv2d(n_filters_before, n_filters,
|
|
108
108
|
(filter_length, 1),
|
|
109
109
|
stride=(conv_stride, 1),
|
|
@@ -21,7 +21,7 @@ class Conv2dWithConstraint(nn.Conv2d):
|
|
|
21
21
|
|
|
22
22
|
class EEGNetv4(BaseModel):
|
|
23
23
|
"""
|
|
24
|
-
EEGNet v4 model from [
|
|
24
|
+
EEGNet v4 model from [EEGNet4]_.
|
|
25
25
|
|
|
26
26
|
Notes
|
|
27
27
|
-----
|
|
@@ -31,7 +31,7 @@ class EEGNetv4(BaseModel):
|
|
|
31
31
|
References
|
|
32
32
|
----------
|
|
33
33
|
|
|
34
|
-
.. [
|
|
34
|
+
.. [EEGNet4] Lawhern, V. J., Solon, A. J., Waytowich, N. R., Gordon,
|
|
35
35
|
S. M., Hung, C. P., & Lance, B. J. (2018).
|
|
36
36
|
EEGNet: A Compact Convolutional Network for EEG-based
|
|
37
37
|
Brain-Computer Interfaces.
|
|
@@ -8,31 +8,48 @@ from braindecode.models.shallow_fbcsp import ShallowFBCSPNet
|
|
|
8
8
|
from braindecode.models.util import to_dense_prediction_model
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
class HybridNet(
|
|
11
|
+
class HybridNet(BaseModel):
|
|
12
12
|
"""
|
|
13
|
-
|
|
13
|
+
Wrapper for HybridNetModule
|
|
14
|
+
"""
|
|
15
|
+
def __init__(self, in_chans, n_classes, input_time_length):
|
|
16
|
+
self.in_chans = in_chans
|
|
17
|
+
self.n_classes = n_classes
|
|
18
|
+
self.input_time_length = input_time_length
|
|
19
|
+
|
|
20
|
+
def create_network(self):
|
|
21
|
+
return HybridNetModule(
|
|
22
|
+
in_chans=self.in_chans,
|
|
23
|
+
n_classes=self.n_classes,
|
|
24
|
+
input_time_length=self.input_time_length
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class HybridNetModule(nn.Module):
|
|
29
|
+
"""
|
|
30
|
+
Hybrid ConvNet model from [3]_.
|
|
14
31
|
|
|
15
|
-
|
|
32
|
+
Very hardcoded at the moment.
|
|
16
33
|
|
|
17
|
-
|
|
18
|
-
|
|
34
|
+
References
|
|
35
|
+
----------
|
|
19
36
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
37
|
+
.. [3] Schirrmeister, R. T., Springenberg, J. T., Fiederer, L. D. J.,
|
|
38
|
+
Glasstetter, M., Eggensperger, K., Tangermann, M., Hutter, F. & Ball, T. (2017).
|
|
39
|
+
Deep learning with convolutional neural networks for EEG decoding and
|
|
40
|
+
visualization.
|
|
41
|
+
Human Brain Mapping , Aug. 2017. Online: http://dx.doi.org/10.1002/hbm.23730
|
|
25
42
|
"""
|
|
26
|
-
def __init__(self,
|
|
27
|
-
super(
|
|
28
|
-
deep_model = Deep4Net(
|
|
43
|
+
def __init__(self, in_chans, n_classes, input_time_length):
|
|
44
|
+
super(HybridNetModule, self).__init__()
|
|
45
|
+
deep_model = Deep4Net(in_chans, n_classes, n_filters_time=20,
|
|
29
46
|
n_filters_spat=30,
|
|
30
47
|
n_filters_2=40,
|
|
31
48
|
n_filters_3=50,
|
|
32
49
|
n_filters_4=60,
|
|
33
50
|
input_time_length=input_time_length,
|
|
34
51
|
final_conv_length=2).create_network()
|
|
35
|
-
shallow_model = ShallowFBCSPNet(
|
|
52
|
+
shallow_model = ShallowFBCSPNet(in_chans, n_classes,
|
|
36
53
|
input_time_length=input_time_length,
|
|
37
54
|
n_filters_time=30,
|
|
38
55
|
n_filters_spat=40,
|
|
@@ -15,11 +15,11 @@ class ShallowFBCSPNet(BaseModel):
|
|
|
15
15
|
References
|
|
16
16
|
----------
|
|
17
17
|
|
|
18
|
-
.. [2] Schirrmeister, R. T., Springenberg, J. T., Fiederer, L. D. J.,
|
|
19
|
-
Glasstetter, M., Eggensperger, K., Tangermann, M.,
|
|
18
|
+
.. [2] Schirrmeister, R. T., Springenberg, J. T., Fiederer, L. D. J.,
|
|
19
|
+
Glasstetter, M., Eggensperger, K., Tangermann, M., Hutter, F. & Ball, T. (2017).
|
|
20
20
|
Deep learning with convolutional neural networks for EEG decoding and
|
|
21
21
|
visualization.
|
|
22
|
-
|
|
22
|
+
Human Brain Mapping , Aug. 2017. Online: http://dx.doi.org/10.1002/hbm.23730
|
|
23
23
|
"""
|
|
24
24
|
def __init__(self, in_chans,
|
|
25
25
|
n_classes,
|
|
@@ -10,10 +10,10 @@ class MaxNormDefaultConstraint(object):
|
|
|
10
10
|
----------
|
|
11
11
|
|
|
12
12
|
.. [1] Schirrmeister, R. T., Springenberg, J. T., Fiederer, L. D. J.,
|
|
13
|
-
Glasstetter, M., Eggensperger, K., Tangermann, M.,
|
|
13
|
+
Glasstetter, M., Eggensperger, K., Tangermann, M., Hutter, F. & Ball, T. (2017).
|
|
14
14
|
Deep learning with convolutional neural networks for EEG decoding and
|
|
15
15
|
visualization.
|
|
16
|
-
|
|
16
|
+
Human Brain Mapping , Aug. 2017. Online: http://dx.doi.org/10.1002/hbm.23730
|
|
17
17
|
|
|
18
18
|
"""
|
|
19
19
|
def apply(self, model):
|
|
@@ -17,7 +17,7 @@ def glorot_weight_zero_bias(model):
|
|
|
17
17
|
if not ('BatchNorm' in module.__class__.__name__):
|
|
18
18
|
init.xavier_uniform_(module.weight, gain=1)
|
|
19
19
|
else:
|
|
20
|
-
init.
|
|
20
|
+
init.constant_(module.weight, 1)
|
|
21
21
|
if hasattr(module, 'bias'):
|
|
22
22
|
if module.bias is not None:
|
|
23
23
|
init.constant_(module.bias, 0)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.4.5"
|
|
@@ -8,7 +8,7 @@ from braindecode.util import wrap_reshape_apply_fn, corr
|
|
|
8
8
|
log = logging.getLogger(__name__)
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
def phase_perturbation(amps,phases,rng=
|
|
11
|
+
def phase_perturbation(amps,phases,rng=None):
|
|
12
12
|
"""Takes amps and phases of BxCxF with B input, C channels, F frequencies
|
|
13
13
|
Shifts spectral phases randomly U(-pi,pi) for input and frequencies, but same for all channels
|
|
14
14
|
|
|
@@ -19,7 +19,7 @@ def phase_perturbation(amps,phases,rng=np.random.RandomState()):
|
|
|
19
19
|
phases : numpy array
|
|
20
20
|
Spectral phases
|
|
21
21
|
rng : object
|
|
22
|
-
Random
|
|
22
|
+
Random Generator
|
|
23
23
|
|
|
24
24
|
Returns
|
|
25
25
|
-------
|
|
@@ -30,6 +30,8 @@ def phase_perturbation(amps,phases,rng=np.random.RandomState()):
|
|
|
30
30
|
pert_vals : numpy array
|
|
31
31
|
Absolute phase shifts
|
|
32
32
|
"""
|
|
33
|
+
if rng is None:
|
|
34
|
+
rng = np.random.RandomState()
|
|
33
35
|
noise_shape = list(phases.shape)
|
|
34
36
|
noise_shape[1] = 1 # Do not sample noise for channels individually
|
|
35
37
|
|
|
@@ -44,7 +46,7 @@ def phase_perturbation(amps,phases,rng=np.random.RandomState()):
|
|
|
44
46
|
pert_vals = np.abs(phase_noise)
|
|
45
47
|
return amps,phases_pert,pert_vals
|
|
46
48
|
|
|
47
|
-
def amp_perturbation_additive(amps,phases,rng=
|
|
49
|
+
def amp_perturbation_additive(amps,phases,rng=None):
|
|
48
50
|
"""Takes amplitudes and phases of BxCxF with B input, C channels, F frequencies
|
|
49
51
|
Adds additive noise N(0,0.02) to amplitudes
|
|
50
52
|
|
|
@@ -66,13 +68,15 @@ def amp_perturbation_additive(amps,phases,rng=np.random.RandomState()):
|
|
|
66
68
|
pert_vals : numpy array
|
|
67
69
|
Amplitude noise
|
|
68
70
|
"""
|
|
71
|
+
if rng is None:
|
|
72
|
+
rng = np.random.RandomState()
|
|
69
73
|
amp_noise = rng.normal(0,1,amps.shape).astype(np.float32)
|
|
70
74
|
amps_pert = amps+amp_noise
|
|
71
75
|
amps_pert[amps_pert<0] = 0
|
|
72
76
|
amp_noise = amps_pert-amps
|
|
73
77
|
return amps_pert,phases,amp_noise
|
|
74
78
|
|
|
75
|
-
def amp_perturbation_multiplicative(amps,phases,rng=
|
|
79
|
+
def amp_perturbation_multiplicative(amps,phases,rng=None):
|
|
76
80
|
"""Takes amplitude and phases of BxCxF with B input, C channels, F frequencies
|
|
77
81
|
Adds multiplicative noise N(1,0.02) to amplitudes
|
|
78
82
|
|
|
@@ -94,6 +98,8 @@ def amp_perturbation_multiplicative(amps,phases,rng=np.random.RandomState()):
|
|
|
94
98
|
pert_vals : numpy array
|
|
95
99
|
Amplitude scaling factor
|
|
96
100
|
"""
|
|
101
|
+
if rng is None:
|
|
102
|
+
rng = np.random.RandomState()
|
|
97
103
|
amp_noise = rng.normal(1,0.02,amps.shape).astype(np.float32)
|
|
98
104
|
amps_pert = amps*amp_noise
|
|
99
105
|
amps_pert[amps_pert<0] = 0
|
|
@@ -278,10 +284,10 @@ def compute_amplitude_prediction_correlations(pred_fn, examples, n_iterations,
|
|
|
278
284
|
----------
|
|
279
285
|
|
|
280
286
|
.. [EEGDeepLearning] Schirrmeister, R. T., Springenberg, J. T., Fiederer, L. D. J.,
|
|
281
|
-
Glasstetter, M., Eggensperger, K., Tangermann, M.,
|
|
287
|
+
Glasstetter, M., Eggensperger, K., Tangermann, M., Hutter, F. & Ball, T. (2017).
|
|
282
288
|
Deep learning with convolutional neural networks for EEG decoding and
|
|
283
289
|
visualization.
|
|
284
|
-
|
|
290
|
+
Human Brain Mapping , Aug. 2017. Online: http://dx.doi.org/10.1002/hbm.23730
|
|
285
291
|
"""
|
|
286
292
|
pred_fn_new = lambda x: [pred_fn(x)]
|
|
287
293
|
pred_corrs = spectral_perturbation_correlation(perturb_fn, mean_diff_feature_maps,
|
|
@@ -67,13 +67,11 @@ def ax_scalp(v, channels,
|
|
|
67
67
|
References
|
|
68
68
|
----------
|
|
69
69
|
|
|
70
|
-
|
|
71
70
|
.. [1] Schirrmeister, R. T., Springenberg, J. T., Fiederer, L. D. J.,
|
|
72
|
-
Glasstetter, M., Eggensperger, K., Tangermann, M.,
|
|
71
|
+
Glasstetter, M., Eggensperger, K., Tangermann, M., Hutter, F. & Ball, T. (2017).
|
|
73
72
|
Deep learning with convolutional neural networks for EEG decoding and
|
|
74
73
|
visualization.
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
Human Brain Mapping , Aug. 2017. Online: http://dx.doi.org/10.1002/hbm.23730
|
|
77
75
|
"""
|
|
78
76
|
if ax is None:
|
|
79
77
|
ax = plt.gca()
|