def test_model_from_keras( subject, batch_size=32, folder='/scratch/sem19h24/EEGNet_reformat/EEGnet/initialModels/'): """ Import the keras model and test it Parameters: subject: Number between 1 and 9 batch_size: Batch Size to test the model folder: Folder where the model files are found. returns: loss, accuracy """ # Just use the default values and hope all dimensions are fine... model = EEGNet(activation='elu', constrain_w=False, permuted_flatten=True) model.load_model_params_from_keras(f"{folder}model{subject-1}_torch.npz") if t.cuda.is_available(): model = model.cuda() print_summary(model, None, None, None) # get dataloader test_samples, test_labels = get_data(subject, training=False) test_loader = as_data_loader(test_samples, test_labels, batch_size=batch_size) # prepare loss function, no optimizer necessary loss_function = t.nn.CrossEntropyLoss() return _test_net(model, test_loader, loss_function, train=False)
def __init__(self): self.net = EEGNet().cuda() self.criterion = nn.BCELoss() self.optimizer = optim.Adam(self.net.parameters(), lr=0.001) self.scheduler = optim.lr_scheduler.StepLR(self.optimizer, step_size=20, gamma=0.5)
class EEGNet_classifier(): def __init__(self): self.net = EEGNet().cuda() self.criterion = nn.BCELoss() self.optimizer = optim.Adam(self.net.parameters(), lr=0.001) self.scheduler = optim.lr_scheduler.StepLR(self.optimizer, step_size=20, gamma=0.8) def fit(self, X, y, quiet=True): for epoch in range(200): running_loss = 0 _skf = StratifiedKFold(n_splits=10, shuffle=True) for more, less in _skf.split(X, y): # Get data and labels inputs = torch.from_numpy(X[more]) labels = torch.FloatTensor(np.array([y[more]]).T * 1.0) # Make sure positive and negative samples have the same number inputs = inputs[:torch.sum(labels).type(torch.int16) * 2] labels = labels[:torch.sum(labels).type(torch.int16) * 2] # wrap them in Variable inputs = Variable(inputs.cuda()) labels = Variable(labels.cuda()) # zero the parameter gradients self.optimizer.zero_grad() # forward + backward + optimize outputs = self.net(inputs) loss = self.criterion(outputs, labels) loss.backward() self.optimizer.step() running_loss += loss.data self.scheduler.step() if not quiet: # print(f'Epoch {epoch}: {running_loss}') if epoch % 10 == 0: print(f'Epoch {epoch}: {running_loss}') print(f'Epoch {epoch}: {running_loss}') def predict(self, X): inputs = torch.from_numpy(X) inputs = Variable(inputs.cuda()) return self.net(inputs)
def train_subject_specific_cv(subject, n_splits=4, epochs=500, batch_size=32, lr=0.001, early_stopping=True, silent=False, plot=True, **kwargs): """ Trains a subject specific model for the given subject, using K-Fold Cross Validation Parameters: - subject: Integer in the Range 1 <= subject <= 9 - n_splits: Number of splits for K-Fold CV - epochs: Number of epochs to train - batch_size: Batch Size - lr: Learning Rate - early_stopping: bool, approximate the number of epochs to train the network for the subject. - silent: bool, if True, generate no output, including progress bar - plot: bool, if True, generates plots - kwargs: remaining parameters are passed to the EEGnet model Returns: (models, metrics, epoch) - models: List of t.nn.Module, size = [n_splits] - metrics: t.tensor, size=[1, 4], accuracy, precision, recall, f1, averaged over all splits - epoch: integer, number of epochs determined by early_stopping. If early_stopping is not used, then this value will always be equal to the parameter epochs Notes: - Early Stopping: Uses early stopping to determine the best epoch to stop training for the given subject by averaging over the stopping epoch of all splits. """ # load the raw data samples, labels = get_data(subject, training=True) samples, labels = as_tensor(samples, labels) # prepare the models models = [EEGNet(T=samples.shape[2], **kwargs) for _ in range(n_splits)] metrics = t.zeros((n_splits, 4)) best_epoch = np.zeros(n_splits) # prepare KFold kfcv = KFoldCV(n_splits) split = 0 # open the progress bar with tqdm(desc=f"Subject {subject} CV, split 1", total=n_splits * epochs, leave=False, unit='epoch', ascii=True, disable=silent) as pbar: # loop over all splits for split, indices in enumerate(kfcv.split(samples, labels)): # set the progress bar title pbar.set_description(f"Subject {subject} CV, split {split + 1}") # generate dataset train_idx, val_idx = indices train_ds = t.utils.data.TensorDataset(samples[train_idx], labels[train_idx]) val_ds = t.utils.data.TensorDataset(samples[val_idx], labels[val_idx]) train_loader = t.utils.data.DataLoader(train_ds, batch_size=batch_size, shuffle=True) val_loader = t.utils.data.DataLoader(val_ds, batch_size=batch_size, shuffle=True) # prepare the model model = models[split] model.initialize_params() if t.cuda.is_available(): model = model.cuda() # prepare loss function and optimizer loss_function = t.nn.CrossEntropyLoss() optimizer = t.optim.Adam(model.parameters(), lr=lr) model, split_metrics, split_epoch, _ = _train_net( subject, model, train_loader, val_loader, loss_function, optimizer, epochs=epochs, early_stopping=early_stopping, plot=plot, pbar=pbar) metrics[split, :] = split_metrics[0, :] best_epoch[split] = split_epoch # average all metrics metrics = metrics.mean(axis=0).reshape(1, 4) # print the result if not silent: print( f"Subje`ct {subject} CV: accuracy = {metrics[0, 0]}, at epoch {best_epoch.mean()} " + f"+- {best_epoch.std()}") return models, metrics, int(best_epoch.mean().round())
def train_subject_specific(subject, epochs=500, batch_size=32, lr=0.001, silent=False, plot=True, **kwargs): """ Trains a subject specific model for the given subject Parameters: - subject: Integer in the Range 1 <= subject <= 9 - epochs: Number of epochs to train - batch_size: Batch Size - lr: Learning Rate - silent: bool, if True, hide all output including the progress bar - plot: bool, if True, generate plots - kwargs: Remaining arguments passed to the EEGnet model Returns: (model, metrics) - model: t.nn.Module, trained model - metrics: t.tensor, size=[1, 4], accuracy, precision, recall, f1 """ # load the data train_samples, train_labels = get_data(subject, training=True) test_samples, test_labels = get_data(subject, training=False) train_loader = as_data_loader(train_samples, train_labels, batch_size=batch_size) # test_loader = as_data_loader(test_samples, test_labels, batch_size=test_labels.shape[0]) test_loader = as_data_loader(test_samples, test_labels, batch_size=batch_size) # prepare the model model = EEGNet(T=train_samples.shape[2], **kwargs) model.initialize_params() if t.cuda.is_available(): model = model.cuda() # prepare loss function and optimizer loss_function = t.nn.CrossEntropyLoss() optimizer = t.optim.Adam(model.parameters(), lr=lr, eps=1e-7) scheduler = None # print the training setup print_summary(model, optimizer, loss_function, scheduler) # prepare progress bar with tqdm(desc=f"Subject {subject}", total=epochs, leave=False, disable=silent, unit='epoch', ascii=True) as pbar: # Early stopping is not allowed in this mode, because the testing data cannot be used for # training! model, metrics, _, history = _train_net(subject, model, train_loader, test_loader, loss_function, optimizer, scheduler=scheduler, epochs=epochs, early_stopping=False, plot=plot, pbar=pbar) if not silent: print(f"Subject {subject}: accuracy = {metrics[0, 0]}") return model, metrics, history
import os import sys import pickle # Computing ------------------------------------- import numpy as np from sklearn.model_selection import StratifiedKFold # Local tools ----------------------------------- sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'tools')) # noqa from MEG_worker import MEG_Worker # EEG net --------------------------------------- import torchsummary from eegnet import torch, nn, EEGNet, optim, Variable, evaluate net = EEGNet().cuda() print(net.forward(Variable(torch.Tensor(np.random.rand(1, 1, 61, 272)).cuda()))) torchsummary.summary(net, input_size=(1, 61, 272)) # Init parameters ------------------------------- # Init results_folder RESULTS_FOLDER = os.path.join('.', 'results_eegnet') # Make sure RESULTS_FOLDER is not a file assert (not os.path.isfile(RESULTS_FOLDER)) # Mkdir if RESULTS_FOLDER does not exist if not os.path.exists(RESULTS_FOLDER): os.mkdir(RESULTS_FOLDER)