{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline\n", "import os\n", "import mne\n", "import pandas as pd\n", "from mne.externals.pymatreader import read_mat\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "import itertools\n", "from glob import glob\n", "import pyriemann\n", "from sklearn.linear_model import LogisticRegression\n", "from sklearn.model_selection import cross_val_score\n", "from sklearn.pipeline import make_pipeline\n", "from sklearn.metrics import accuracy_score \n", "import time" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "cwd = os.getcwd()\n", "data_path = cwd\n", "n_subs = 4\n", "n_sessions = 2\n", "diff = ['MATBeasy', 'MATBmed', 'MATBdiff']" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ch_namesxyz
0Fp1-29.437083.917-6.990
1Fz0.312258.51266.462
2F3-50.244053.11142.192
3F7-70.263042.474-11.420
4FT9-84.076014.567-50.429
\n", "
" ], "text/plain": [ " ch_names x y z\n", "0 Fp1 -29.4370 83.917 -6.990\n", "1 Fz 0.3122 58.512 66.462\n", "2 F3 -50.2440 53.111 42.192\n", "3 F7 -70.2630 42.474 -11.420\n", "4 FT9 -84.0760 14.567 -50.429" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "electrodes = pd.read_csv(data_path + '/chan_locs_standard',header=None, sep ='\\t', names=['ch_names','x','y','z'])\n", "electrodes.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Covariance estimation For robust covariance estimation, we take advantage of shrinkage. Here\n", "the Oracle Approximating Shrinkage (OAS) is used. #### Classifier We use a simple Logistic\n", "Regression (with a non-optimized L2 penalty) on Tangent Space Features, extracted with Pyriemann\n", "toolbox. #### Channel selection A manual and naive EEG channel selection is performed\n", "to use 13 electrodes, mostly frontal." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "lr = LogisticRegression(C=1/10.)\n", "clf = make_pipeline(pyriemann.estimation.Covariances(estimator='oas'), pyriemann.classification.TSclassifier(clf=lr))\n", "ch_slice = ['F7', 'F5', 'F3', 'F1', 'F2', 'F4', 'F6', 'AF3', 'AFz', 'AF4', 'FP1', 'FP2', 'FPz']" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "time = 3.9678661823272705\n", "Subject P01 and session 1: mean accuracy of 0.78 with a standard deviation of 0.03\n", "time = 3.8175976276397705\n", "Subject P01 and session 2: mean accuracy of 0.74 with a standard deviation of 0.06\n", "time = 3.891139030456543\n", "Subject P02 and session 1: mean accuracy of 0.74 with a standard deviation of 0.04\n", "time = 3.886229991912842\n", "Subject P02 and session 2: mean accuracy of 0.83 with a standard deviation of 0.08\n", "time = 3.8696224689483643\n", "Subject P03 and session 1: mean accuracy of 0.67 with a standard deviation of 0.05\n", "time = 3.850278854370117\n", "Subject P03 and session 2: mean accuracy of 0.63 with a standard deviation of 0.1\n", "time = 3.811692237854004\n", "Subject P04 and session 1: mean accuracy of 0.73 with a standard deviation of 0.03\n", "time = 3.878727912902832\n", "Subject P04 and session 2: mean accuracy of 0.78 with a standard deviation of 0.06\n" ] } ], "source": [ "# Single Subj epochs classification\n", "for sub_n, session_n in itertools.product(range(n_subs), range(n_sessions)):\n", " epochs_data = []\n", " labels = []\n", " for lab_idx, level in enumerate(diff):\n", " sub = 'P{0:02d}'.format(sub_n+1)\n", " sess = f'S{session_n+1}'\n", " path = os.path.join(os.path.join(data_path, sub), sess) + f'/eeg/alldata_sbj{str(sub_n+1).zfill(2)}_sess{session_n+1}_{level}.set'\n", "# print(path)\n", " # Read the epoched data with MNE\n", " epochs = mne.io.read_epochs_eeglab(path, verbose=False)\n", " # You could add some pre-processing here with MNE\n", " # We will just select some channels (mostly frontal ones)\n", " epochs = epochs.drop_channels(list(set(epochs.ch_names) - set(ch_slice)))\n", " # Get the data and concatenante with others MATB levels\n", " tmp = epochs.get_data()\n", " epochs_data.extend(tmp)\n", " labels.extend([lab_idx]*len(tmp))\n", "\n", " epochs_data = np.array(epochs_data)\n", " labels = np.array(labels)\n", "\n", " # Compute classification accuracy with 5-folds cross validation\n", " start = time.time()\n", " acc = cross_val_score(clf, X=epochs_data, y=labels, cv=5)\n", " end = time.time()\n", " print(f'time = {end-start}')\n", " print(f'Subject {sub} and session {session_n+1}: mean accuracy of {round(np.mean(acc), 2)} with a standard deviation of {round(np.std(acc), 2)}')" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Fitting time on Subject 1 Sess 1 = 0.9518132209777832\n" ] } ], "source": [ "#Transfer from senssion 1 to 2 for P01\n", "sub_n = 0\n", "session_n = 0\n", "epochs_data = []\n", "labels = []\n", "for lab_idx, level in enumerate(diff):\n", " sub = 'P{0:02d}'.format(sub_n+1)\n", " sess = f'S{session_n+1}'\n", " path = os.path.join(os.path.join(data_path, sub), sess) + f'/eeg/alldata_sbj{str(sub_n+1).zfill(2)}_sess{session_n+1}_{level}.set'\n", " # Read the epoched data with MNE\n", " epochs = mne.io.read_epochs_eeglab(path, verbose=False)\n", " # You could add some pre-processing here with MNE\n", " # We will just select some channels (mostly frontal ones)\n", " epochs = epochs.drop_channels(list(set(epochs.ch_names) - set(ch_slice)))\n", " # Get the data and concatenante with others MATB levels\n", " tmp = epochs.get_data()\n", " epochs_data.extend(tmp)\n", " labels.extend([lab_idx]*len(tmp))\n", "epochs_data = np.array(epochs_data)\n", "labels = np.array(labels)\n", "# Train the model on all epochs from session 1\n", "start = time.time()\n", "clf.fit(epochs_data, labels)\n", "end = time.time()\n", "print(f'Fitting time on Subject {sub_n+1} Sess {session_n+1} = {end-start}')" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Prediction time on Subject 1 Sess 2 = 0.14130353927612305\n", "Subject P01 and transfer from session 1 to 2: mean accuracy of 0.33.\n" ] } ], "source": [ "session_n = 1\n", "epochs_data = []\n", "labels = []\n", "for lab_idx, level in enumerate(diff):\n", " sub = 'P{0:02d}'.format(sub_n+1)\n", " sess = f'S{session_n+1}'\n", " path = os.path.join(os.path.join(data_path, sub), sess) + f'/eeg/alldata_sbj{str(sub_n+1).zfill(2)}_sess{session_n+1}_{level}.set'\n", " # Read the epoched data with MNE\n", " tmp = mne.io.read_epochs_eeglab(path, verbose=False)\n", " # You could add some pre-processing here with MNE\n", " # We will just select some channels (mostly frontal ones)\n", " epochs = epochs.drop_channels(list(set(epochs.ch_names) - set(ch_slice)))\n", " # Get the data and concatenante with others MATB levels\n", " tmp = epochs.get_data()\n", " epochs_data.extend(tmp)\n", " labels.extend([lab_idx]*len(tmp))\n", "epochs_data = np.array(epochs_data)\n", "labels = np.array(labels)\n", "# Use trained model to predict for all epochs of session 2 and compute accuracy\n", "start = time.time()\n", "y_pred = clf.predict(epochs_data)\n", "end = time.time()\n", "print(f'Prediction time on Subject {sub_n+1} Sess {session_n+1} = {end-start}')\n", "acc = accuracy_score(labels, y_pred)\n", "print(f'Subject {sub} and transfer from session 1 to 2: mean accuracy of {round(acc, 2)}.')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#Generate a CSV to submit\n", "submission = pd.DataFrame({'epochID':np.arange(len(y_pred)), 'prediction' : y_pred})\n", "submission.head()\n", "submission.to_csv(\"submission.csv\",header=True,index=False)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.3" } }, "nbformat": 4, "nbformat_minor": 5 }