def _create_robintibor_balanced_folds(self): """ OLD BALANCED BATCHES ROUTINE ---------------------------- Using robintibor ml routine """ # getting pseudo-random folds folds = get_balanced_batches(n_trials=self.n_trials, rng=self.random_state, shuffle=self.shuffle, n_batches=self.n_folds) # train is everything except fold; test is fold indexes self.folds = [{ 'train': setdiff1d(arange(self.n_trials), fold), 'valid': None, 'test': fold } for fold in folds] # getting validation and reshaping train for idx, current_fold in enumerate(self.folds): self.folds[idx]['valid'] = \ current_fold['train'][-self.validation_size:] self.folds[idx]['train'] = \ current_fold['train'][:-self.validation_size]
def split_into_train_test(dataset, n_folds, i_test_fold, rng=None): """ Split datasets into folds, select one test fold and merge rest as train fold. Parameters ---------- dataset: :class:`.SignalAndTarget` n_folds: int Number of folds to split dataset into. i_test_fold: int Index of the test fold (0-based) rng: `numpy.random.RandomState`, optional Random Generator for shuffling, None means no shuffling Returns ------- reduced_set: :class:`.SignalAndTarget` Dataset with only examples selected. """ n_trials = len(dataset.X) if n_trials < n_folds: raise ValueError("Less Trials: {:d} than folds: {:d}".format( n_trials, n_folds)) shuffle = rng is not None folds = get_balanced_batches(n_trials, rng, shuffle, n_batches=n_folds) test_inds = folds[i_test_fold] all_inds = list(range(n_trials)) train_inds = np.setdiff1d(all_inds, test_inds) assert np.intersect1d(train_inds, test_inds).size == 0 assert np.array_equal(np.sort(np.union1d(train_inds, test_inds)), all_inds) train_set = select_examples(dataset, train_inds) test_set = select_examples(dataset, test_inds) return train_set, test_set
def split( self, X, y, ): if len(X) < self.n_folds: raise ValueError("Less Trials: {:d} than folds: {:d}".format( len(X), self.n_folds)) folds = get_balanced_batches(len(X), self.rng, self.shuffle, n_batches=self.n_folds) test_inds = folds[self.i_test_fold] valid_inds = folds[self.i_test_fold - 1] all_inds = list(range(len(X))) train_inds = np.setdiff1d(all_inds, np.union1d(test_inds, valid_inds)) assert np.intersect1d(train_inds, valid_inds).size == 0 assert np.intersect1d(train_inds, test_inds).size == 0 assert np.intersect1d(valid_inds, test_inds).size == 0 assert np.array_equal( np.sort(np.union1d(train_inds, np.union1d(valid_inds, test_inds))), all_inds) train_set = create_set(X, y, train_inds) valid_set = create_set(X, y, valid_inds) test_set = create_set(X, y, test_inds) return train_set, valid_set, test_set
def perturbation_correlation(pert_fn, diff_fn, pred_fn, n_layers, inputs, n_iterations, batch_size=30, seed=((2017, 7, 10))): """ Calculates phase perturbation correlation for layers in network pred_fn: Function that returns a list of activations. Each entry in the list corresponds to the output of 1 layer in a network n_layers: Number of layers pred_fn returns activations for. inputs: Original inputs that are used for perturbation [B,X,T,1] Phase perturbations are sampled for each input individually, but applied to all X of that input n_iterations: Number of iterations of correlation computation. The higher the better batch_size: Number of inputs that are used for one forward pass. (Concatenated for all inputs) """ rng = np.random.RandomState(seed) # Get batch indeces batch_inds = get_balanced_batches( n_trials=len(inputs), rng=rng, shuffle=False, batch_size=batch_size) # Calculate layer activations and reshape orig_preds = [pred_fn(inputs[inds]) for inds in batch_inds] orig_preds_layers = [np.concatenate([orig_preds[o][l] for o in range(len(orig_preds))]) for l in range(n_layers)] # Compute FFT of inputs fft_input = np.fft.rfft(inputs, n=inputs.shape[2], axis=2) amps = np.abs(fft_input) phases = np.angle(fft_input) pert_corrs = [0]*n_layers for i in range(n_iterations): #print('Iteration%d'%i) amps_pert,phases_pert,pert_vals = pert_fn(amps,phases,rng=rng) # Compute perturbed inputs fft_pert = amps_pert*np.exp(1j*phases_pert) inputs_pert = np.fft.irfft(fft_pert, n=inputs.shape[2], axis=2).astype(np.float32) # Calculate layer activations for perturbed inputs new_preds = [pred_fn(inputs_pert[inds]) for inds in batch_inds] new_preds_layers = [np.concatenate([new_preds[o][l] for o in range(len(new_preds))]) for l in range(n_layers)] for l in range(n_layers): # Calculate correlations of original and perturbed feature map activations preds_diff = diff_fn(orig_preds_layers[l][:,:,:,0],new_preds_layers[l][:,:,:,0]) # Calculate feature map correlations with absolute phase perturbations pert_corrs_tmp = wrap_reshape_apply_fn(corr, pert_vals[:,:,:,0],preds_diff, axis_a=(0), axis_b=(0)) pert_corrs[l] += pert_corrs_tmp pert_corrs = [pert_corrs[l]/n_iterations for l in range(n_layers)] #mean over iterations return pert_corrs
def _evalTraining(self, i_epoch, train_set, test_set): # Print some statistics each epoch self.model.eval() print("Epoch {:d}".format(i_epoch)) sets = {'Train': 0, 'Test': 1} # run evaluation on both train and test sets for setname, dataset in (('Train', train_set), ('Test', test_set)): # get balanced sets i_trials_in_batch = get_balanced_batches(len(dataset.X), self.rng, batch_size=32, shuffle=False) outputs = [] net_targets = [] # for all trials in set for i_trials in i_trials_in_batch: # adapt datasets batch_X = dataset.X[i_trials][:, :, :, None] batch_y = dataset.y[i_trials] # apply some conversion net_in = np_to_var(batch_X) net_target = np_to_var(batch_y) # convert if self.cuda: net_in = net_in.cuda() net_target = net_target.cuda() net_target = var_to_np(net_target) output = var_to_np(self.model(net_in)) outputs.append(output) net_targets.append(net_target) net_targets = np_to_var(np.concatenate(net_targets)) outputs = np_to_var(np.concatenate(outputs)) loss = F.nll_loss(outputs, net_targets) print("{:6s} Loss: {:.5f}".format(setname, float(var_to_np(loss)))) self.loss_rec[i_epoch, sets[setname]] = var_to_np(loss) predicted_labels = np.argmax(var_to_np(outputs), axis=1) accuracy = np.mean(dataset.y == predicted_labels) print("{:6s} Accuracy: {:.1f}%".format(setname, accuracy * 100)) self.accuracy_rec[i_epoch, sets[setname]] = accuracy return
def get_batches(self, dataset, shuffle): n_trials = dataset.X.shape[0] batches = get_balanced_batches(n_trials, batch_size=self.batch_size, rng=self.rng, shuffle=shuffle) for batch_inds in batches: batch_X = dataset.X[batch_inds] batch_y = dataset.y[batch_inds] batch_X = turn_dataset_to_timefreq(batch_X) # add empty fourth dimension if necessary if batch_X.ndim == 3: batch_X = batch_X[:, :, :, None] yield (batch_X, batch_y)
def init_training_vars(self): self.filterbands = generate_filterbank( min_freq=self.min_freq, max_freq=self.max_freq, last_low_freq=self.last_low_freq, low_width=self.low_width, low_overlap=self.low_overlap, high_width=self.high_width, high_overlap=self.high_overlap, low_bound=self.low_bound) assert filterbank_is_stable( self.filterbands, self.filt_order, self.cnt.info['sfreq']), ( "Expect filter bank to be stable given filter order.") # check if number of selected features is not too large if self.n_selected_features is not None: n_spatial_filters = self.n_top_bottom_csp_filters if n_spatial_filters is None: n_spatial_filters = len(self.cnt.ch_names) n_max_features = len(self.filterbands) * n_spatial_filters assert n_max_features >= self.n_selected_features, ( "Cannot select more features than will be originally created " "Originally: {:d}, requested: {:d}".format( n_max_features, self.n_selected_features) ) n_classes = len(self.name_to_start_codes) self.class_pairs = list(itertools.combinations(range(n_classes),2)) # use only number of clean trials to split folds epo = create_signal_target_from_raw_mne( self.cnt, name_to_start_codes=self.name_to_start_codes, epoch_ival_ms=self.epoch_ival_ms, name_to_stop_codes=self.name_to_stop_codes) n_trials = len(epo.X) if self.restricted_n_trials is not None: if self.restricted_n_trials <= 1: n_trials = int(n_trials * self.restricted_n_trials) else: n_trials = min(n_trials, self.restricted_n_trials) rng = RandomState(903372376) folds = get_balanced_batches(n_trials, rng, self.shuffle, n_batches=self.n_folds) # remap to original indices in unclean set(!) # train is everything except fold # test is fold inds self.folds = [{'train': np.setdiff1d(np.arange(n_trials),fold), 'test': fold} for fold in folds] if self.only_last_fold: self.folds = self.folds[-1:]
def get_batches(self, dataset, shuffle): n_trials = dataset.X.shape[0] batch_size_fake = int(np.ceil(self.batch_size * self.ratio)) batch_size_real = self.batch_size - batch_size_fake batches = get_balanced_batches(n_trials, batch_size=batch_size_real, rng=self.rng, shuffle=shuffle) for batch_inds in batches: batch_X = dataset.X[batch_inds] batch_y = dataset.y[batch_inds] fake_X, fake_y = self.trial_generator(batch_size_fake) batch_X = np.concatenate((batch_X, fake_X)) batch_y = np.concatenate((batch_y, fake_y)) # add empty fourth dimension if necessary if batch_X.ndim == 3: batch_X = batch_X[:, :, :, None] yield (batch_X, batch_y)
def split(self, X, y): folds = get_balanced_batches(len(X), None, False, n_batches=self.n_folds) test_inds = folds[self.i_test_fold] valid_inds = folds[self.i_test_fold - 1] all_inds = list(range(len(X))) train_inds = np.setdiff1d(all_inds, np.union1d(test_inds, valid_inds)) assert np.intersect1d(train_inds, valid_inds).size == 0 assert np.intersect1d(train_inds, test_inds).size == 0 assert np.intersect1d(valid_inds, test_inds).size == 0 assert np.array_equal( np.sort(np.union1d(train_inds, np.union1d(valid_inds, test_inds))), all_inds) train_set = create_set(X, y, train_inds) valid_set = create_set(X, y, valid_inds) test_set = create_set(X, y, test_inds) return train_set, valid_set, test_set
def _get_batch_indeces(self, dataset, shuffle): # start always at first predictable sample, so # start at end of receptive field n_receptive_field = self.input_time_length - self.n_preds_per_input + 1 i_trial_starts = [n_receptive_field - 1] * len(dataset.X) i_trial_stops = [trial.shape[1] for trial in dataset.X] # Check whether input lengths ok input_lens = i_trial_stops for i_trial, input_len in enumerate(input_lens): assert input_len >= self.input_time_length, ( "Input length {:d} of trial {:d} is smaller than the " "input time length {:d}".format(input_len, i_trial, self.input_time_length)) start_stop_blocks_per_trial = _compute_start_stop_block_inds( i_trial_starts, i_trial_stops, self.input_time_length, self.n_preds_per_input, check_preds_smaller_trial_len=self.check_preds_smaller_trial_len, ) for i_trial, trial_blocks in enumerate(start_stop_blocks_per_trial): assert trial_blocks[0][0] == 0 assert trial_blocks[-1][1] == i_trial_stops[i_trial] i_trial_start_stop_block = np.array([ (i_trial, start, stop) for i_trial, block in enumerate(start_stop_blocks_per_trial) for start, stop in block ]) batches = get_balanced_batches( n_trials=len(i_trial_start_stop_block), rng=self.rng, shuffle=shuffle, batch_size=self.batch_size, ) return [i_trial_start_stop_block[batch_ind] for batch_ind in batches]
def _batchTrain(self, i_epoch, train_set): # get a set of balanced batches i_trials_in_batch = get_balanced_batches(len(train_set.X), self.rng, shuffle=True, batch_size=32) self.adjust_learning_rate(self.optimizer, i_epoch) # Set model to training mode self.model.train() # go through all batches for i_trials in i_trials_in_batch: # Have to add empty fourth dimension to X batch_X = train_set.X[i_trials][:, :, :, None] batch_y = train_set.y[i_trials] net_in = np_to_var(batch_X) net_target = np_to_var(batch_y) # if cuda, copy to cuda memory if self.cuda: net_in = net_in.cuda() net_target = net_target.cuda() # Remove gradients of last backward pass from all parameters self.optimizer.zero_grad() # Compute outputs of the network outputs = self.model(net_in) # Compute the loss loss = F.nll_loss(outputs, net_target) # Do the backpropagation loss.backward() # Update parameters with the optimizer self.optimizer.step() return
def cross_validate_lda(features): n_trials = features.X.shape[0] folds = get_balanced_batches(n_trials, rng=None, shuffle=False, n_batches=5) # make to train-test splits, fold is test part.. folds = [(np.setdiff1d(np.arange(n_trials), fold), fold) for fold in folds] test_accuracies = [] for train_inds, test_inds in folds: train_features = select_trials(features, train_inds) test_features = select_trials(features, test_inds) clf = lda_train_scaled(train_features, shrink=True) test_out = lda_apply(test_features, clf) higher_class = np.max(test_features.y) true_0_1_labels_test = test_features.y == higher_class predicted_test = test_out >= 0 test_accuracy = np.mean(true_0_1_labels_test == predicted_test) test_accuracies.append(test_accuracy) return np.mean(test_accuracies)
def get_batches(self, dataset, shuffle): n_trials = dataset.y['source'].shape[0] batches = get_balanced_batches(n_trials, batch_size=self.batch_size, rng=self.rng, shuffle=shuffle) for batch_inds in batches: batch_inds = np.array(batch_inds) batch_X = { 'source': dataset.X['source'][batch_inds], 'target': dataset.X['target'][batch_inds] } batch_y = { 'source': dataset.y['source'][batch_inds], 'target': dataset.y['target'][batch_inds] } # add empty fourth dimension if necessary if batch_X['source'].ndim == 3: batch_X['source'] = batch_X['source'][:, :, :, None] if batch_X['target'].ndim == 3: batch_X['target'] = batch_X['target'][:, :, :, None] yield (batch_X, batch_y)
def create_folds(self): if self.cross_subject_computation is True: # in case of cross-subject computation folds = [ arange(self.cross_subject_object.subject_indexes[x][0], self.cross_subject_object.subject_indexes[x][1]) for x in range(len(self.cross_subject_object.subject_indexes)) ] self.n_folds = len(folds) self.folds = [{ 'train': setdiff1d(arange(self.n_trials), fold), 'test': fold } for fold in folds] elif self.load_fold_from_file is True: # in case of pre-batched computation self.folds = np.load(self.fold_file)['folds'] elif self.n_folds == 0: self.n_folds = 1 # creating schirrmeister fold all_idxs = np.array(range(len(self.clean_trial_mask))) self.folds = [{'train': all_idxs[:-160], 'test': all_idxs[-160:]}] self.folds[0]['train'] = self.folds[0]['train'][ self.clean_trial_mask[:-160]] self.folds[0]['test'] = self.folds[0]['test'][ self.clean_trial_mask[-160:]] else: # getting pseudo-random folds folds = get_balanced_batches(n_trials=self.n_trials, rng=self.random_state, shuffle=self.shuffle, n_batches=self.n_folds) self.folds = [{ 'train': setdiff1d(arange(self.n_trials), fold), 'test': fold } for fold in folds]
def compute_amplitude_prediction_correlations_voltage(pred_fn, examples, n_iterations, perturb_fn=None, batch_size=30, seed=((2017, 7, 10))): """ Changed function to calculate time-resolved voltage pertubations, and not frequency as original in compute_amplitude_prediction_correlations Perturb input amplitudes and compute correlation between amplitude perturbations and prediction changes when pushing perturbed input through the prediction function. For more details, see [EEGDeepLearning]_. Parameters ---------- pred_fn: function Function accepting an numpy input and returning prediction. examples: ndarray Numpy examples, first axis should be example axis. n_iterations: int Number of iterations to compute. perturb_fn: function, optional Function accepting amplitude array and random generator and returning perturbation. Default is Gaussian perturbation. batch_size: int, optional Batch size for computing predictions. seed: int, optional Random generator seed Returns ------- amplitude_pred_corrs: ndarray Correlations between amplitude perturbations and prediction changes for all sensors and frequency bins. References ---------- .. [EEGDeepLearning] Schirrmeister, R. T., Springenberg, J. T., Fiederer, L. D. J., Glasstetter, M., Eggensperger, K., Tangermann, M., ... & Ball, T. (2017). Deep learning with convolutional neural networks for EEG decoding and visualization. arXiv preprint arXiv:1703.05051. """ inds_per_batch = get_balanced_batches(n_trials=len(examples), rng=None, shuffle=False, batch_size=batch_size) log.info("Compute original predictions...") orig_preds = [ pred_fn(examples[example_inds]) for example_inds in inds_per_batch ] orig_preds_arr = np.concatenate(orig_preds) rng = RandomState(seed) fft_input = np.fft.rfft(examples, axis=2) amps = np.abs(fft_input) phases = np.angle(fft_input) amp_pred_corrs = [] for i_iteration in range(n_iterations): log.info("Iteration {:d}...".format(i_iteration)) log.info("Sample perturbation...") #modified part start perturbation = rng.randn(*examples.shape) new_in = examples + perturbation #modified part end log.info("Compute new predictions...") new_in = new_in.astype('float32') new_preds = [ pred_fn(new_in[example_inds]) for example_inds in inds_per_batch ] new_preds_arr = np.concatenate(new_preds) diff_preds = new_preds_arr - orig_preds_arr log.info("Compute correlation...") amp_pred_corr = wrap_reshape_apply_fn(corr, perturbation[:, :, :, 0], diff_preds, axis_a=(0, ), axis_b=(0)) amp_pred_corrs.append(amp_pred_corr) return amp_pred_corrs
def test_trialwise_decoding(): # 5,6,7,10,13,14 are codes for executed and imagined hands/feet subject_id = 1 event_codes = [5, 6, 9, 10, 13, 14] # event_codes = [6] # This will download the files if you don't have them yet, # and then return the paths to the files. physionet_paths = mne.datasets.eegbci.load_data(subject_id, event_codes) # Load each of the files parts = [ mne.io.read_raw_edf(path, preload=True, stim_channel='auto', verbose='WARNING') for path in physionet_paths ] # Concatenate them raw = concatenate_raws(parts) # Find the events in this dataset # events = mne.find_events(raw, shortest_event=0, stim_channel='STI 014') events, _ = mne.events_from_annotations(raw) # Extract trials, only using EEG channels eeg_channel_inds = mne.pick_types(raw.info, meg=False, eeg=True, stim=False, eog=False, exclude='bads') # Extract trials, only using EEG channels epoched = mne.Epochs(raw, events, dict(hands=2, feet=3), tmin=1, tmax=4.1, proj=False, picks=eeg_channel_inds, baseline=None, preload=True) # Convert data from volt to millivolt # Pytorch expects float32 for input and int64 for labels. # X:[90,64,497] X = (epoched.get_data() * 1e6).astype(np.float32) # y:[90] y = (epoched.events[:, 2] - 2).astype(np.int64) # 2,3 -> 0,1 # X_train:[60,64,497], y_train:[60] train_set = SignalAndTarget(X[:60], y=y[:60]) # X_test:[30,64,497], y_test:[30] test_set = SignalAndTarget(X[60:], y=y[60:]) # Set if you want to use GPU # You can also use torch.cuda.is_available() to determine if cuda is available on your machine. cuda = False set_random_seeds(seed=20170629, cuda=cuda) n_classes = 2 in_chans = train_set.X.shape[1] # final_conv_length = auto ensures we only get a single output in the time dimension # def __init__(self, in_chans=64, n_classes=2, input_time_length=497, n_filters_time=40, filter_time_length=25, n_filters_spat=40, pool_time_length=75, pool_time_stride=15, final_conv_length='auto, conv_nonlin=square, pool_mode="mean", pool_nonlin=safe_log, split_first_layer=True, batch_norm=True, batch_norm_alpha=0.1, drop_prob=0.5, ): # 感觉create_network()就是__init__的一部分, 现在改成用self.model调用了, 还是感觉不优雅, 主要是forward集成在nn.Sequential里面了 # 然后这个model的实际__init__不是ShallowFBCSPNet, 而是nn.Sequential, 感觉我更喜欢原来的定义方式, 这种方式看不到中间输出 # model = ShallowFBCSPNet(in_chans=in_chans, n_classes=n_classes, input_time_length=train_set.X.shape[2], final_conv_length='auto').create_network() #原来的 model = ShallowFBCSPNet(in_chans=in_chans, n_classes=n_classes, input_time_length=train_set.X.shape[2], final_conv_length='auto').model if cuda: model.cuda() optimizer = optim.Adam(model.parameters()) rng = RandomState((2017, 6, 30)) losses = [] accuracies = [] for i_epoch in range(6): i_trials_in_batch = get_balanced_batches(len(train_set.X), rng, shuffle=True, batch_size=10) # Set model to training mode model.train() for i_trials in i_trials_in_batch: # Have to add empty fourth dimension to X batch_X = train_set.X[i_trials][:, :, :, None] batch_y = train_set.y[i_trials] net_in = np_to_var(batch_X) if cuda: net_in = net_in.cuda() net_target = np_to_var(batch_y) if cuda: net_target = net_target.cuda() # Remove gradients of last backward pass from all parameters optimizer.zero_grad() # Compute outputs of the network #net_in: [10, 64, 497, 1]=[bsz, H_im, W_im, C_im] # outputs = model.forward(net_in) # model=Sequential( # (dimshuffle): Expression(expression=_transpose_time_to_spat) # (conv_time): Conv2d(1, 40, kernel_size=(25, 1), stride=(1, 1)) # (conv_spat): Conv2d(40, 40, kernel_size=(1, 64), stride=(1, 1), bias=False) # (bnorm): BatchNorm2d(40, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) # (conv_nonlin): Expression(expression=square) # (pool): AvgPool2d(kernel_size=(75, 1), stride=(15, 1), padding=0) # (pool_nonlin): Expression(expression=safe_log) # (drop): Dropout(p=0.5) # (conv_classifier): Conv2d(40, 2, kernel_size=(27, 1), stride=(1, 1)) # (softmax): LogSoftmax() # (squeeze): Expression(expression=_squeeze_final_output) # ) # Compute the loss loss = F.nll_loss(outputs, net_target) # Do the backpropagation loss.backward() # Update parameters with the optimizer optimizer.step() # Print some statistics each epoch model.eval() print("Epoch {:d}".format(i_epoch)) for setname, dataset in (('Train', train_set), ('Test', test_set)): # Here, we will use the entire dataset at once, which is still possible # for such smaller datasets. Otherwise we would have to use batches. net_in = np_to_var(dataset.X[:, :, :, None]) if cuda: net_in = net_in.cuda() net_target = np_to_var(dataset.y) if cuda: net_target = net_target.cuda() outputs = model(net_in) loss = F.nll_loss(outputs, net_target) losses.append(float(var_to_np(loss))) print("{:6s} Loss: {:.5f}".format(setname, float(var_to_np(loss)))) predicted_labels = np.argmax(var_to_np(outputs), axis=1) accuracy = np.mean(dataset.y == predicted_labels) accuracies.append(accuracy * 100) print("{:6s} Accuracy: {:.1f}%".format(setname, accuracy * 100)) np.testing.assert_allclose(np.array(losses), np.array([ 1.1775966882705688, 1.2602351903915405, 0.7068756818771362, 0.9367912411689758, 0.394258975982666, 0.6598362326622009, 0.3359280526638031, 0.656258761882782, 0.2790488004684448, 0.6104397177696228, 0.27319177985191345, 0.5949864983558655 ]), rtol=1e-4, atol=1e-5) np.testing.assert_allclose(np.array(accuracies), np.array([ 51.666666666666671, 53.333333333333336, 63.333333333333329, 56.666666666666664, 86.666666666666671, 66.666666666666657, 90.0, 63.333333333333329, 96.666666666666671, 56.666666666666664, 96.666666666666671, 66.666666666666657 ]), rtol=1e-4, atol=1e-5)
def compute_amplitude_prediction_correlations_batchwise( pred_fn, examples, n_iterations, perturb_fn=gaussian_perturbation, batch_size=30, seed=((2017, 7, 10)), original_y=None, ): """ Perturb input amplitudes and compute correlation between amplitude perturbations and prediction changes when pushing perturbed input through the prediction function. For more details, see [EEGDeepLearning]_. Parameters ---------- pred_fn: function Function accepting an numpy input and returning prediction. examples: ndarray Numpy examples, first axis should be example axis. n_iterations: int Number of iterations to compute. perturb_fn: function, optional Function accepting amplitude array and random generator and returning perturbation. Default is Gaussian perturbation. batch_size: int, optional Batch size for computing predictions. seed: int, optional Random generator seed Returns ------- amplitude_pred_corrs: ndarray Correlations between amplitude perturbations and prediction changes for all sensors and frequency bins. References ---------- .. [EEGDeepLearning] Schirrmeister, R. T., Springenberg, J. T., Fiederer, L. D. J., Glasstetter, M., Eggensperger, K., Tangermann, M., ... & Ball, T. (2017). Deep learning with convolutional neural networks for EEG decoding and visualization. arXiv preprint arXiv:1703.05051. """ inds_per_batch = get_balanced_batches(n_trials=len(examples), rng=None, shuffle=False, batch_size=batch_size) log.info("Compute original predictions...") orig_preds = [ pred_fn(examples[example_inds]) for example_inds in inds_per_batch ] orig_preds_arr = np.concatenate(orig_preds) if original_y is not None: orig_pred_labels = np.argmax(orig_preds_arr, axis=1) orig_accuracy = np.mean(orig_pred_labels == original_y) log.info("Original accuracy: {:.2f}...".format(orig_accuracy)) amp_pred_corrs = [] new_accuracies = [] rng = RandomState(seed) for i_iteration in range(n_iterations): log.info("Iteration {:d}...".format(i_iteration)) size_so_far = 0 mean_perturb_so_far = None mean_pred_diff_so_far = None var_perturb_so_far = None var_pred_diff_so_far = None covariance_so_far = None all_new_pred_labels = [] for example_inds in inds_per_batch: this_orig_preds = orig_preds_arr[example_inds] this_examples = examples[example_inds] fft_input = np.fft.rfft(this_examples, axis=2).astype(np.complex64) amps = np.abs(fft_input).astype(np.float32) phases = np.angle(fft_input).astype(np.float32) #log.info("Sample perturbation...") perturbation = perturb_fn(amps, rng).astype(np.float32) #log.info("Compute new amplitudes...") # do not allow perturbation to make amplitudes go below # zero perturbation = np.maximum(-amps, perturbation) new_amps = amps + perturbation new_amps = new_amps.astype(np.float32) #log.info("Compute new complex inputs...") new_complex = _amplitude_phase_to_complex(new_amps, phases).astype( np.complex64) #log.info("Compute new real inputs...") new_in = np.fft.irfft(new_complex, axis=2).astype(np.float32) #log.info("Compute new predictions...") new_preds_arr = pred_fn(new_in) if original_y is not None: new_pred_labels = np.argmax(new_preds_arr, axis=1) all_new_pred_labels.append(new_pred_labels) diff_preds = new_preds_arr - this_orig_preds this_amp_pred_cov = wrap_reshape_apply_fn(cov, perturbation[:, :, :, 0], diff_preds, axis_a=(0, ), axis_b=(0)) var_perturb = np.var(perturbation, axis=0, ddof=1) var_pred_diff = np.var(diff_preds, axis=0, ddof=1) mean_perturb = np.mean(perturbation, axis=0) mean_diff_pred = np.mean(diff_preds) if mean_perturb_so_far is None: mean_perturb_so_far = mean_perturb mean_pred_diff_so_far = mean_diff_pred covariance_so_far = this_amp_pred_cov var_perturb_so_far = var_perturb var_pred_diff_so_far = var_pred_diff else: covariance_so_far = combine_covs(covariance_so_far, size_so_far, mean_perturb_so_far, mean_pred_diff_so_far, this_amp_pred_cov, len(example_inds), mean_perturb, mean_diff_pred) var_perturb_so_far = combine_vars( var_perturb_so_far, size_so_far, mean_perturb_so_far, var_perturb, len(example_inds), mean_perturb, ) var_pred_diff_so_far = combine_vars( var_pred_diff_so_far, size_so_far, mean_pred_diff_so_far, var_pred_diff, len(example_inds), mean_diff_pred, ) next_size = size_so_far + len(example_inds) mean_perturb_so_far = ( (mean_perturb_so_far * size_so_far / float(next_size)) + (mean_perturb * len(example_inds) / float(next_size))) mean_pred_diff_so_far = ( (mean_pred_diff_so_far * size_so_far / float(next_size)) + (mean_diff_pred * len(example_inds) / float(next_size))) size_so_far += len(example_inds) all_new_pred_labels = np.concatenate(all_new_pred_labels) new_accuracy = np.mean(all_new_pred_labels == original_y) assert len(original_y) == len(all_new_pred_labels) log.info("New accuracy: {:.2f}...".format(new_accuracy)) new_accuracies.append(new_accuracy) divisor = np.outer(np.sqrt(var_perturb_so_far), np.sqrt(var_pred_diff_so_far)).reshape( (var_perturb_so_far.shape + var_pred_diff_so_far.shape)).squeeze() this_amp_pred_corr = covariance_so_far / divisor amp_pred_corrs.append(this_amp_pred_corr) if original_y is not None: return amp_pred_corrs, orig_accuracy, new_accuracies else: return amp_pred_corrs
z_vars_im = rng.normal(0,1,size=(1000,n_z)).astype(np.float32) for i_block in range(i_block_tmp,n_blocks): c = 0 train_tmp = discriminator.model.downsample_to_block(Variable(torch.from_numpy(train).cuda(),volatile=True),discriminator.model.cur_block).data.cpu() for i_epoch in range(i_epoch_tmp,block_epochs[i_block]): i_epoch_tmp = 0 if fade_alpha<1: fade_alpha += 1./rampup generator.model.alpha = fade_alpha discriminator.model.alpha = fade_alpha batches = get_balanced_batches(train.shape[0], rng, True, batch_size=n_batch) iters = int(len(batches)/n_critic) for it in range(iters): for i_critic in range(n_critic): train_batches = train_tmp[batches[it*n_critic+i_critic]] batch_real = Variable(train_batches,requires_grad=True).cuda() z_vars = rng.normal(0,1,size=(len(batches[it*n_critic+i_critic]),n_z)).astype(np.float32) z_vars = Variable(torch.from_numpy(z_vars),volatile=True).cuda() batch_fake = Variable(generator(z_vars).data,requires_grad=True).cuda() loss_d = discriminator.train_batch(batch_real,batch_fake) assert np.all(np.isfinite(loss_d)) z_vars = rng.normal(0,1,size=(n_batch,n_z)).astype(np.float32) z_vars = Variable(torch.from_numpy(z_vars),requires_grad=True).cuda()
def compute_amplitude_prediction_correlations( pred_fn, examples, n_iterations, perturb_fn=gaussian_perturbation, batch_size=30, seed=((2017, 7, 10)), original_y=None, ): """ Perturb input amplitudes and compute correlation between amplitude perturbations and prediction changes when pushing perturbed input through the prediction function. For more details, see [EEGDeepLearning]_. Parameters ---------- pred_fn: function Function accepting an numpy input and returning prediction. examples: ndarray Numpy examples, first axis should be example axis. n_iterations: int Number of iterations to compute. perturb_fn: function, optional Function accepting amplitude array and random generator and returning perturbation. Default is Gaussian perturbation. batch_size: int, optional Batch size for computing predictions. seed: int, optional Random generator seed Returns ------- amplitude_pred_corrs: ndarray Correlations between amplitude perturbations and prediction changes for all sensors and frequency bins. References ---------- .. [EEGDeepLearning] Schirrmeister, R. T., Springenberg, J. T., Fiederer, L. D. J., Glasstetter, M., Eggensperger, K., Tangermann, M., ... & Ball, T. (2017). Deep learning with convolutional neural networks for EEG decoding and visualization. arXiv preprint arXiv:1703.05051. """ inds_per_batch = get_balanced_batches(n_trials=len(examples), rng=None, shuffle=False, batch_size=batch_size) log.info("Compute original predictions...") orig_preds = [ pred_fn(examples[example_inds]) for example_inds in inds_per_batch ] orig_preds_arr = np.concatenate(orig_preds) if original_y is not None: orig_pred_labels = np.argmax(orig_preds_arr, axis=1) orig_accuracy = np.mean(orig_pred_labels == original_y) log.info("Original accuracy: {:.2f}...".format(orig_accuracy)) rng = RandomState(seed) fft_input = np.fft.rfft(examples, axis=2).astype(np.complex64) amps = np.abs(fft_input).astype(np.float32) phases = np.angle(fft_input).astype(np.float32) del fft_input amp_pred_corrs = [] new_accuracies = [] for i_iteration in range(n_iterations): log.info("Iteration {:d}...".format(i_iteration)) log.info("Sample perturbation...") perturbation = perturb_fn(amps, rng).astype(np.float32) log.info("Compute new amplitudes...") # do not allow perturbation to make amplitudes go below # zero perturbation = np.maximum(-amps, perturbation) new_amps = amps + perturbation new_amps = new_amps.astype(np.float32) log.info("Compute new complex inputs...") new_complex = _amplitude_phase_to_complex(new_amps, phases).astype(np.complex64) log.info("Compute new real inputs...") new_in = np.fft.irfft(new_complex, axis=2).astype(np.float32) del new_complex, new_amps log.info("Compute new predictions...") new_preds = [ pred_fn(new_in[example_inds]) for example_inds in inds_per_batch ] new_preds_arr = np.concatenate(new_preds) if original_y is not None: new_pred_labels = np.argmax(new_preds_arr, axis=1) new_accuracy = np.mean(new_pred_labels == original_y) log.info("New accuracy: {:.2f}...".format(new_accuracy)) new_accuracies.append(new_accuracy) diff_preds = new_preds_arr - orig_preds_arr log.info("Compute correlation...") amp_pred_corr = wrap_reshape_apply_fn(corr, perturbation[:, :, :, 0], diff_preds, axis_a=(0, ), axis_b=(0)) print("max corr", np.max(amp_pred_corr)) print("min corr", np.min(amp_pred_corr)) amp_pred_corrs.append(amp_pred_corr) if original_y is not None: return amp_pred_corrs, orig_accuracy, new_accuracies else: return amp_pred_corrs
def test_trialwise_decoding(): # 5,6,7,10,13,14 are codes for executed and imagined hands/feet subject_id = 1 event_codes = [5, 6, 9, 10, 13, 14] # This will download the files if you don't have them yet, # and then return the paths to the files. physionet_paths = mne.datasets.eegbci.load_data(subject_id, event_codes) # Load each of the files parts = [ mne.io.read_raw_edf(path, preload=True, stim_channel='auto', verbose='WARNING') for path in physionet_paths ] # Concatenate them raw = concatenate_raws(parts) # Find the events in this dataset events, _ = mne.events_from_annotations(raw) # Use only EEG channels eeg_channel_inds = mne.pick_types(raw.info, meg=False, eeg=True, stim=False, eog=False, exclude='bads') # Extract trials, only using EEG channels epoched = mne.Epochs(raw, events, dict(hands=2, feet=3), tmin=1, tmax=4.1, proj=False, picks=eeg_channel_inds, baseline=None, preload=True) # Convert data from volt to millivolt # Pytorch expects float32 for input and int64 for labels. X = (epoched.get_data() * 1e6).astype(np.float32) y = (epoched.events[:, 2] - 2).astype(np.int64) # 2,3 -> 0,1 train_set = SignalAndTarget(X[:60], y=y[:60]) test_set = SignalAndTarget(X[60:], y=y[60:]) # Set if you want to use GPU # You can also use torch.cuda.is_available() to determine if cuda is available on your machine. cuda = False set_random_seeds(seed=20170629, cuda=cuda) n_classes = 2 in_chans = train_set.X.shape[1] # final_conv_length = auto ensures we only get a single output in the time dimension model = ShallowFBCSPNet(in_chans=in_chans, n_classes=n_classes, input_time_length=train_set.X.shape[2], final_conv_length='auto').create_network() if cuda: model.cuda() optimizer = optim.Adam(model.parameters()) rng = RandomState((2017, 6, 30)) losses = [] accuracies = [] for i_epoch in range(6): i_trials_in_batch = get_balanced_batches(len(train_set.X), rng, shuffle=True, batch_size=30) # Set model to training mode model.train() for i_trials in i_trials_in_batch: # Have to add empty fourth dimension to X batch_X = train_set.X[i_trials][:, :, :, None] batch_y = train_set.y[i_trials] net_in = np_to_var(batch_X) if cuda: net_in = net_in.cuda() net_target = np_to_var(batch_y) if cuda: net_target = net_target.cuda() # Remove gradients of last backward pass from all parameters optimizer.zero_grad() # Compute outputs of the network outputs = model(net_in) # Compute the loss loss = F.nll_loss(outputs, net_target) # Do the backpropagation loss.backward() # Update parameters with the optimizer optimizer.step() # Print some statistics each epoch model.eval() print("Epoch {:d}".format(i_epoch)) for setname, dataset in (('Train', train_set), ('Test', test_set)): # Here, we will use the entire dataset at once, which is still possible # for such smaller datasets. Otherwise we would have to use batches. net_in = np_to_var(dataset.X[:, :, :, None]) if cuda: net_in = net_in.cuda() net_target = np_to_var(dataset.y) if cuda: net_target = net_target.cuda() outputs = model(net_in) loss = F.nll_loss(outputs, net_target) losses.append(float(var_to_np(loss))) print("{:6s} Loss: {:.5f}".format(setname, float(var_to_np(loss)))) predicted_labels = np.argmax(var_to_np(outputs), axis=1) accuracy = np.mean(dataset.y == predicted_labels) accuracies.append(accuracy * 100) print("{:6s} Accuracy: {:.1f}%".format(setname, accuracy * 100)) np.testing.assert_allclose(np.array(losses), np.array([ 0.91796708, 1.2714895, 0.4999536, 0.94365239, 0.39268905, 0.89928466, 0.37648854, 0.8940345, 0.35774994, 0.86749417, 0.35080773, 0.80767328 ]), rtol=1e-4, atol=1e-5) np.testing.assert_allclose(np.array(accuracies), np.array([ 55., 63.33333333, 71.66666667, 63.33333333, 81.66666667, 60., 78.33333333, 63.33333333, 83.33333333, 66.66666667, 80., 66.66666667 ]), rtol=1e-4, atol=1e-5)
def run_exp(max_recording_mins, n_recordings, sec_to_cut, duration_recording_mins, max_abs_val, max_min_threshold, max_min_expected, shrink_val, max_min_remove, batch_set_zero_val, batch_set_zero_test, sampling_freq, low_cut_hz, high_cut_hz, exp_demean, exp_standardize, moving_demean, moving_standardize, channel_demean, channel_standardize, divisor, n_folds, i_test_fold, model_name, input_time_length, final_conv_length, batch_size, max_epochs, only_return_exp): cuda = True preproc_functions = [] preproc_functions.append(lambda data, fs: ( data[:, int(sec_to_cut * fs):-int(sec_to_cut * fs)], fs)) preproc_functions.append(lambda data, fs: (data[:, :int( duration_recording_mins * 60 * fs)], fs)) if max_abs_val is not None: preproc_functions.append( lambda data, fs: (np.clip(data, -max_abs_val, max_abs_val), fs)) if max_min_threshold is not None: preproc_functions.append(lambda data, fs: (clean_jumps( data, 200, max_min_threshold, max_min_expected, cuda), fs)) if max_min_remove is not None: window_len = 200 preproc_functions.append(lambda data, fs: (set_jumps_to_zero( data, window_len=window_len, threshold=max_min_remove, cuda=cuda, clip_min_max_to_zero=True), fs)) if shrink_val is not None: preproc_functions.append(lambda data, fs: (shrink_spikes( data, shrink_val, 1, 9, ), fs)) preproc_functions.append(lambda data, fs: (resampy.resample( data, fs, sampling_freq, axis=1, filter='kaiser_fast'), sampling_freq)) preproc_functions.append(lambda data, fs: (bandpass_cnt( data, low_cut_hz, high_cut_hz, fs, filt_order=4, axis=1), fs)) if exp_demean: preproc_functions.append(lambda data, fs: (exponential_running_demean( data.T, factor_new=0.001, init_block_size=100).T, fs)) if exp_standardize: preproc_functions.append( lambda data, fs: (exponential_running_standardize( data.T, factor_new=0.001, init_block_size=100).T, fs)) if moving_demean: preproc_functions.append(lambda data, fs: (padded_moving_demean( data, axis=1, n_window=201), fs)) if moving_standardize: preproc_functions.append(lambda data, fs: (padded_moving_standardize( data, axis=1, n_window=201), fs)) if channel_demean: preproc_functions.append(lambda data, fs: (demean(data, axis=1), fs)) if channel_standardize: preproc_functions.append(lambda data, fs: (standardize(data, axis=1), fs)) if divisor is not None: preproc_functions.append(lambda data, fs: (data / divisor, fs)) all_file_names, labels = get_all_sorted_file_names_and_labels() lengths = np.load( '/home/schirrmr/code/auto-diagnosis/sorted-recording-lengths.npy') mask = lengths < max_recording_mins * 60 cleaned_file_names = np.array(all_file_names)[mask] cleaned_labels = labels[mask] diffs_per_rec = np.load( '/home/schirrmr/code/auto-diagnosis/diffs_per_recording.npy') def create_set(inds): X = [] for i in inds: log.info("Load {:s}".format(cleaned_file_names[i])) x = load_data(cleaned_file_names[i], preproc_functions) X.append(x) y = cleaned_labels[inds].astype(np.int64) return SignalAndTarget(X, y) if not only_return_exp: folds = get_balanced_batches(n_recordings, None, False, n_batches=n_folds) test_inds = folds[i_test_fold] valid_inds = folds[i_test_fold - 1] all_inds = list(range(n_recordings)) train_inds = np.setdiff1d(all_inds, np.union1d(test_inds, valid_inds)) rec_nr_sorted_by_diff = np.argsort(diffs_per_rec)[::-1] train_inds = rec_nr_sorted_by_diff[train_inds] valid_inds = rec_nr_sorted_by_diff[valid_inds] test_inds = rec_nr_sorted_by_diff[test_inds] train_set = create_set(train_inds) valid_set = create_set(valid_inds) test_set = create_set(test_inds) else: train_set = None valid_set = None test_set = None set_random_seeds(seed=20170629, cuda=cuda) # This will determine how many crops are processed in parallel n_classes = 2 in_chans = 21 if model_name == 'shallow': model = ShallowFBCSPNet( in_chans=in_chans, n_classes=n_classes, input_time_length=input_time_length, final_conv_length=final_conv_length).create_network() elif model_name == 'deep': model = Deep4Net(in_chans, n_classes, input_time_length=input_time_length, final_conv_length=final_conv_length).create_network() optimizer = optim.Adam(model.parameters()) to_dense_prediction_model(model) log.info("Model:\n{:s}".format(str(model))) if cuda: model.cuda() # determine output size test_input = np_to_var( np.ones((2, in_chans, input_time_length, 1), dtype=np.float32)) if cuda: test_input = test_input.cuda() out = model(test_input) n_preds_per_input = out.cpu().data.numpy().shape[2] log.info("{:d} predictions per input/trial".format(n_preds_per_input)) iterator = CropsFromTrialsIterator(batch_size=batch_size, input_time_length=input_time_length, n_preds_per_input=n_preds_per_input) loss_function = lambda preds, targets: F.nll_loss( th.mean(preds, dim=2)[:, :, 0], targets) model_constraint = None monitors = [ LossMonitor(), MisclassMonitor(col_suffix='sample_misclass'), CroppedTrialMisclassMonitor(input_time_length), RuntimeMonitor(), ] stop_criterion = MaxEpochs(max_epochs) batch_modifier = None if batch_set_zero_val is not None: batch_modifier = RemoveMinMaxDiff(batch_set_zero_val, clip_max_abs=True, set_zero=True) if (batch_set_zero_val is not None) and (batch_set_zero_test == True): iterator = ModifiedIterator( iterator, batch_modifier, ) batch_modifier = None exp = Experiment(model, train_set, valid_set, test_set, iterator, loss_function, optimizer, model_constraint, monitors, stop_criterion, remember_best_column='valid_misclass', run_after_early_stop=True, batch_modifier=batch_modifier, cuda=cuda) if not only_return_exp: exp.run() else: exp.dataset = None exp.splitter = None return exp
def split_paired_into_train_test(paired_dataset, n_folds, i_test_fold, n_classes, rng=None): # Indexing with lists faster than ndarrays: assert type(paired_dataset.X['source']) == list and \ type(paired_dataset.X['source']) == list, \ "Expected paired dataset X to be list containing ndarrays." n_trials = len(paired_dataset.X['source']) if n_trials < n_folds: raise ValueError("Less Trials: {:d} than folds: {:d}".format( n_trials, n_folds)) train_indices = [] test_indices = [] source_y = paired_dataset.y['source'] target_y = paired_dataset.y['target'] n_possible_label_pairs = n_classes**2 lists_of_indices_per_pair = [[] for _ in range(n_possible_label_pairs)] possible_label_pairs = [] for i in range(n_classes): for j in range(n_classes): possible_label_pairs.append((i, j)) # for i in range(source_y.shape[0]): for i in range(len(source_y)): src_label = source_y[i] tgt_label = target_y[i] idx = possible_label_pairs.index((src_label, tgt_label)) lists_of_indices_per_pair[idx].append(i) for pair_list in lists_of_indices_per_pair: # pair_list = np.array(pair_list) n_list_trials = len(pair_list) shuffle = rng is not None folds = get_balanced_batches(n_list_trials, rng, shuffle, n_batches=n_folds) list_test_inds = folds[i_test_fold] list_all_inds = list(range(n_list_trials)) list_train_inds = np.setdiff1d(list_all_inds, list_test_inds) assert np.intersect1d(list_train_inds, list_test_inds).size == 0 assert np.array_equal( np.sort(np.union1d(list_train_inds, list_test_inds)), list_all_inds) # train_indices += pair_list[list_train_inds] # test_indices += pair_list[list_test_inds] train_indices += [pair_list[i] for i in list_train_inds] test_indices += [pair_list[i] for i in list_test_inds] # Because indices now sorted by label pairing, shuffle them: # np.random.shuffle(train_indices) # np.random.shuffle(test_indices) random.shuffle(train_indices) random.shuffle(test_indices) train_set = select_pairs_from_paired_dataset(paired_dataset, train_indices) test_set = select_pairs_from_paired_dataset(paired_dataset, test_indices) return train_set, test_set
def spectral_perturbation_correlation(pert_fn, diff_fn, pred_fn, n_layers, inputs, n_iterations, batch_size=30, seed=((2017, 7, 10))): """Calculates perturbation correlations for layers in network by perturbing either amplitudes or phases Parameters ---------- pert_fn : function Function that perturbs spectral phase and amplitudes of inputs diff_fn : function Function that calculates difference between original and perturbed activations pred_fn : function Function that returns a list of activations. Each entry in the list corresponds to the output of 1 layer in a network n_layers : int Number of layers pred_fn returns activations for. inputs : numpy array Original inputs that are used for perturbation [B,X,T,1] Phase perturbations are sampled for each input individually, but applied to all X of that input n_iterations : int Number of iterations of correlation computation. The higher the better batch_size : int Number of inputs that are used for one forward pass. (Concatenated for all inputs) Returns ------- pert_corrs : numpy array List of length n_layers containing average perturbation correlations over iterations L x CxFrxFi (Channels,Frequencies,Filters) """ rng = np.random.RandomState(seed) # Get batch indeces batch_inds = get_balanced_batches(n_trials=len(inputs), rng=rng, shuffle=False, batch_size=batch_size) # Calculate layer activations and reshape log.info("Compute original predictions...") orig_preds = [pred_fn(inputs[inds]) for inds in batch_inds] use_shape = [] for l in range(n_layers): tmp = list(orig_preds[0][l].shape) tmp.extend([1] * (4 - len(tmp))) tmp[0] = len(inputs) use_shape.append(tmp) orig_preds_layers = [ np.concatenate([orig_preds[o][l] for o in range(len(orig_preds))]).reshape(use_shape[l]) for l in range(n_layers) ] # Compute FFT of inputs fft_input = np.fft.rfft(inputs, n=inputs.shape[2], axis=2) amps = np.abs(fft_input) phases = np.angle(fft_input) pert_corrs = [0] * n_layers for i in range(n_iterations): log.info("Iteration {:d}...".format(i)) log.info("Sample perturbation...") amps_pert, phases_pert, pert_vals = pert_fn(amps, phases, rng=rng) # Compute perturbed inputs log.info("Compute perturbed complex inputs...") fft_pert = amps_pert * np.exp(1j * phases_pert) log.info("Compute perturbed real inputs...") inputs_pert = np.fft.irfft(fft_pert, n=inputs.shape[2], axis=2).astype(np.float32) # Calculate layer activations for perturbed inputs log.info("Compute new predictions...") new_preds = [pred_fn(inputs_pert[inds]) for inds in batch_inds] new_preds_layers = [ np.concatenate([new_preds[o][l] for o in range(len(new_preds)) ]).reshape(use_shape[l]) for l in range(n_layers) ] for l in range(n_layers): log.info("Layer {:d}...".format(l)) # Calculate difference of original and perturbed feature map activations log.info("Compute activation difference...") preds_diff = diff_fn(new_preds_layers[l][:, :, :, 0], orig_preds_layers[l][:, :, :, 0]) # Calculate feature map differences with perturbations log.info("Compute correlation...") pert_corrs_tmp = wrap_reshape_apply_fn(corr, pert_vals[:, :, :, 0], preds_diff, axis_a=(0, ), axis_b=(0)) pert_corrs[l] += pert_corrs_tmp pert_corrs = [pert_corrs[l] / n_iterations for l in range(n_layers)] #mean over iterations return pert_corrs
def test_trialwise_decoding(): import mne from mne.io import concatenate_raws # 5,6,7,10,13,14 are codes for executed and imagined hands/feet subject_id = 1 event_codes = [5, 6, 9, 10, 13, 14] # This will download the files if you don't have them yet, # and then return the paths to the files. physionet_paths = mne.datasets.eegbci.load_data(subject_id, event_codes) # Load each of the files parts = [ mne.io.read_raw_edf(path, preload=True, stim_channel='auto', verbose='WARNING') for path in physionet_paths ] # Concatenate them raw = concatenate_raws(parts) # Find the events in this dataset events = mne.find_events(raw, shortest_event=0, stim_channel='STI 014') # Use only EEG channels eeg_channel_inds = mne.pick_types(raw.info, meg=False, eeg=True, stim=False, eog=False, exclude='bads') # Extract trials, only using EEG channels epoched = mne.Epochs(raw, events, dict(hands=2, feet=3), tmin=1, tmax=4.1, proj=False, picks=eeg_channel_inds, baseline=None, preload=True) import numpy as np # Convert data from volt to millivolt # Pytorch expects float32 for input and int64 for labels. X = (epoched.get_data() * 1e6).astype(np.float32) y = (epoched.events[:, 2] - 2).astype(np.int64) # 2,3 -> 0,1 from braindecode.datautil.signal_target import SignalAndTarget train_set = SignalAndTarget(X[:60], y=y[:60]) test_set = SignalAndTarget(X[60:], y=y[60:]) from braindecode.models.shallow_fbcsp import ShallowFBCSPNet from torch import nn from braindecode.torch_ext.util import set_random_seeds # Set if you want to use GPU # You can also use torch.cuda.is_available() to determine if cuda is available on your machine. cuda = False set_random_seeds(seed=20170629, cuda=cuda) n_classes = 2 in_chans = train_set.X.shape[1] # final_conv_length = auto ensures we only get a single output in the time dimension model = ShallowFBCSPNet(in_chans=in_chans, n_classes=n_classes, input_time_length=train_set.X.shape[2], final_conv_length='auto').create_network() if cuda: model.cuda() from torch import optim optimizer = optim.Adam(model.parameters()) from braindecode.torch_ext.util import np_to_var, var_to_np from braindecode.datautil.iterators import get_balanced_batches import torch.nn.functional as F from numpy.random import RandomState rng = RandomState((2017, 6, 30)) losses = [] accuracies = [] for i_epoch in range(6): i_trials_in_batch = get_balanced_batches(len(train_set.X), rng, shuffle=True, batch_size=30) # Set model to training mode model.train() for i_trials in i_trials_in_batch: # Have to add empty fourth dimension to X batch_X = train_set.X[i_trials][:, :, :, None] batch_y = train_set.y[i_trials] net_in = np_to_var(batch_X) if cuda: net_in = net_in.cuda() net_target = np_to_var(batch_y) if cuda: net_target = net_target.cuda() # Remove gradients of last backward pass from all parameters optimizer.zero_grad() # Compute outputs of the network outputs = model(net_in) # Compute the loss loss = F.nll_loss(outputs, net_target) # Do the backpropagation loss.backward() # Update parameters with the optimizer optimizer.step() # Print some statistics each epoch model.eval() print("Epoch {:d}".format(i_epoch)) for setname, dataset in (('Train', train_set), ('Test', test_set)): # Here, we will use the entire dataset at once, which is still possible # for such smaller datasets. Otherwise we would have to use batches. net_in = np_to_var(dataset.X[:, :, :, None]) if cuda: net_in = net_in.cuda() net_target = np_to_var(dataset.y) if cuda: net_target = net_target.cuda() outputs = model(net_in) loss = F.nll_loss(outputs, net_target) losses.append(float(var_to_np(loss))) print("{:6s} Loss: {:.5f}".format(setname, float(var_to_np(loss)))) predicted_labels = np.argmax(var_to_np(outputs), axis=1) accuracy = np.mean(dataset.y == predicted_labels) accuracies.append(accuracy * 100) print("{:6s} Accuracy: {:.1f}%".format(setname, accuracy * 100)) np.testing.assert_allclose(np.array(losses), np.array([ 1.1775966882705688, 1.2602351903915405, 0.7068756818771362, 0.9367912411689758, 0.394258975982666, 0.6598362326622009, 0.3359280526638031, 0.656258761882782, 0.2790488004684448, 0.6104397177696228, 0.27319177985191345, 0.5949864983558655 ]), rtol=1e-4, atol=1e-5) np.testing.assert_allclose(np.array(accuracies), np.array([ 51.666666666666671, 53.333333333333336, 63.333333333333329, 56.666666666666664, 86.666666666666671, 66.666666666666657, 90.0, 63.333333333333329, 96.666666666666671, 56.666666666666664, 96.666666666666671, 66.666666666666657 ]), rtol=1e-4, atol=1e-5)
def load_train_valid_test(train_filename, test_filename, n_folds, i_test_fold, valid_set_fraction, use_validation_set, low_cut_hz, debug=False): # we loaded all sensors to always get same cleaning results independent of sensor selection # There is an inbuilt heuristic that tries to use only EEG channels and that definitely # works for datasets in our paper if test_filename is None: assert n_folds is not None assert i_test_fold is not None assert valid_set_fraction is None else: assert n_folds is None assert i_test_fold is None assert use_validation_set == (valid_set_fraction is not None) train_folder = '/home/schirrmr/data/BBCI-without-last-runs/' log.info("Loading train...") full_train_set = load_bbci_data(os.path.join(train_folder, train_filename), low_cut_hz=low_cut_hz, debug=debug) if test_filename is not None: test_folder = '/home/schirrmr/data/BBCI-only-last-runs/' log.info("Loading test...") test_set = load_bbci_data(os.path.join(test_folder, test_filename), low_cut_hz=low_cut_hz, debug=debug) if use_validation_set: assert valid_set_fraction is not None train_set, valid_set = split_into_two_sets(full_train_set, valid_set_fraction) else: train_set = full_train_set valid_set = None # Split data if n_folds is not None: fold_inds = get_balanced_batches(len(full_train_set.X), None, shuffle=False, n_batches=n_folds) fold_sets = [ select_examples(full_train_set, inds) for inds in fold_inds ] test_set = fold_sets[i_test_fold] train_folds = np.arange(n_folds) train_folds = np.setdiff1d(train_folds, [i_test_fold]) if use_validation_set: i_valid_fold = (i_test_fold - 1) % n_folds train_folds = np.setdiff1d(train_folds, [i_valid_fold]) valid_set = fold_sets[i_valid_fold] assert i_valid_fold not in train_folds assert i_test_fold != i_valid_fold else: valid_set = None assert i_test_fold not in train_folds train_fold_sets = [fold_sets[i] for i in train_folds] train_set = concatenate_sets(train_fold_sets) # Some checks if valid_set is None: assert len(train_set.X) + len(test_set.X) == len(full_train_set.X) else: assert len(train_set.X) + len(valid_set.X) + len( test_set.X) == len(full_train_set.X) log.info("Train set with {:4d} trials".format(len(train_set.X))) if valid_set is not None: log.info("Valid set with {:4d} trials".format(len(valid_set.X))) log.info("Test set with {:4d} trials".format(len(test_set.X))) return train_set, valid_set, test_set
model.cuda() from torch import optim optimizer = optim.Adam(model.parameters()) # Training loop from braindecode.torch_ext.util import np_to_var, var_to_np from braindecode.datautil.iterators import get_balanced_batches import torch.nn.functional as F from numpy.random import RandomState rng = RandomState((2017, 6, 30)) for i_epoch in range(30): i_trials_in_batch = get_balanced_batches(len(train_set.X), rng, shuffle=True, batch_size=30) # Set model to training mode model.train() for i_trials in i_trials_in_batch: # Have to add empty fourth dimension to X batch_X = train_set.X[i_trials][:, :, :, None] batch_y = train_set.y[i_trials] net_in = np_to_var(batch_X) if cuda: net_in = net_in.cuda() net_target = np_to_var(batch_y) if cuda: net_target = net_target.cuda() # Remove gradients of last backward pass from all parameters optimizer.zero_grad()