def load_train_test_hgd(subject_id): hgd_names = [ 'Fp2', 'Fp1', 'F4', 'F3', 'C4', 'C3', 'P4', 'P3', 'O2', 'O1', 'F8', 'F7', 'T8', 'T7', 'P8', 'P7', 'M2', 'M1', 'Fz', 'Cz', 'Pz' ] log.info("Loading dataset..") # using the moabb dataset to load our data dataset = MOABBDataset(dataset_name="Schirrmeister2017", subject_ids=[subject_id]) sfreq = 32 train_whole_set = dataset.split('run')['train'] log.info("Preprocessing dataset..") # Define preprocessing steps preprocessors = [ # convert from volt to microvolt, directly modifying the numpy array MNEPreproc( fn='set_eeg_reference', ref_channels='average', ), MNEPreproc(fn='pick_channels', ch_names=hgd_names, ordered=True), NumpyPreproc(fn=lambda x: x * 1e6), NumpyPreproc(fn=lambda x: np.clip(x, -800, 800)), NumpyPreproc(fn=lambda x: x / 10), MNEPreproc(fn='resample', sfreq=sfreq), NumpyPreproc(fn=lambda x: np.clip(x, -80, 80)), NumpyPreproc(fn=lambda x: x / 3), NumpyPreproc(fn=exponential_moving_demean, init_block_size=int(sfreq * 10), factor_new=1 / (sfreq * 5)), # keep only EEG sensors # NumpyPreproc(fn=exponential_moving_demean, init_block_size=sfreq*10, factor_new=1/(sfreq*5)), ] # Preprocess the data preprocess(train_whole_set, preprocessors) # Next, extract the 4-second trials from the dataset. # Create windows using braindecode function for this. It needs parameters to define how # trials should be used. class_names = ['Right Hand', 'Rest'] # for later plotting class_mapping = {'right_hand': 0, 'rest': 1} windows_dataset = create_windows_from_events( train_whole_set, trial_start_offset_samples=0, trial_stop_offset_samples=0, preload=True, mapping=class_mapping, ) from torch.utils.data import Subset n_split = int(np.round(0.75 * len(windows_dataset))) valid_set = Subset(windows_dataset, range(n_split, len(windows_dataset))) train_set = Subset(windows_dataset, range(0, n_split)) return train_set, valid_set
def bcic4_2a(subject, low_hz=None, high_hz=None, paradigm=None, phase=False): X = [] y = [] if isinstance(subject, int): subject = [subject] for subject_id in subject: # Load data print_off() dataset = MOABBDataset(dataset_name="BNCI2014001", subject_ids=[subject_id]) # Preprocess factor_new = 1e-3 init_block_size = 1000 preprocessors = [ # keep only EEG sensors MNEPreproc(fn='pick_types', eeg=True, meg=False, stim=False), # convert from volt to microvolt NumpyPreproc(fn=lambda x: x * 1e+06), # bandpass filter MNEPreproc(fn='filter', l_freq=low_hz, h_freq=high_hz), # exponential moving standardization NumpyPreproc(fn=exponential_moving_standardize, factor_new=factor_new, init_block_size=init_block_size) ] preprocess(dataset, preprocessors) # Divide data by trial # - Check sampling frequency sfreq = dataset.datasets[0].raw.info['sfreq'] assert all([ds.raw.info['sfreq'] == sfreq for ds in dataset.datasets]) trial_start_offset_seconds = -0.5 trial_start_offset_samples = int(trial_start_offset_seconds * sfreq) windows_dataset = create_windows_from_events( dataset, trial_start_offset_samples=trial_start_offset_samples, trial_stop_offset_samples=0, preload=True # verbose=True ) # If you need split data, try this. if paradigm == 'session': if phase == "train": windows_dataset = windows_dataset.split('session')['session_T'] else: windows_dataset = windows_dataset.split('session')['session_E'] # Merge subject for trial in windows_dataset: X.append(trial[0]) y.append(trial[1]) print_on() return np.array(X), np.array(y)
def feature_extract(subjects, windowsize, aug_factor, aug_noise_factor, trunc_start=0, trunc_stop=-1): dataset = MOABBDataset(dataset_name="BNCI2014001", subject_ids=subjects) our_preprocess(dataset) trial_start_offset_seconds = -0.5 # Extract sampling frequency, check that they are same in all datasets sfreq = dataset.datasets[0].raw.info['sfreq'] assert all([ds.raw.info['sfreq'] == sfreq for ds in dataset.datasets]) # Calculate the trial start offset in samples. trial_start_offset_samples = int(trial_start_offset_seconds * sfreq) # Create windows using braindecode function for this. It needs parameters to define how # trials should be used. windows_dataset = create_windows_from_events( dataset, trial_start_offset_samples=trial_start_offset_samples, trial_stop_offset_samples=0, preload=True ) #Get the actual Data data = [] labels = [] for d, l, g in windows_dataset: data.append(d) labels.append(l) data = np.array(data) labels = np.array(labels) X_train, X_val, y_train, y_val = train_test_split(data, labels, test_size=0.4, random_state=1) X_val, X_test, y_val, y_test = train_test_split(X_val, y_val, test_size=0.5, random_state=1) X_train, y_train = add_noise(X_train, y_train, aug_factor, aug_noise_factor) #roll_data(X_train, 0.5, windowsize, 0.3) X_train = overlap_window(X_train, windowsize, windowsize//2, 2) # trial x channel x window x sample X_train = extract_features(X_train) #final shape trials x Channels x Feature x Window X_val = overlap_window(X_val, windowsize, windowsize//2, 2) # trial x channel x window x sample X_val = extract_features(X_val) #final shape trials x Channels x Feature x Window X_test = overlap_window(X_test, windowsize, windowsize//2, 2) # trial x channel x window x sample X_test = extract_features(X_test) #final shape trials x Channels x Feature x Window return X_train[..., trunc_start:trunc_stop], y_train, X_val[..., trunc_start:trunc_stop], y_val, X_test[..., trunc_start:trunc_stop], y_test
""" # Authors: Lukas Gemein <*****@*****.**> # # License: BSD (3-clause) from braindecode.datasets.moabb import MOABBDataset from braindecode.datautil.preprocess import preprocess, MNEPreproc from braindecode.datautil.serialization import load_concat_dataset from braindecode.datautil.windowers import create_windows_from_events ############################################################################### # First, we load some dataset using MOABB. ds = MOABBDataset( dataset_name='BNCI2014001', subject_ids=[1], ) ############################################################################### # We can apply preprocessing steps to the dataset. It is also possible to skip # this step and not apply any preprocessing. preprocess( concat_ds=ds, preprocessors=[MNEPreproc(fn='resample', sfreq=10)] ) ############################################################################### # We save the dataset to a an existing directory. It will create a '.fif' file # for every dataset in the concat dataset. Additionally it will create two # JSON files, the first holding the description of the dataset, the second # holding the name of the target. If you want to store to the same directory
def train(subject_id): print('\n--------------------------------------------------\n') print( 'Training on BCI_IV_2a dataset | Cross-subject | ID: {:02d}\n'.format( subject_id)) ##### subject_range = [subject_id] subject_range = [x for x in range(1, 10)] dataset = MOABBDataset(dataset_name="BNCI2014001", subject_ids=subject_range) ###################################################################### # Preprocessing low_cut_hz = 4. # low cut frequency for filtering high_cut_hz = 38. # high cut frequency for filtering # Parameters for exponential moving standardization factor_new = 1e-3 init_block_size = 1000 preprocessors = [ Preprocessor('pick_types', eeg=True, eog=False, meg=False, stim=False), # Keep EEG sensors Preprocessor(lambda x: x * 1e6), # Convert from V to uV Preprocessor('filter', l_freq=low_cut_hz, h_freq=high_cut_hz), # Bandpass filter #Preprocessor('set_eeg_reference', ref_channels='average', ch_type='eeg'), Preprocessor('resample', sfreq=125), Preprocessor(covariance_align), ## Preprocessor(exponential_moving_standardize, # Exponential moving standardization ## factor_new=factor_new, init_block_size=init_block_size) ## Preprocessor('pick_channels', ch_names=short_ch_names, ordered=True), ] # Transform the data print('Preprocessing dataset\n') preprocess(dataset, preprocessors) ###################################################################### # Cut Compute Windows # ~~~~~~~~~~~~~~~~~~~ trial_start_offset_seconds = -0.5 trial_stop_offset_seconds = 0.0 # Extract sampling frequency, check that they are same in all datasets sfreq = dataset.datasets[0].raw.info['sfreq'] assert all([ds.raw.info['sfreq'] == sfreq for ds in dataset.datasets]) # Calculate the trial start offset in samples. trial_start_offset_samples = int(trial_start_offset_seconds * sfreq) trial_stop_offset_samples = int(trial_stop_offset_seconds * sfreq) # Create windows using braindecode function for this. It needs parameters to define how # trials should be used. print('Windowing dataset\n') windows_dataset = create_windows_from_events( dataset, # picks=["Fz", "FC3", "FC1", "FCz", "FC2", "FC4", "C5", "C3", "C1", "Cz", "C2", "C4", "C6", "CP3", "CP1", "CPz", "CP2", "CP4", "P1", "Pz", "P2", "POz"], trial_start_offset_samples=trial_start_offset_samples, trial_stop_offset_samples=trial_stop_offset_samples, preload=True, ) print('Computing covariances of each WindowsDataset') windows_dataset.compute_covariances_concat() # print(windows_dataset.datasets[0].windows) ###################################################################### # Merge multiple datasets into a single WindowDataset # metadata_all = [ds.windows.metadata for ds in windows_dataset.datasets] # metadata_full = pd.concat(metadata_all) """ epochs_all = [ds.windows for ds in windows_dataset.datasets] epochs_full = mne.concatenate_epochs(epochs_all) full_dataset = WindowsDataset(windows=epochs_full, description=None, transform=None) windows_dataset = full_dataset """ ###################################################################### # Split dataset into train and valid # keep only session 1: # temp = windows_dataset.split( 'session' ) # windows_dataset = temp['session_T'] # print(windows_dataset.datasets[0].windows) # print(windows_dataset.datasets[0].windows.get_data().shape) # quit() subject_column = windows_dataset.description['subject'].values inds_train = list(np.where(subject_column != subject_id)[0]) inds_valid = list(np.where(subject_column == subject_id)[0]) splitted = windows_dataset.split([inds_train, inds_valid]) train_set = splitted['0'] valid_set = splitted['1'] ####### epochs_all = [ds.windows for ds in train_set.datasets] epochs_full = mne.concatenate_epochs(epochs_all) trialwise_weights_all = [ds.trialwise_weights for ds in train_set.datasets] trialwise_weights_full = np.hstack(trialwise_weights_all) full_dataset = WindowsDataset(windows=epochs_full, description=None, transform=None) full_dataset.trialwise_weights = trialwise_weights_full train_set = full_dataset # print(train_set.windows.metadata) ###################################################################### # Create model cuda = torch.cuda.is_available( ) # check if GPU is available, if True chooses to use it device = 'cuda' if cuda else 'cpu' if cuda: torch.backends.cudnn.benchmark = True seed = 20200220 # random seed to make results reproducible # Set random seed to be able to reproduce results set_random_seeds(seed=seed, cuda=cuda) n_classes = 4 # Extract number of chans and time steps from dataset n_chans = train_set[0][0].shape[0] input_window_samples = train_set[0][0].shape[1] """ model = ShallowFBCSPNet( n_chans, n_classes, input_window_samples=input_window_samples, final_conv_length='auto') """ """ model = EEGNetv1( n_chans, n_classes, input_window_samples=input_window_samples, final_conv_length="auto", pool_mode="mean", second_kernel_size=(2, 32), third_kernel_size=(8, 4), drop_prob=0.25) """ """ model = HybridNet(n_chans, n_classes, input_window_samples=input_window_samples) """ """ model = TCN(n_chans, n_classes, n_blocks=6, n_filters=32, kernel_size=9, drop_prob=0.0, add_log_softmax=True) """ model = EEGNetv4( n_chans, n_classes, input_window_samples=input_window_samples, final_conv_length="auto", pool_mode="mean", F1=8, D=2, F2=16, # usually set to F1*D (?) kernel_length=64, third_kernel_size=(8, 4), drop_prob=0.2) if cuda: model.cuda() ###################################################################### # Training # These values we found good for shallow network: lr = 0.01 # 0.0625 * 0.01 weight_decay = 0.0005 # For deep4 they should be: # lr = 1 * 0.01 # weight_decay = 0.5 * 0.001 batch_size = 64 n_epochs = 100 # clf = EEGClassifier( clf = EEGClassifier_weighted( model, criterion=torch.nn.NLLLoss, optimizer=torch.optim.SGD, #AdamW, train_split=predefined_split( valid_set), # using valid_set for validation optimizer__lr=lr, optimizer__momentum=0.9, optimizer__weight_decay=weight_decay, batch_size=batch_size, callbacks=[ "accuracy", #("lr_scheduler", LRScheduler('CosineAnnealingLR', T_max=n_epochs - 1)), ], device=device, ) # Model training for a specified number of epochs. `y` is None as it is already supplied # in the dataset. clf.fit(train_set, y=None, epochs=n_epochs) results_columns = [ 'train_loss', 'valid_loss', 'train_accuracy', 'valid_accuracy' ] df = pd.DataFrame(clf.history[:, results_columns], columns=results_columns, index=clf.history[:, 'epoch']) val_accs = df['valid_accuracy'].values max_val_acc = 100.0 * np.max(val_accs) return max_val_acc
def setup_concat_raw_dataset(): return MOABBDataset(dataset_name="BNCI2014001", subject_ids=[1])
# braindecode to load datasets through # `MOABB <https://github.com/NeuroTechX/moabb>`__ to load the BCI # Competition IV 2a data. # # .. note:: # To load your own datasets either via mne or from # preprocessed X/y numpy arrays, see `MNE Dataset # Tutorial <./plot_mne_dataset_example.html>`__ and `Numpy Dataset # Tutorial <./plot_custom_dataset_example.html>`__. # from braindecode.datasets.moabb import MOABBDataset import mne import torch dataset = MOABBDataset(dataset_name="BNCI2014001", subject_ids=list(range(1, 10))) # subject_id = 3 ###################################################################### # Preprocessing # ~~~~~~~~~~~~~ # ###################################################################### # Now we apply preprocessing like bandpass filtering to our dataset. You # can either apply functions provided by # `mne.Raw <https://mne.tools/stable/generated/mne.io.Raw.html>`__ or # `mne.Epochs <https://mne.tools/0.11/generated/mne.Epochs.html#mne.Epochs>`__ # or apply your own functions, either to the MNE object or the underlying # numpy array. #
# braindecode to load datasets through # `MOABB <https://github.com/NeuroTechX/moabb>`__ to load the BCI # Competition IV 2a data. # # .. note:: # To load your own datasets either via mne or from # preprocessed X/y numpy arrays, see `MNE Dataset # Tutorial <./plot_mne_dataset_example.html>`__ and `Numpy Dataset # Tutorial <./plot_custom_dataset_example.html>`__. # from braindecode.datasets.moabb import MOABBDataset import mne subject_id = 3 dataset = MOABBDataset(dataset_name="BNCI2014001", subject_ids=[subject_id]) ###################################################################### # Preprocessing # ~~~~~~~~~~~~~ # ###################################################################### # Now we apply preprocessing like bandpass filtering to our dataset. You # can either apply functions provided by # `mne.Raw <https://mne.tools/stable/generated/mne.io.Raw.html>`__ or # `mne.Epochs <https://mne.tools/0.11/generated/mne.Epochs.html#mne.Epochs>`__ # or apply your own functions, either to the MNE object or the underlying # numpy array. # # .. note::
# Authors: Lukas Gemein <*****@*****.**> # # License: BSD (3-clause) import tempfile from braindecode.datasets.moabb import MOABBDataset from braindecode.preprocessing.preprocess import preprocess, MNEPreproc from braindecode.datautil.serialization import load_concat_dataset from braindecode.preprocessing.windowers import create_windows_from_events ############################################################################### # First, we load some dataset using MOABB. dataset = MOABBDataset( dataset_name='BNCI2014001', subject_ids=[1], ) ############################################################################### # We can apply preprocessing steps to the dataset. It is also possible to skip # this step and not apply any preprocessing. preprocess( concat_ds=dataset, preprocessors=[MNEPreproc(fn='resample', sfreq=10)] ) ############################################################################### # We save the dataset to a an existing directory. It will create a '.fif' file # for every dataset in the concat dataset. Additionally it will create two # JSON files, the first holding the description of the dataset, the second # holding the name of the target. If you want to store to the same directory
# braindecode to load datasets through # `MOABB <https://github.com/NeuroTechX/moabb>`__ to load the BCI # Competition IV 2a data. # # .. note:: # To load your own datasets either via mne or from # preprocessed X/y numpy arrays, see `MNE Dataset # Tutorial <./plot_mne_dataset_example.html>`__ and `Numpy Dataset # Tutorial <./plot_custom_dataset_example.html>`__. # from braindecode.datasets.moabb import MOABBDataset subject_id = list(range(1,70))#[3,4,5,6] # events=dict(left_hand=2, right_hand=3, feet=5, hands=4, rest=1) dataset = MOABBDataset(dataset_name="PhysionetMI", subject_ids=subject_id) ###################################################################### # Preprocessing # ~~~~~~~~~~~~~ # ###################################################################### # Now we apply preprocessing like bandpass filtering to our dataset. You # can either apply functions provided by # `mne.Raw <https://mne.tools/stable/generated/mne.io.Raw.html>`__ or # `mne.Epochs <https://mne.tools/0.11/generated/mne.Epochs.html#mne.Epochs>`__ # or apply your own functions, either to the MNE object or the underlying # numpy array.
def exp(subject_id): dataset = MOABBDataset(dataset_name="BNCI2014001", subject_ids=subject_id) from braindecode.datautil.preprocess import exponential_moving_standardize from braindecode.datautil.preprocess import MNEPreproc, NumpyPreproc, preprocess low_cut_hz = 0. # low cut frequency for filtering high_cut_hz = 49. # high cut frequency for filtering # Parameters for exponential moving standardization factor_new = 1e-3 init_block_size = 1000 preprocessors = [ # keep only EEG sensors MNEPreproc(fn='pick_types', eeg=True, meg=False, stim=False), # convert from volt to microvolt, directly modifying the numpy array NumpyPreproc(fn=lambda x: x * 1e6), # bandpass filter MNEPreproc(fn='filter', l_freq=low_cut_hz, h_freq=high_cut_hz), # exponential moving standardization # NumpyPreproc(fn=exponential_moving_standardize, factor_new=factor_new, # init_block_size=init_block_size) ] # Transform the data preprocess(dataset, preprocessors) ###################################################################### # Create model and compute windowing parameters # --------------------------------------------- # ###################################################################### # In contrast to trialwise decoding, we first have to create the model # before we can cut the dataset into windows. This is because we need to # know the receptive field of the network to know how large the window # stride should be. # ###################################################################### # We first choose the compute/input window size that will be fed to the # network during training This has to be larger than the networks # receptive field size and can otherwise be chosen for computational # efficiency (see explanations in the beginning of this tutorial). Here we # choose 1000 samples, which are 4 seconds for the 250 Hz sampling rate. # input_window_samples = 1000 ###################################################################### # Now we create the model. To enable it to be used in cropped decoding # efficiently, we manually set the length of the final convolution layer # to some length that makes the receptive field of the ConvNet smaller # than ``input_window_samples`` (see ``final_conv_length=30`` in the model # definition). # import torch from braindecode.util import set_random_seeds from braindecode.models import ShallowFBCSPNet, Deep4Net cuda = torch.cuda.is_available( ) # check if GPU is available, if True chooses to use it device = 'cuda:1' if cuda else 'cpu' if cuda: torch.backends.cudnn.benchmark = True seed = 20190706 # random seed to make results reproducible # Set random seed to be able to reproduce results set_random_seeds(seed=seed, cuda=cuda) n_classes = 4 # Extract number of chans from dataset n_chans = dataset[0][0].shape[0] # model = Deep4Net( # n_chans, # n_classes, # input_window_samples=input_window_samples, # final_conv_length="auto", # ) # # # # embedding_net = Deep4Net_origin(4, 22, input_window_samples) # model = FcClfNet(embedding_net) model = ShallowFBCSPNet( n_chans, n_classes, input_window_samples=input_window_samples, final_conv_length=30, ) print(model) # Send model to GPU if cuda: model.cuda(device) ###################################################################### # And now we transform model with strides to a model that outputs dense # prediction, so we can use it to obtain predictions for all # crops. # from braindecode.models.util import to_dense_prediction_model, get_output_shape to_dense_prediction_model(model) n_preds_per_input = get_output_shape(model, n_chans, input_window_samples)[2] print("n_preds_per_input : ", n_preds_per_input) print(model) ###################################################################### # Cut the data into windows # ------------------------- # ###################################################################### # In contrast to trialwise decoding, we have to supply an explicit window size and window stride to the # ``create_windows_from_events`` function. # import numpy as np from braindecode.datautil.windowers import create_windows_from_events trial_start_offset_seconds = -0.5 # Extract sampling frequency, check that they are same in all datasets sfreq = dataset.datasets[0].raw.info['sfreq'] assert all([ds.raw.info['sfreq'] == sfreq for ds in dataset.datasets]) # Calculate the trial start offset in samples. trial_start_offset_samples = int(trial_start_offset_seconds * sfreq) # Create windows using braindecode function for this. It needs parameters to define how # trials should be used. windows_dataset = create_windows_from_events( dataset, trial_start_offset_samples=trial_start_offset_samples, trial_stop_offset_samples=0, window_size_samples=input_window_samples, window_stride_samples=n_preds_per_input, drop_last_window=False, preload=True, ) ###################################################################### # Split the dataset # ----------------- # # This code is the same as in trialwise decoding. # from braindecode.datasets.base import BaseConcatDataset splitted = windows_dataset.split('session') train_set = splitted['session_T'] valid_set = splitted['session_E'] lr = 0.0625 * 0.01 weight_decay = 0 batch_size = 8 n_epochs = 100 train_loader = torch.utils.data.DataLoader(train_set, batch_size=batch_size, shuffle=True) # valid_loader = torch.utils.data.DataLoader(valid_set, batch_size=batch_size, shuffle=False) test_loader = torch.utils.data.DataLoader(valid_set, batch_size=batch_size, shuffle=False) # Send model to GPU if cuda: model.cuda(device) from torch.optim import lr_scheduler import torch.optim as optim import argparse parser = argparse.ArgumentParser( description='cross subject domain adaptation') parser.add_argument('--batch-size', type=int, default=50, metavar='N', help='input batch size for training (default: 64)') parser.add_argument('--test-batch-size', type=int, default=50, metavar='N', help='input batch size for testing (default: 1000)') parser.add_argument('--epochs', type=int, default=100, metavar='N', help='number of epochs to train (default: 10)') parser.add_argument('--lr', type=float, default=0.001, metavar='LR', help='learning rate (default: 0.01)') parser.add_argument('--momentum', type=float, default=0.5, metavar='M', help='SGD momentum (default: 0.5)') parser.add_argument('--no-cuda', action='store_true', default=False, help='disables CUDA training') parser.add_argument( '--log-interval', type=int, default=10, metavar='N', help='how many batches to wait before logging training status') parser.add_argument('--save-model', action='store_true', default=True, help='For Saving the current Model') args = parser.parse_args() args.gpuidx = 0 args.seed = 0 args.use_tensorboard = False args.save_model = False optimizer = optim.AdamW(model.parameters(), lr=lr, weight_decay=weight_decay) # scheduler = lr_scheduler.CosineAnnealingWarmRestarts(optimizer, T_0=10, T_mult=1) scheduler = lr_scheduler.CosineAnnealingLR(optimizer, T_max=n_epochs - 1) import pandas as pd results_columns = ['test_loss', 'test_accuracy'] df = pd.DataFrame(columns=results_columns) for epochidx in range(1, n_epochs): print(epochidx) train_crop(10, model, device, train_loader, optimizer, scheduler, cuda, args.gpuidx) test_loss, test_score = eval_crop(model, device, test_loader) results = {'test_loss': test_loss, 'test_accuracy': test_score} df = df.append(results, ignore_index=True) print(results) return df
def test_predict_trials(): ds = MOABBDataset('BNCI2014001', subject_ids=1) ds1 = ds.split([0])['0'] # determine original trial size windows_ds1 = create_windows_from_events( ds1, ) trial_size = windows_ds1[0][0].shape[1] # create two windows per trial, where windows maximally overlap window_size_samples = trial_size - 1 window_stride_samples = 5 windows_ds1 = create_windows_from_events( ds1, window_size_samples=window_size_samples, window_stride_samples=window_stride_samples, drop_last_window=False, ) in_chans = windows_ds1[0][0].shape[0] n_classes = len(windows_ds1.get_metadata()['target'].unique()) model = ShallowFBCSPNet( in_chans=in_chans, n_classes=n_classes, ) to_dense_prediction_model(model) output_shape = get_output_shape(model, in_chans, window_size_samples) # the number of samples required to get 1 output receptive_field_size = window_size_samples - output_shape[-1] + 1 preds, targets = predict_trials(model, windows_ds1) # some model, cropped data assert preds.shape[-1] + receptive_field_size - 1 == trial_size assert preds.shape[1] == n_classes assert preds.shape[0] == targets.shape[0] metadata = windows_ds1.get_metadata() expected_targets = metadata[metadata['i_window_in_trial'] == 0][ 'target'].values np.testing.assert_array_equal(expected_targets, targets) # some model, trialwise data windows_ds2 = create_windows_from_events(ds1) with pytest.warns(UserWarning, match='This function was designed to predict' ' trials from cropped datasets.'): predict_trials(model, windows_ds2) # cropped EEGClassifier, cropped data clf = EEGClassifier( model, criterion=torch.nn.NLLLoss, optimizer=optim.AdamW, train_split=None, optimizer__lr=0.0625 * 0.01, optimizer__weight_decay=0, batch_size=64, ) clf.initialize() clf.predict_trials(windows_ds1, return_targets=True) # cropped EEGClassifier, trialwise data with pytest.warns(UserWarning, match="This method was designed to predict " "trials in cropped mode. Calling it " "when cropped is False will give the " "same result as '.predict'."): clf.predict_trials(windows_ds2)
def exp(subject_id): dataset = MOABBDataset(dataset_name="BNCI2014001", subject_ids=subject_id) from braindecode.datautil.preprocess import exponential_moving_standardize from braindecode.datautil.preprocess import MNEPreproc, NumpyPreproc, preprocess low_cut_hz = 0. # low cut frequency for filtering high_cut_hz = 38. # high cut frequency for filtering # Parameters for exponential moving standardization factor_new = 1e-3 init_block_size = 1000 preprocessors = [ # keep only EEG sensors MNEPreproc(fn='pick_types', eeg=True, meg=False, stim=False), # convert from volt to microvolt, directly modifying the numpy array NumpyPreproc(fn=lambda x: x * 1e6), # bandpass filter MNEPreproc(fn='filter', l_freq=low_cut_hz, h_freq=high_cut_hz), # exponential moving standardization # NumpyPreproc(fn=exponential_moving_standardize, factor_new=factor_new, # init_block_size=init_block_size) ] # Transform the data preprocess(dataset, preprocessors) ###################################################################### # Create model and compute windowing parameters # --------------------------------------------- # ###################################################################### # In contrast to trialwise decoding, we first have to create the model # before we can cut the dataset into windows. This is because we need to # know the receptive field of the network to know how large the window # stride should be. # ###################################################################### # We first choose the compute/input window size that will be fed to the # network during training This has to be larger than the networks # receptive field size and can otherwise be chosen for computational # efficiency (see explanations in the beginning of this tutorial). Here we # choose 1000 samples, which are 4 seconds for the 250 Hz sampling rate. # input_window_samples = 1000 ###################################################################### # Now we create the model. To enable it to be used in cropped decoding # efficiently, we manually set the length of the final convolution layer # to some length that makes the receptive field of the ConvNet smaller # than ``input_window_samples`` (see ``final_conv_length=30`` in the model # definition). # import torch from braindecode.util import set_random_seeds from braindecode.models import ShallowFBCSPNet, Deep4Net cuda = torch.cuda.is_available( ) # check if GPU is available, if True chooses to use it device = 'cuda:1' if cuda else 'cpu' if cuda: torch.backends.cudnn.benchmark = True seed = 20190706 # random seed to make results reproducible # Set random seed to be able to reproduce results set_random_seeds(seed=seed, cuda=cuda) n_classes = 4 # Extract number of chans from dataset n_chans = dataset[0][0].shape[0] # model = Deep4Net( # n_chans, # n_classes, # input_window_samples=input_window_samples, # final_conv_length="auto", # ) # # # # embedding_net = Deep4Net_origin(4, 22, input_window_samples) # model = FcClfNet(embedding_net) model = ShallowFBCSPNet( n_chans, n_classes, input_window_samples=input_window_samples, final_conv_length=30, ) print(model) # Send model to GPU if cuda: model.cuda(device) ###################################################################### # And now we transform model with strides to a model that outputs dense # prediction, so we can use it to obtain predictions for all # crops. # from braindecode.models.util import to_dense_prediction_model, get_output_shape to_dense_prediction_model(model) n_preds_per_input = get_output_shape(model, n_chans, input_window_samples)[2] print("n_preds_per_input : ", n_preds_per_input) print(model) ###################################################################### # Cut the data into windows # ------------------------- # ###################################################################### # In contrast to trialwise decoding, we have to supply an explicit window size and window stride to the # ``create_windows_from_events`` function. # import numpy as np from braindecode.datautil.windowers import create_windows_from_events trial_start_offset_seconds = -0.5 # Extract sampling frequency, check that they are same in all datasets sfreq = dataset.datasets[0].raw.info['sfreq'] assert all([ds.raw.info['sfreq'] == sfreq for ds in dataset.datasets]) # Calculate the trial start offset in samples. trial_start_offset_samples = int(trial_start_offset_seconds * sfreq) # Create windows using braindecode function for this. It needs parameters to define how # trials should be used. windows_dataset = create_windows_from_events( dataset, trial_start_offset_samples=trial_start_offset_samples, trial_stop_offset_samples=0, window_size_samples=input_window_samples, window_stride_samples=n_preds_per_input, drop_last_window=False, preload=True, ) ###################################################################### # Split the dataset # ----------------- # # This code is the same as in trialwise decoding. # from braindecode.datasets.base import BaseConcatDataset splitted = windows_dataset.split('session') train_set = splitted['session_T'] valid_set = splitted['session_E'] ###################################################################### # In difference to trialwise decoding, we now should supply # ``cropped=True`` to the EEGClassifier, and ``CroppedLoss`` as the # criterion, as well as ``criterion__loss_function`` as the loss function # applied to the meaned predictions. # ###################################################################### # .. note:: # In this tutorial, we use some default parameters that we # have found to work well for motor decoding, however we strongly # encourage you to perform your own hyperparameter optimization using # cross validation on your training data. # from skorch.callbacks import LRScheduler from skorch.helper import predefined_split from braindecode import EEGClassifier from braindecode.training.losses import CroppedLoss from braindecode.training.scoring import trial_preds_from_window_preds # # These values we found good for shallow network: lr = 0.0625 * 0.01 weight_decay = 0 # # For deep4 they should be: # lr = 1 * 0.01 # weight_decay = 0.5 * 0.001 # batch_size = 8 n_epochs = 100 clf = EEGClassifier( model, cropped=True, criterion=CroppedLoss, criterion__loss_function=torch.nn.functional.nll_loss, optimizer=torch.optim.AdamW, train_split=predefined_split(valid_set), optimizer__lr=lr, optimizer__weight_decay=weight_decay, iterator_train__shuffle=True, batch_size=batch_size, callbacks=[ "accuracy", ("lr_scheduler", LRScheduler('CosineAnnealingLR', T_max=n_epochs - 1)), ], device=device, ) # Model training for a specified number of epochs. `y` is None as it is already supplied # in the dataset. clf.fit(train_set, y=None, epochs=n_epochs) ###################################################################### # Plot Results # ------------ # ###################################################################### # This is again the same code as in trialwise decoding. # # .. note:: # Note that we drop further in the classification error and # loss as in the trialwise decoding tutorial. # import matplotlib.pyplot as plt from matplotlib.lines import Line2D import pandas as pd # Extract loss and accuracy values for plotting from history object results_columns = [ 'train_loss', 'valid_loss', 'train_accuracy', 'valid_accuracy' ] df = pd.DataFrame(clf.history[:, results_columns], columns=results_columns, index=clf.history[:, 'epoch']) # get percent of misclass for better visual comparison to loss df = df.assign(train_misclass=100 - 100 * df.train_accuracy, valid_misclass=100 - 100 * df.valid_accuracy) plt.style.use('seaborn') fig, ax1 = plt.subplots(figsize=(8, 3)) df.loc[:, ['train_loss', 'valid_loss']].plot(ax=ax1, style=['-', ':'], marker='o', color='tab:blue', legend=False, fontsize=14) ax1.tick_params(axis='y', labelcolor='tab:blue', labelsize=14) ax1.set_ylabel("Loss", color='tab:blue', fontsize=14) ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axis df.loc[:, ['train_misclass', 'valid_misclass']].plot(ax=ax2, style=['-', ':'], marker='o', color='tab:red', legend=False) ax2.tick_params(axis='y', labelcolor='tab:red', labelsize=14) ax2.set_ylabel("Misclassification Rate [%]", color='tab:red', fontsize=14) ax2.set_ylim(ax2.get_ylim()[0], 85) # make some room for legend ax1.set_xlabel("Epoch", fontsize=14) # where some data has already been plotted to ax handles = [] handles.append( Line2D([0], [0], color='black', linewidth=1, linestyle='-', label='Train')) handles.append( Line2D([0], [0], color='black', linewidth=1, linestyle=':', label='Valid')) plt.legend(handles, [h.get_label() for h in handles], fontsize=14) plt.tight_layout() return df