{"metadata":{"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"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.13"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":59093,"databundleVersionId":7469972,"sourceType":"competition"},{"sourceId":7392733,"sourceType":"datasetVersion","datasetId":4297749},{"sourceId":7465251,"sourceType":"datasetVersion","datasetId":4317718},{"sourceId":7970729,"sourceType":"datasetVersion","datasetId":4690015}],"dockerImageVersionId":30673,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd, numpy as np, os\nimport matplotlib.pyplot as plt \n\ntrain = pd.read_csv('/kaggle/input/hms-harmful-brain-activity-classification/train.csv')\nprint(train.shape)\ndisplay(train.head())\n\nCREATE_EEGS = False\nTRAIN_MODEL = False","metadata":{"execution":{"iopub.status.busy":"2024-03-29T04:18:35.767231Z","iopub.execute_input":"2024-03-29T04:18:35.767610Z","iopub.status.idle":"2024-03-29T04:18:35.880496Z","shell.execute_reply.started":"2024-03-29T04:18:35.767580Z","shell.execute_reply":"2024-03-29T04:18:35.879394Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf \ntf.test.is_built_with_cuda()","metadata":{"execution":{"iopub.status.busy":"2024-03-29T04:18:35.882417Z","iopub.execute_input":"2024-03-29T04:18:35.882775Z","iopub.status.idle":"2024-03-29T04:18:35.889805Z","shell.execute_reply.started":"2024-03-29T04:18:35.882744Z","shell.execute_reply":"2024-03-29T04:18:35.888702Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_parquet('/kaggle/input/hms-harmful-brain-activity-classification/train_eegs/1000913311.parquet')\nFEATS = df.columns\nprint(f'There are {len(FEATS)} raw eeg features')\nprint(list(FEATS))","metadata":{"execution":{"iopub.status.busy":"2024-03-29T04:18:35.891120Z","iopub.execute_input":"2024-03-29T04:18:35.891535Z","iopub.status.idle":"2024-03-29T04:18:35.906796Z","shell.execute_reply.started":"2024-03-29T04:18:35.891502Z","shell.execute_reply":"2024-03-29T04:18:35.905511Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('We will use the following subset of raw EEG features:')\nFEATS = ['Fp1','T3','C3','O1','Fp2','C4','T4','O2']\nFEAT2IDX = {x:y for x,y in zip(FEATS,range(len(FEATS)))}\nprint( list(FEATS) )","metadata":{"execution":{"iopub.status.busy":"2024-03-29T04:18:35.909084Z","iopub.execute_input":"2024-03-29T04:18:35.909394Z","iopub.status.idle":"2024-03-29T04:18:35.916214Z","shell.execute_reply.started":"2024-03-29T04:18:35.909367Z","shell.execute_reply":"2024-03-29T04:18:35.915080Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def eeg_from_parquet(parquet_path, display=False):\n    \n    # EXTRACT MIDDLE 50 SECONDS\n    eeg = pd.read_parquet(parquet_path, columns=FEATS)\n    rows = len(eeg)\n    offset = (rows-10_000)//2\n    eeg = eeg.iloc[offset:offset+10_000]\n    \n    if display: \n        plt.figure(figsize=(10,5))\n        offset = 0\n    \n    # CONVERT TO NUMPY\n    data = np.zeros((10_000,len(FEATS)))\n    for j,col in enumerate(FEATS):\n        \n        # FILL NAN\n        x = eeg[col].values.astype('float32')\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        data[:,j] = x\n        \n        if display: \n            if j!=0: offset += x.max()\n            plt.plot(range(10_000),x-offset,label=col)\n            offset -= x.min()\n            \n    if display:\n        plt.legend()\n        name = parquet_path.split('/')[-1]\n        name = name.split('.')[0]\n        plt.title(f'EEG {name}',size=16)\n        plt.show()\n        \n    return data","metadata":{"execution":{"iopub.status.busy":"2024-03-29T04:18:35.917944Z","iopub.execute_input":"2024-03-29T04:18:35.918252Z","iopub.status.idle":"2024-03-29T04:18:35.929790Z","shell.execute_reply.started":"2024-03-29T04:18:35.918218Z","shell.execute_reply":"2024-03-29T04:18:35.928181Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n\nall_eegs = {}\nDISPLAY = 4\nEEG_IDS = train.eeg_id.unique()\nPATH = '/kaggle/input/hms-harmful-brain-activity-classification/train_eegs/'\n\nfor i,eeg_id in enumerate(EEG_IDS):\n    if (i%100==0)&(i!=0): print(i,', ',end='') \n    \n    # SAVE EEG TO PYTHON DICTIONARY OF NUMPY ARRAYS\n    data = eeg_from_parquet(f'{PATH}{eeg_id}.parquet', display=i<DISPLAY)              \n    all_eegs[eeg_id] = data\n    \n    if i==DISPLAY:\n        if CREATE_EEGS:\n            print(f'Processing {train.eeg_id.nunique()} eeg parquets... ',end='')\n        else:\n            print(f'Reading {len(EEG_IDS)} eeg NumPys from disk.')\n            break\n            \nif CREATE_EEGS: \n    np.save('eegs',all_eegs)\nelse:\n    all_eegs = np.load('/kaggle/input/brain-eegs/eegs.npy',allow_pickle=True).item()","metadata":{"execution":{"iopub.status.busy":"2024-03-29T04:18:52.345968Z","iopub.execute_input":"2024-03-29T04:18:52.346322Z","iopub.status.idle":"2024-03-29T04:20:43.996628Z","shell.execute_reply.started":"2024-03-29T04:18:52.346293Z","shell.execute_reply":"2024-03-29T04:20:43.995651Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-03-29T04:21:55.423749Z","iopub.execute_input":"2024-03-29T04:21:55.424161Z","iopub.status.idle":"2024-03-29T04:21:55.612079Z","shell.execute_reply.started":"2024-03-29T04:21:55.424128Z","shell.execute_reply":"2024-03-29T04:21:55.610959Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from scipy.signal import butter, lfilter\n\ndef butter_lowpass_filter(data, cutoff_freq=20, sampling_rate=200, order=4):\n    nyquist = 0.5 * sampling_rate\n    normal_cutoff = cutoff_freq / nyquist\n    b, a = butter(order, normal_cutoff, btype='low', analog=False)\n    filtered_data = lfilter(b, a, data, axis=0)\n    return filtered_data","metadata":{"execution":{"iopub.status.busy":"2024-03-29T04:21:57.223538Z","iopub.execute_input":"2024-03-29T04:21:57.224059Z","iopub.status.idle":"2024-03-29T04:21:57.228823Z","shell.execute_reply.started":"2024-03-29T04:21:57.224032Z","shell.execute_reply":"2024-03-29T04:21:57.228140Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"FREQS = [1,2,4,8,16][::-1]\nx = [all_eegs[EEG_IDS[0]][:,0]]\nfor k in FREQS:\n    x.append( butter_lowpass_filter(x[0], cutoff_freq=k) )\n\nplt.figure(figsize=(20,20))\nplt.plot(range(10_000),x[0], label='without filter')\nfor k in range(1,len(x)):\n    plt.plot(range(10_000),x[k]-k*(x[0].max()-x[0].min()), label=f'with filter {FREQS[k-1]}Hz')\nplt.legend()\nplt.title('Butter Low-Pass Filter Examples',size=18)\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-03-29T04:21:58.724719Z","iopub.execute_input":"2024-03-29T04:21:58.725428Z","iopub.status.idle":"2024-03-29T04:21:59.288868Z","shell.execute_reply.started":"2024-03-29T04:21:58.725381Z","shell.execute_reply":"2024-03-29T04:21:59.286898Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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                 downsample=5): \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.downsample = downsample\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[:,::self.downsample,:], 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),10_000,8),dtype='float32')\n        y = np.zeros((len(indexes),6),dtype='float32')\n        \n        sample = np.zeros((10_000,X.shape[-1]))\n        for j,i in enumerate(indexes):\n            row = self.data.iloc[i]      \n            data = self.eegs[row.eeg_id]\n            \n            # FEATURE ENGINEER\n            sample[:,0] = data[:,FEAT2IDX['Fp1']] - data[:,FEAT2IDX['T3']]\n            sample[:,1] = data[:,FEAT2IDX['T3']] - data[:,FEAT2IDX['O1']]\n            \n            sample[:,2] = data[:,FEAT2IDX['Fp1']] - data[:,FEAT2IDX['C3']]\n            sample[:,3] = data[:,FEAT2IDX['C3']] - data[:,FEAT2IDX['O1']]\n            \n            sample[:,4] = data[:,FEAT2IDX['Fp2']] - data[:,FEAT2IDX['C4']]\n            sample[:,5] = data[:,FEAT2IDX['C4']] - data[:,FEAT2IDX['O2']]\n            \n            sample[:,6] = data[:,FEAT2IDX['Fp2']] - data[:,FEAT2IDX['T4']]\n            sample[:,7] = data[:,FEAT2IDX['T4']] - data[:,FEAT2IDX['O2']]\n            \n            # STANDARDIZE\n            sample = np.clip(sample,-1024,1024)\n            sample = np.nan_to_num(sample, nan=0) / 32.0\n            \n            # BUTTER LOW-PASS FILTER\n            sample = butter_lowpass_filter(sample)\n            \n            X[j,] = sample\n            if self.mode!='test':\n                y[j] = row[TARGETS]\n            \n        return X,y","metadata":{"execution":{"iopub.status.busy":"2024-03-29T04:22:01.223886Z","iopub.execute_input":"2024-03-29T04:22:01.224455Z","iopub.status.idle":"2024-03-29T04:22:01.240151Z","shell.execute_reply.started":"2024-03-29T04:22:01.224426Z","shell.execute_reply":"2024-03-29T04:22:01.238652Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gen = DataGenerator(train, shuffle=False)\n\nfor x,y in gen:\n    for k in range(4):\n        plt.figure(figsize=(20,4))\n        offset = 0\n        for j in range(x.shape[-1]):\n            if j!=0: offset -= x[k,:,j].min()\n            plt.plot(range(2_000),x[k,:,j]+offset,label=f'feature {j+1}')\n            offset += x[k,:,j].max()\n        tt = f'{y[k][0]:0.1f}'\n        for t in y[k][1:]:\n            tt += f', {t:0.1f}'\n        plt.title(f'EEG_Id = {EEG_IDS[k]}\\nTarget = {tt}',size=14)\n        plt.legend()\n        plt.show()\n    break","metadata":{"execution":{"iopub.status.busy":"2024-03-29T04:22:05.723868Z","iopub.execute_input":"2024-03-29T04:22:05.724535Z","iopub.status.idle":"2024-03-29T04:22:07.865633Z","shell.execute_reply.started":"2024-03-29T04:22:05.724497Z","shell.execute_reply":"2024-03-29T04:22:07.864173Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os, random\nos.environ[\"CUDA_VISIBLE_DEVICES\"]=\"0,1\"\nimport tensorflow as tf\nprint('TensorFlow version =',tf.__version__)\n\ndef seed_everything(seed: int = 42):\n    random.seed(seed)\n    np.random.seed(seed)\n    os.environ[\"PYTHONHASHSEED\"] = str(seed)\n    tf.random.set_seed(seed)\nSEED = 42\nseed_everything(SEED)\n    \n# USE MULTIPLE GPUS\ngpus = tf.config.list_physical_devices('GPU')\nif len(gpus)<=1: \n    strategy = tf.distribute.OneDeviceStrategy(device=\"/gpu:0\")\n    print(f'Using {len(gpus)} GPU')\nelse: \n    strategy = tf.distribute.MirroredStrategy()\n    print(f'Using {len(gpus)} GPUs')","metadata":{"execution":{"iopub.status.busy":"2024-03-29T04:22:09.353145Z","iopub.execute_input":"2024-03-29T04:22:09.353666Z","iopub.status.idle":"2024-03-29T04:22:09.370563Z","shell.execute_reply.started":"2024-03-29T04:22:09.353623Z","shell.execute_reply":"2024-03-29T04:22:09.369412Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# USE MIXED PRECISION\nMIX = True\nif MIX:\n    tf.config.optimizer.set_experimental_options({\"auto_mixed_precision\": True})\n    print('Mixed precision enabled')\nelse:\n    print('Using full precision')","metadata":{"execution":{"iopub.status.busy":"2024-03-29T04:22:11.491037Z","iopub.execute_input":"2024-03-29T04:22:11.491499Z","iopub.status.idle":"2024-03-29T04:22:11.498306Z","shell.execute_reply.started":"2024-03-29T04:22:11.491465Z","shell.execute_reply":"2024-03-29T04:22:11.496824Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# TRAIN SCHEDULE\ndef lrfn(epoch):\n        return [1e-3,1e-3,1e-4,1e-4,1e-5][epoch]\nLR = tf.keras.callbacks.LearningRateScheduler(lrfn, verbose = True)\nEPOCHS = 5","metadata":{"execution":{"iopub.status.busy":"2024-03-29T04:22:12.924897Z","iopub.execute_input":"2024-03-29T04:22:12.925738Z","iopub.status.idle":"2024-03-29T04:22:12.930978Z","shell.execute_reply.started":"2024-03-29T04:22:12.925696Z","shell.execute_reply":"2024-03-29T04:22:12.929782Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.layers import Input, Dense, Multiply, Add, Conv1D, Concatenate, Lambda\n\ndef wave_block(x, filters, kernel_size, n):\n    dilation_rates = [2**i for i in range(n)]\n    print('x1',x.shape)\n    x = Conv1D(filters = filters,\n               kernel_size = 1,\n               padding = 'same')(x)\n\n    res_x = x\n    for dilation_rate in dilation_rates:\n        tanh_out = Conv1D(filters = filters,\n                          kernel_size = kernel_size,\n                          padding = 'same', \n                          activation = 'tanh', \n                          dilation_rate = dilation_rate)(x)\n        sigm_out = Conv1D(filters = filters,\n                          kernel_size = kernel_size,\n                          padding = 'same',\n                          activation = 'sigmoid', \n                          dilation_rate = dilation_rate)(x)\n        x = Multiply()([tanh_out, sigm_out])\n        x = Conv1D(filters = filters,\n                   kernel_size = 1,\n                   padding = 'same')(x)\n        res_x = Add()([res_x, x])\n    return res_x","metadata":{"execution":{"iopub.status.busy":"2024-03-29T04:26:51.949457Z","iopub.execute_input":"2024-03-29T04:26:51.949888Z","iopub.status.idle":"2024-03-29T04:26:51.959194Z","shell.execute_reply.started":"2024-03-29T04:26:51.949858Z","shell.execute_reply":"2024-03-29T04:26:51.957532Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Define Inception Block","metadata":{}},{"cell_type":"code","source":"def SamePadConv(x, out_channels, kernel_size, dilation=1, stride=1, bias=True):\n    receptive_field = (kernel_size - 1) * dilation + 1\n    remove = 1 if receptive_field % 2 == 0 else 0\n    conv = tf.keras.layers.Conv1D(out_channels, kernel_size, strides=stride, padding='same', dilation_rate=dilation, use_bias=bias)(x)\n    if remove > 0:\n        conv = conv[:, :, :-remove]\n    return conv\n\ndef BasicUnit(x, in_channels, out_channels, index, kernel_size):\n    last_idx = max(0, index - 1)\n    base_reception = 2 * kernel_size - 1\n    last_reception = base_reception**last_idx\n    x = SamePadConv(x, out_channels, kernel_size, dilation=last_reception)\n    x = SamePadConv(x, out_channels, kernel_size, dilation=last_reception)\n    x = Lambda(lambda x: tf.nn.gelu(x))(x)\n    return x\n\ndef InceptionBlock(x, in_channels, out_channels, index, residual=True, stride=1, hidden_channels=64, kernel_sizes=[3, 5]):\n    conv_layers_outputs = [BasicUnit(x, in_channels, hidden_channels, index, ks) for ks in kernel_sizes]\n    max_pool_layer = tf.keras.layers.MaxPooling1D(pool_size=3, strides=1, padding='same')(x)\n    max_pool_layer = tf.keras.layers.Conv1D(hidden_channels, 1)(max_pool_layer)\n    combined = tf.keras.layers.Concatenate(axis=-1)(conv_layers_outputs + [max_pool_layer])\n    aggregated = tf.keras.layers.Conv1D(out_channels, 3, padding='same')(combined)\n    if residual:\n        residual_connection = tf.keras.layers.Conv1D(out_channels, 1)(x)\n        aggregated += residual_connection\n    return aggregated\n\n\n","metadata":{"execution":{"iopub.status.busy":"2024-03-29T04:27:15.524866Z","iopub.execute_input":"2024-03-29T04:27:15.525401Z","iopub.status.idle":"2024-03-29T04:27:15.541108Z","shell.execute_reply.started":"2024-03-29T04:27:15.525356Z","shell.execute_reply":"2024-03-29T04:27:15.539111Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Define Dilated Inception Model","metadata":{}},{"cell_type":"code","source":"def build_model():\n        \n    # INPUT \n    inp = tf.keras.Input(shape=(2_000,8))\n    inp2 = tf.keras.Input(shape=(2000, 1))\n    dropout = 0.1\n    \n    input_shape = (None, 2000, 64)\n    channels = [64] * 3 + [320]\n\n    kernel_sizes=[2,5,8]\n    x = tf.keras.layers.Dense(64)(inp2)\n    for i, channel in enumerate(channels):\n        x = InceptionBlock(x, channels[i-1] if i > 0 else input_shape[-1], \n                           channel, i+1, residual=True, hidden_channels=channel // 4 if i > 0 else input_shape[-1] // 4, \n                           kernel_sizes=kernel_sizes)\n    x = tf.keras.layers.SpatialDropout1D(dropout)(x)\n    x = tf.keras.layers.GRU(128, \n                            dropout = dropout, \n                            return_sequences = True, \n                            kernel_initializer = 'orthogonal')(x)\n    model1 = tf.keras.Model(inputs=inp2, outputs=x)\n\n\n    # LEFT TEMPORAL CHAIN\n    x1 = model1(inp[:,:,0:1]) # shape - (none, 2000, 64)\n    # inp[:,:,0:1].shape - (none, 2000, 1)\n    x1 = tf.keras.layers.GlobalAveragePooling1D()(x1)\n    x2 = model1(inp[:,:,1:2])\n    x2 = tf.keras.layers.GlobalAveragePooling1D()(x2)\n    z1 = tf.keras.layers.Average()([x1,x2])\n\n    # LEFT PARASAGITTAL CHAIN\n    x1 = model1(inp[:,:,2:3])\n    x1 = tf.keras.layers.GlobalAveragePooling1D()(x1)\n    x2 = model1(inp[:,:,3:4])\n    x2 = tf.keras.layers.GlobalAveragePooling1D()(x2)\n    z2 = tf.keras.layers.Average()([x1,x2])\n    \n    # RIGHT PARASAGITTAL CHAIN\n    x1 = model1(inp[:,:,4:5])\n    x1 = tf.keras.layers.GlobalAveragePooling1D()(x1)\n    x2 = model1(inp[:,:,5:6])\n    x2 = tf.keras.layers.GlobalAveragePooling1D()(x2)\n    z3 = tf.keras.layers.Average()([x1,x2])\n    \n    # RIGHT TEMPORAL CHAIN\n    x1 = model1(inp[:,:,6:7])\n    x1 = tf.keras.layers.GlobalAveragePooling1D()(x1)\n    x2 = model1(inp[:,:,7:8])\n    x2 = tf.keras.layers.GlobalAveragePooling1D()(x2)\n    z4 = tf.keras.layers.Average()([x1,x2])\n    \n    ## InceptionTime Multivariate\n    # COMBINE CHAINS\n\n    y = tf.keras.layers.Concatenate()([z1,z2,z3,z4])\n    y = tf.keras.layers.Dense(64, activation='relu')(y)\n    y = tf.keras.layers.Dense(6,activation='softmax', dtype='float32')(y)\n    \n    # COMPILE MODEL\n    model = tf.keras.Model(inputs=inp, outputs=y)\n    opt = tf.keras.optimizers.Adam(learning_rate = 1e-3)\n    loss = tf.keras.losses.KLDivergence()\n    model.compile(loss=loss, optimizer = opt)\n\n    return model","metadata":{"execution":{"iopub.status.busy":"2024-03-29T04:27:17.338004Z","iopub.execute_input":"2024-03-29T04:27:17.338474Z","iopub.status.idle":"2024-03-29T04:27:17.356710Z","shell.execute_reply.started":"2024-03-29T04:27:17.338441Z","shell.execute_reply":"2024-03-29T04:27:17.355613Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"VERBOSE = 1\nFOLDS_TO_TRAIN = 5\nif not os.path.exists('WaveNet_Model'):\n    os.makedirs('WaveNet_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    with strategy.scope():\n        model = build_model()\n    if TRAIN_MODEL:\n        model.fit(train_gen, verbose=VERBOSE,\n              validation_data = valid_gen,\n              epochs=EPOCHS, callbacks = [LR])\n        model.save_weights(f'/kaggle/input/dilated-inception-gru-beck/WaveNet_fold{i}_inception_wav.h5')\n    else:\n        model.load_weights(f'/kaggle/input/dilated-inception-gru-beck/WaveNet_fold{i}_inception_wav.h5')\n    \n    # WAVENET OOF\n    oof = model.predict(valid_gen, verbose=VERBOSE)\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":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import sys\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 WaveNet Raw EEG =',cv)","metadata":{"execution":{"iopub.status.busy":"2024-03-29T04:18:39.988542Z","iopub.status.idle":"2024-03-29T04:18:39.989157Z","shell.execute_reply.started":"2024-03-29T04:18:39.988865Z","shell.execute_reply":"2024-03-29T04:18:39.988893Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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 Train Means =',cv)","metadata":{"execution":{"iopub.status.busy":"2024-03-29T04:18:39.990473Z","iopub.status.idle":"2024-03-29T04:18:39.990957Z","shell.execute_reply.started":"2024-03-29T04:18:39.990725Z","shell.execute_reply":"2024-03-29T04:18:39.990747Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-03-29T04:18:39.992134Z","iopub.status.idle":"2024-03-29T04:18:39.992626Z","shell.execute_reply.started":"2024-03-29T04:18:39.992405Z","shell.execute_reply":"2024-03-29T04:18:39.992425Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"all_eegs2 = {}\nDISPLAY = 1\nEEG_IDS2 = test.eeg_id.unique()\nPATH2 = '/kaggle/input/hms-harmful-brain-activity-classification/test_eegs/'\n\nprint('Processing Test EEG parquets...'); print()\nfor i,eeg_id in enumerate(EEG_IDS2):\n        \n    # SAVE EEG TO PYTHON DICTIONARY OF NUMPY ARRAYS\n    data = eeg_from_parquet(f'{PATH2}{eeg_id}.parquet', i<DISPLAY)\n    all_eegs2[eeg_id] = data","metadata":{"execution":{"iopub.status.busy":"2024-03-29T04:18:39.994553Z","iopub.status.idle":"2024-03-29T04:18:39.995126Z","shell.execute_reply.started":"2024-03-29T04:18:39.994877Z","shell.execute_reply":"2024-03-29T04:18:39.994901Z"},"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    if TRAIN_MODEL:\n        model.load_weights(f'/kaggle/input/inceptionblock2/WaveNet_fold{i}_inception_wav.h5')\n    else:\n        model.load_weights(f'/kaggle/input/inceptionblock2/WaveNet_fold{i}_inception_wav.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":{"execution":{"iopub.status.busy":"2024-03-29T04:18:39.996140Z","iopub.status.idle":"2024-03-29T04:18:39.996639Z","shell.execute_reply.started":"2024-03-29T04:18:39.996426Z","shell.execute_reply":"2024-03-29T04:18:39.996444Z"},"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":{"execution":{"iopub.status.busy":"2024-03-29T04:18:39.998090Z","iopub.status.idle":"2024-03-29T04:18:39.998574Z","shell.execute_reply.started":"2024-03-29T04:18:39.998346Z","shell.execute_reply":"2024-03-29T04:18:39.998367Z"},"trusted":true},"execution_count":null,"outputs":[]}]}