{"metadata":{"kaggle":{"accelerator":"none","dataSources":[{"sourceId":59093,"databundleVersionId":7469972,"sourceType":"competition"},{"sourceId":7392733,"sourceType":"datasetVersion","datasetId":4297749},{"sourceId":7414022,"sourceType":"datasetVersion","datasetId":4312784}],"dockerImageVersionId":30635,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false},"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.10.12"},"papermill":{"default_parameters":{},"duration":102.485133,"end_time":"2024-01-16T12:14:21.10455","environment_variables":{},"exception":null,"input_path":"__notebook__.ipynb","output_path":"__notebook__.ipynb","parameters":{},"start_time":"2024-01-16T12:12:38.619417","version":"2.4.0"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd, numpy as np, os\nimport matplotlib.pyplot as plt, gc\n\ntrain = pd.read_csv('/kaggle/input/hms-harmful-brain-activity-classification/train.csv')\nprint('Train shape', train.shape )\ndisplay( train.head() )\n\n# CHOICE TO CREATE OR LOAD SPECTROGRAMS FROM NOTEBOOK VERSION 2\nCREATE_SPECTROGRAMS = False","metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","papermill":{"duration":0.693827,"end_time":"2024-01-16T12:12:42.606147","exception":false,"start_time":"2024-01-16T12:12:41.91232","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-01-16T14:01:59.130302Z","iopub.execute_input":"2024-01-16T14:01:59.130709Z","iopub.status.idle":"2024-01-16T14:02:00.012551Z","shell.execute_reply.started":"2024-01-16T14:01:59.130677Z","shell.execute_reply":"2024-01-16T14:02:00.011204Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"NAMES = ['LL','LP','RP','RR']\n\nFEATS = [['Fp1','F7','T3','T5','O1'],\n         ['Fp1','F3','C3','P3','O1'],\n         ['Fp2','F8','T4','T6','O2'],\n         ['Fp2','F4','C4','P4','O2']]\n\ndirectory_path = 'EEG_Spectrograms/'\nif not os.path.exists(directory_path):\n    os.makedirs(directory_path)","metadata":{"papermill":{"duration":0.017131,"end_time":"2024-01-16T12:12:42.644893","exception":false,"start_time":"2024-01-16T12:12:42.627762","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-01-16T14:02:00.015275Z","iopub.execute_input":"2024-01-16T14:02:00.016534Z","iopub.status.idle":"2024-01-16T14:02:00.024762Z","shell.execute_reply.started":"2024-01-16T14:02:00.01648Z","shell.execute_reply":"2024-01-16T14:02:00.023774Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pywt\nprint(\"The wavelet functions we can use:\")\nprint(pywt.wavelist())\n\nUSE_WAVELET = None #or \"db8\" or anything below","metadata":{"papermill":{"duration":0.540601,"end_time":"2024-01-16T12:12:43.206759","exception":false,"start_time":"2024-01-16T12:12:42.666158","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-01-16T14:02:00.026747Z","iopub.execute_input":"2024-01-16T14:02:00.027676Z","iopub.status.idle":"2024-01-16T14:02:00.298039Z","shell.execute_reply.started":"2024-01-16T14:02:00.027626Z","shell.execute_reply":"2024-01-16T14:02:00.296761Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# DENOISE FUNCTION\ndef maddest(d, axis=None):\n    return np.mean(np.absolute(d - np.mean(d, axis)), axis)\n\ndef denoise(x, wavelet='haar', level=1):    \n    coeff = pywt.wavedec(x, wavelet, mode=\"per\")\n    sigma = (1/0.6745) * maddest(coeff[-level])\n\n    uthresh = sigma * np.sqrt(2*np.log(len(x)))\n    coeff[1:] = (pywt.threshold(i, value=uthresh, mode='hard') for i in coeff[1:])\n\n    ret=pywt.waverec(coeff, wavelet, mode='per')\n    \n    return ret","metadata":{"papermill":{"duration":0.018392,"end_time":"2024-01-16T12:12:43.23335","exception":false,"start_time":"2024-01-16T12:12:43.214958","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-01-16T14:02:00.301578Z","iopub.execute_input":"2024-01-16T14:02:00.302716Z","iopub.status.idle":"2024-01-16T14:02:00.313837Z","shell.execute_reply.started":"2024-01-16T14:02:00.302662Z","shell.execute_reply":"2024-01-16T14:02:00.311986Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import librosa\n\ndef spectrogram_from_eeg(parquet_path, display=False):\n    \n    # LOAD MIDDLE 50 SECONDS OF EEG SERIES\n    eeg = pd.read_parquet(parquet_path)\n    middle = (len(eeg)-10_000)//2\n    eeg = eeg.iloc[middle:middle+10_000]\n    \n    # VARIABLE TO HOLD SPECTROGRAM\n    img = np.zeros((128,256,4),dtype='float32')\n    \n    if display: plt.figure(figsize=(10,7))\n    signals = []\n    for k in range(4):\n        COLS = FEATS[k]\n        \n        # COMPUTE PAIR DIFFERENCES AND AVERAGE\n        x = eeg[COLS[0]].values - eeg[COLS[1]].values\n        for j in range(3):\n            x += eeg[COLS[j+1]].values - eeg[COLS[j+2]].values\n        x /= 4.0\n        signals.append(x)\n        \n        # FILL NANS\n        m = np.nanmean(x)\n        if np.isnan(x).mean()<1: x = np.nan_to_num(x,nan=m)\n        else: x[:] = 0\n            \n        # DENOISE\n        if USE_WAVELET:\n            x = denoise(x, wavelet=USE_WAVELET)\n                    \n        # RAW SPECTROGRAM\n        mel_spec = librosa.feature.melspectrogram(y=x, sr=200, hop_length=len(x)//256, \n              n_fft=1024, n_mels=128, fmin=0, fmax=20, win_length=128)\n        \n        # LOG TRANSFORM\n        width = (mel_spec.shape[1]//32)*32\n        mel_spec_db = librosa.power_to_db(mel_spec, ref=np.max).astype(np.float32)[:,:width]\n        \n        # STANDARDIZE TO -1 TO 1\n        mel_spec_db = (mel_spec_db+40)/40 \n        \n        img[:,:,k] = mel_spec_db\n        if display:\n            plt.subplot(2,2,k+1)\n            plt.imshow(mel_spec_db,aspect='auto',origin='lower')\n            plt.title(f'EEG {eeg_id} - Spectrogram {NAMES[k]}')\n            \n    if display: \n        plt.show()\n        plt.figure(figsize=(10,5))\n        offset = 0\n        for k in range(4):\n            if k>0: offset -= signals[3-k].min()\n            plt.plot(range(10_000),signals[k]+offset,label=NAMES[3-k])\n            offset += signals[3-k].max()\n        plt.legend()\n        plt.title(f'EEG {eeg_id} Signals')\n        plt.show()\n        print(); print('#'*25); print()\n        \n    return img","metadata":{"papermill":{"duration":0.032361,"end_time":"2024-01-16T12:12:43.287163","exception":false,"start_time":"2024-01-16T12:12:43.254802","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-01-16T14:02:00.316678Z","iopub.execute_input":"2024-01-16T14:02:00.317169Z","iopub.status.idle":"2024-01-16T14:02:00.350145Z","shell.execute_reply.started":"2024-01-16T14:02:00.317131Z","shell.execute_reply":"2024-01-16T14:02:00.348785Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\nPATH = '/kaggle/input/hms-harmful-brain-activity-classification/train_eegs/'\nDISPLAY = 4\nEEG_IDS = train.eeg_id.unique()\nall_eegs = {}\n\nfor i,eeg_id in enumerate(EEG_IDS):\n    if (i%100==0)&(i!=0): print(i,', ',end='')\n        \n    # CREATE SPECTROGRAM FROM EEG PARQUET\n    display = False\n    if i<DISPLAY: display = True\n    img = spectrogram_from_eeg(f'{PATH}{eeg_id}.parquet', display)\n    \n    # SAVE TO DISK\n    if i==DISPLAY:\n        if CREATE_SPECTROGRAMS:\n            print(f'Creating and writing {len(EEG_IDS)} spectrograms to disk... ',end='')\n        else: \n            print(f'Reading {len(EEG_IDS)} spectrograms from disk.')\n            break\n    if CREATE_SPECTROGRAMS:\n        np.save(f'{directory_path}{eeg_id}',img)\n    all_eegs[eeg_id] = img\n   \n# SAVE OR LOAD EEG SPECTROGRAM DICTIONARY\nif not CREATE_SPECTROGRAMS:\n    all_eegs = np.load('/kaggle/input/eeg-spectrograms/eeg_specs.npy',allow_pickle=True).item()\nelse:\n    np.save('eeg_specs',all_eegs)","metadata":{"papermill":{"duration":66.745724,"end_time":"2024-01-16T12:13:50.040166","exception":false,"start_time":"2024-01-16T12:12:43.294442","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-01-16T14:05:49.172993Z","iopub.execute_input":"2024-01-16T14:05:49.173504Z","iopub.status.idle":"2024-01-16T14:07:13.620093Z","shell.execute_reply.started":"2024-01-16T14:05:49.173467Z","shell.execute_reply":"2024-01-16T14:07:13.617324Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Evaluate Spectrograms\nAs of Jan 15th, nobody has successfully trained a model using only EEG (without using Kaggle's spectrograms) and achieved a CV score or LB score better than simply submitting train means. The CV score of train means is `CV = 1.26`. Let's see if we can use our EEG spectrograms to beat this!","metadata":{"papermill":{"duration":0.0281,"end_time":"2024-01-16T12:13:50.09789","exception":false,"start_time":"2024-01-16T12:13:50.06979","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"## Load Train Data\nWe load train data and deduplicate `eeg_id`. The reason for this is explained in my other starter notebooks [here][2] and [here][3]. And discussion [here][1]\n\n[1]: https://www.kaggle.com/competitions/hms-harmful-brain-activity-classification/discussion/468010\n[2]: https://www.kaggle.com/code/cdeotte/efficientnetb2-starter-lb-0-57\n[3]: https://www.kaggle.com/code/cdeotte/catboost-starter-lb-0-67","metadata":{"papermill":{"duration":0.027115,"end_time":"2024-01-16T12:13:50.152869","exception":false,"start_time":"2024-01-16T12:13:50.125754","status":"completed"},"tags":[]}},{"cell_type":"code","source":"# LOAD TRAIN \ndf = pd.read_csv('/kaggle/input/hms-harmful-brain-activity-classification/train.csv')\nTARGETS = df.columns[-6:]\nTARS = {'Seizure':0, 'LPD':1, 'GPD':2, 'LRDA':3, 'GRDA':4, 'Other':5}\nTARS2 = {x:y for y,x in TARS.items()}\n\ntrain = df.groupby('eeg_id')[['patient_id']].agg('first')\n\ntmp = df.groupby('eeg_id')[TARGETS].agg('sum')\nfor t in TARGETS:\n    train[t] = tmp[t].values\n    \ny_data = train[TARGETS].values\ny_data = y_data / y_data.sum(axis=1,keepdims=True)\ntrain[TARGETS] = y_data\n\ntmp = df.groupby('eeg_id')[['expert_consensus']].agg('first')\ntrain['target'] = tmp\n\ntrain = train.reset_index()\ntrain = train.loc[train.eeg_id.isin(EEG_IDS)]\nprint('Train Data with unique eeg_id shape:', train.shape )\ntrain.head()","metadata":{"_kg_hide-input":true,"papermill":{"duration":0.282057,"end_time":"2024-01-16T12:13:50.46312","exception":false,"start_time":"2024-01-16T12:13:50.181063","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-01-16T14:07:25.890122Z","iopub.execute_input":"2024-01-16T14:07:25.890572Z","iopub.status.idle":"2024-01-16T14:07:26.274039Z","shell.execute_reply.started":"2024-01-16T14:07:25.890537Z","shell.execute_reply":"2024-01-16T14:07:26.27287Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Dataloader","metadata":{"papermill":{"duration":0.028035,"end_time":"2024-01-16T12:13:50.519598","exception":false,"start_time":"2024-01-16T12:13:50.491563","status":"completed"},"tags":[]}},{"cell_type":"code","source":"import tensorflow as tf\n\nclass DataGenerator(tf.keras.utils.Sequence):\n    'Generates data for Keras'\n    def __init__(self, data, batch_size=32, shuffle=False, eegs=all_eegs, mode='train'): \n\n        self.data = data\n        self.batch_size = batch_size\n        self.shuffle = shuffle\n        self.eegs = eegs\n        self.mode = mode\n        self.on_epoch_end()\n        \n    def __len__(self):\n        'Denotes the number of batches per epoch'\n        ct = int( np.ceil( len(self.data) / self.batch_size ) )\n        return ct\n\n    def __getitem__(self, index):\n        'Generate one batch of data'\n        indexes = self.indexes[index*self.batch_size:(index+1)*self.batch_size]\n        X, y = self.__data_generation(indexes)\n        return X, y\n\n    def on_epoch_end(self):\n        'Updates indexes after each epoch'\n        self.indexes = np.arange( len(self.data) )\n        if self.shuffle: np.random.shuffle(self.indexes)\n                        \n    def __data_generation(self, indexes):\n        'Generates data containing batch_size samples' \n    \n        X = np.zeros((len(indexes),128,256,4),dtype='float32')\n        y = np.zeros((len(indexes),6),dtype='float32')\n        \n        for j,i in enumerate(indexes):\n            row = self.data.iloc[i]                    \n            X[j,] = self.eegs[row.eeg_id]\n            if self.mode!='test':\n                y[j] = row[TARGETS]\n            \n        return X,y\n    \ngen = DataGenerator(train, shuffle=False)\nROWS=2; COLS=3\nfor x,y in gen:\n    plt.figure(figsize=(20,8))\n    for j in range(ROWS):\n        for k in range(COLS):\n            plt.subplot(ROWS,COLS,j*COLS+k+1)\n            t = y[j*COLS+k]\n            img = x[j*COLS+k,:,:,0]\n            plt.imshow(img)\n            tt = f'{y[j*COLS+k][0]:0.1f}'\n            for t in y[j*COLS+k][1:]:\n                tt += f', {t:0.1f}'\n            plt.title(f'EEG_Id = {EEG_IDS[j*COLS+k]}\\nTarget = {tt}',size=14)\n    plt.show()\n    break","metadata":{"_kg_hide-input":true,"papermill":{"duration":15.615215,"end_time":"2024-01-16T12:14:06.163387","exception":false,"start_time":"2024-01-16T12:13:50.548172","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-01-16T14:07:26.277174Z","iopub.execute_input":"2024-01-16T14:07:26.277606Z","iopub.status.idle":"2024-01-16T14:07:28.385473Z","shell.execute_reply.started":"2024-01-16T14:07:26.277573Z","shell.execute_reply":"2024-01-16T14:07:28.38363Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# TRAIN SCHEDULE\ndef lrfn(epoch):\n        return [1e-3,1e-3,1e-3,1e-4,1e-4,1e-4,1e-5,1e-5,1e-5][epoch]\nLR = tf.keras.callbacks.LearningRateScheduler(lrfn, verbose = True)\nEPOCHS = 5\n\n# BUILD MODEL\ndef build_model():\n    \n    # INPUT\n    inp = tf.keras.Input(shape=(128,256,4))\n    specs = [inp[:,:,:,k] for k in range(4)]\n    x = tf.keras.layers.Concatenate(axis=1)(specs)\n    x = tf.transpose(x,[0,2,1])\n    \n    # POOLING\n    x1 = tf.keras.layers.GlobalAveragePooling1D()(x)\n    x2 = tf.keras.layers.GlobalMaxPooling1D()(x)\n    x = tf.keras.layers.Concatenate(axis=-1)([x1,x2])    \n    \n    # HIDDEN LAYERS\n    x = tf.keras.layers.Dense(64, activation='relu')(x)\n    x = tf.keras.layers.Dense(64, activation='relu')(x)\n    x = tf.keras.layers.Dense(64, activation='relu')(x)\n    x = tf.keras.layers.Dense(64, activation='relu')(x)\n    \n    # HEAD\n    x = tf.keras.layers.Dense(6,activation='softmax', dtype='float32')(x)\n        \n    # COMPILE MODEL with KL DIV LOSS\n    model = tf.keras.Model(inputs=inp, outputs=x)\n    opt = tf.keras.optimizers.Adam(learning_rate = 1e-3)\n    loss = tf.keras.losses.KLDivergence()\n\n    model.compile(loss=loss, optimizer = opt) \n        \n    return model","metadata":{"papermill":{"duration":0.053799,"end_time":"2024-01-16T12:14:06.333372","exception":false,"start_time":"2024-01-16T12:14:06.279573","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-01-16T14:07:28.388136Z","iopub.execute_input":"2024-01-16T14:07:28.388675Z","iopub.status.idle":"2024-01-16T14:07:28.413273Z","shell.execute_reply.started":"2024-01-16T14:07:28.388634Z","shell.execute_reply":"2024-01-16T14:07:28.410473Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Train Group KFold\nWe will train one fold of Group KFold. Note that we are training this simple MLP model with CPU. If you train a larger model, you must turn on GPU.","metadata":{"papermill":{"duration":0.037735,"end_time":"2024-01-16T12:14:06.409252","exception":false,"start_time":"2024-01-16T12:14:06.371517","status":"completed"},"tags":[]}},{"cell_type":"code","source":"FOLDS_TO_TRAIN = 5\nif not os.path.exists('MLP_Model'):\n    os.makedirs('MLP_Model')\n\nfrom sklearn.model_selection import KFold, GroupKFold\nimport tensorflow.keras.backend as K, gc\n\nall_oof = []; all_oof2 = []; all_true = []\ngkf = GroupKFold(n_splits=5)\nfor i, (train_index, valid_index) in enumerate(gkf.split(train, train.target, train.patient_id)):   \n    \n    print('#'*25)\n    print(f'### Fold {i+1}')\n    train_gen = DataGenerator(train.iloc[train_index], shuffle=True, batch_size=32)\n    valid_gen = DataGenerator(train.iloc[valid_index], shuffle=False, batch_size=64, mode='valid')\n    print(f'### train size {len(train_index)}, valid size {len(valid_index)}')\n    print('#'*25)\n    \n    # TRAIN MODEL\n    K.clear_session()\n    model = build_model()\n    model.fit(train_gen, verbose=2,\n          validation_data = valid_gen,\n          epochs=EPOCHS, callbacks = [LR])\n    model.save_weights(f'MLP_Model/MLP_fold{i}.h5')\n    \n    # MLP OOF\n    oof = model.predict(valid_gen, verbose=2)\n    all_oof.append(oof)\n    all_true.append(train.iloc[valid_index][TARGETS].values)\n    \n    # TRAIN MEAN OOF\n    y_train = train.iloc[train_index][TARGETS].values\n    y_valid = train.iloc[valid_index][TARGETS].values\n    oof = y_valid.copy()\n    for j in range(6):\n        oof[:,j] = y_train[:,j].mean()\n    oof = oof / oof.sum(axis=1,keepdims=True)\n    all_oof2.append(oof)\n    \n    del model, oof, y_train, y_valid\n    gc.collect()\n    \n    if i==FOLDS_TO_TRAIN-1: break\n    \nall_oof = np.concatenate(all_oof)\nall_oof2 = np.concatenate(all_oof2)\nall_true = np.concatenate(all_true)","metadata":{"_kg_hide-input":true,"papermill":{"duration":8.803966,"end_time":"2024-01-16T12:14:15.252859","exception":false,"start_time":"2024-01-16T12:14:06.448893","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-01-16T14:07:28.416015Z","iopub.execute_input":"2024-01-16T14:07:28.416842Z","iopub.status.idle":"2024-01-16T14:22:28.939027Z","shell.execute_reply.started":"2024-01-16T14:07:28.416702Z","shell.execute_reply":"2024-01-16T14:22:28.937968Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# CV Score with EEG Spectrograms\nWe observe that CV score with our new eeg spectrograms is better than CV score using only train means!","metadata":{"papermill":{"duration":0.039052,"end_time":"2024-01-16T12:14:15.33223","exception":false,"start_time":"2024-01-16T12:14:15.293178","status":"completed"},"tags":[]}},{"cell_type":"code","source":"import sys\nsys.path.append('/kaggle/input/kaggle-kl-div')\nfrom kaggle_kl_div import score\n\noof = pd.DataFrame(all_oof.copy())\noof['id'] = np.arange(len(oof))\n\ntrue = pd.DataFrame(all_true.copy())\ntrue['id'] = np.arange(len(true))\n\ncv = score(solution=true, submission=oof, row_id_column_name='id')\nprint('CV Score with EEG Spectrograms =',cv)","metadata":{"papermill":{"duration":0.096437,"end_time":"2024-01-16T12:14:15.468873","exception":false,"start_time":"2024-01-16T12:14:15.372436","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-01-16T14:22:28.942738Z","iopub.execute_input":"2024-01-16T14:22:28.943189Z","iopub.status.idle":"2024-01-16T14:22:29.055196Z","shell.execute_reply.started":"2024-01-16T14:22:28.943154Z","shell.execute_reply":"2024-01-16T14:22:29.053911Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# CV Score using Train Means\nWe observe that CV score with our new eeg spectrograms is better than CV score using only train means!","metadata":{"papermill":{"duration":0.040763,"end_time":"2024-01-16T12:14:15.549535","exception":false,"start_time":"2024-01-16T12:14:15.508772","status":"completed"},"tags":[]}},{"cell_type":"code","source":"oof = pd.DataFrame(all_oof2.copy())\noof['id'] = np.arange(len(oof))\n\ntrue = pd.DataFrame(all_true.copy())\ntrue['id'] = np.arange(len(true))\n\ncv = score(solution=true, submission=oof, row_id_column_name='id')\nprint('CV Score with EEG Spectrograms =',cv)","metadata":{"papermill":{"duration":0.080915,"end_time":"2024-01-16T12:14:15.671617","exception":false,"start_time":"2024-01-16T12:14:15.590702","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-01-16T14:22:29.056724Z","iopub.execute_input":"2024-01-16T14:22:29.057164Z","iopub.status.idle":"2024-01-16T14:22:29.143644Z","shell.execute_reply.started":"2024-01-16T14:22:29.05713Z","shell.execute_reply":"2024-01-16T14:22:29.14252Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Submit to Kaggle LB\nAbove we observe that EEG spectrograms achieve a better CV score than using train means as predictions. Let's submit to Kaggle's LB and see if using these EEG spectrograms can beat LB compared with using train means which achieves `LB = 0.97`...","metadata":{"papermill":{"duration":0.039743,"end_time":"2024-01-16T12:14:15.75862","exception":false,"start_time":"2024-01-16T12:14:15.718877","status":"completed"},"tags":[]}},{"cell_type":"code","source":"del all_eegs, train; gc.collect()\ntest = pd.read_csv('/kaggle/input/hms-harmful-brain-activity-classification/test.csv')\nprint('Test shape:',test.shape)\ntest.head()","metadata":{"papermill":{"duration":0.059958,"end_time":"2024-01-16T12:14:15.85819","exception":false,"start_time":"2024-01-16T12:14:15.798232","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-01-16T14:22:29.145547Z","iopub.execute_input":"2024-01-16T14:22:29.146383Z","iopub.status.idle":"2024-01-16T14:22:29.518974Z","shell.execute_reply.started":"2024-01-16T14:22:29.146328Z","shell.execute_reply":"2024-01-16T14:22:29.517582Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"PATH2 = '/kaggle/input/hms-harmful-brain-activity-classification/test_eegs/'\nDISPLAY = 1\nEEG_IDS2 = test.eeg_id.unique()\nall_eegs2 = {}\n\nprint('Converting Test EEG to Spectrograms...'); print()\nfor i,eeg_id in enumerate(EEG_IDS2):\n        \n    # CREATE SPECTROGRAM FROM EEG PARQUET\n    display = False\n    if i<DISPLAY: display = True\n    img = spectrogram_from_eeg(f'{PATH2}{eeg_id}.parquet', display)\n    all_eegs2[eeg_id] = img","metadata":{"_kg_hide-input":true,"papermill":{"duration":1.653528,"end_time":"2024-01-16T12:14:17.551293","exception":false,"start_time":"2024-01-16T12:14:15.897765","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-01-16T14:22:29.520948Z","iopub.execute_input":"2024-01-16T14:22:29.521884Z","iopub.status.idle":"2024-01-16T14:22:31.482655Z","shell.execute_reply.started":"2024-01-16T14:22:29.521843Z","shell.execute_reply":"2024-01-16T14:22:31.481443Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# INFER MLP ON TEST\npreds = []\nmodel = build_model()\ntest_gen = DataGenerator(test, shuffle=False, batch_size=64, eegs=all_eegs2, mode='test')\n\nprint('Inferring test... ',end='')\nfor i in range(FOLDS_TO_TRAIN):\n    print(f'fold {i+1}, ',end='')\n    model.load_weights(f'MLP_Model/MLP_fold{i}.h5')\n    pred = model.predict(test_gen, verbose=0)\n    preds.append(pred)\npred = np.mean(preds,axis=0)\nprint()\nprint('Test preds shape',pred.shape)","metadata":{"_kg_hide-input":false,"papermill":{"duration":0.3438,"end_time":"2024-01-16T12:14:17.94204","exception":false,"start_time":"2024-01-16T12:14:17.59824","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-01-16T14:22:31.484646Z","iopub.execute_input":"2024-01-16T14:22:31.485885Z","iopub.status.idle":"2024-01-16T14:22:32.341442Z","shell.execute_reply.started":"2024-01-16T14:22:31.485776Z","shell.execute_reply":"2024-01-16T14:22:32.340446Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# CREATE SUBMISSION.CSV\nfrom IPython.display import display\n\nsub = pd.DataFrame({'eeg_id':test.eeg_id.values})\nsub[TARGETS] = pred\nsub.to_csv('submission.csv',index=False)\nprint('Submission shape',sub.shape)\ndisplay( sub.head() )\n\n# SANITY CHECK TO CONFIRM PREDICTIONS SUM TO ONE\nprint('Sub row 0 sums to:',sub.iloc[0,-6:].sum())","metadata":{"papermill":{"duration":0.07372,"end_time":"2024-01-16T12:14:18.05987","exception":false,"start_time":"2024-01-16T12:14:17.98615","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-01-16T14:22:32.342839Z","iopub.execute_input":"2024-01-16T14:22:32.343207Z","iopub.status.idle":"2024-01-16T14:22:32.377249Z","shell.execute_reply.started":"2024-01-16T14:22:32.343175Z","shell.execute_reply":"2024-01-16T14:22:32.375443Z"},"trusted":true},"execution_count":null,"outputs":[]}]}