{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":59093,"databundleVersionId":7469972,"sourceType":"competition"},{"sourceId":8343809,"sourceType":"datasetVersion","datasetId":4956133},{"sourceId":8351009,"sourceType":"datasetVersion","datasetId":4961634},{"sourceId":6127,"sourceType":"modelInstanceVersion","modelInstanceId":4598}],"dockerImageVersionId":30698,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nimport matplotlib.pyplot as plt\nimport os \nimport numpy as np\nimport tensorflow as tf\nimport keras\nfrom tensorflow.keras import Model\nfrom tensorflow.keras.layers import Dense, GlobalAveragePooling2D, Lambda\nfrom tensorflow.keras.applications import EfficientNetB2\nfrom tensorflow.keras.layers import Permute\nfrom tensorflow.keras.layers import Layer\nimport keras_cv","metadata":{"execution":{"iopub.status.busy":"2024-05-10T08:20:28.675861Z","iopub.execute_input":"2024-05-10T08:20:28.676256Z","iopub.status.idle":"2024-05-10T08:20:51.023670Z","shell.execute_reply.started":"2024-05-10T08:20:28.676225Z","shell.execute_reply":"2024-05-10T08:20:51.022320Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Montages","metadata":{}},{"cell_type":"code","source":"NAMES = ['LL', 'LP', 'RL', 'RP', 'C']\n\nIMP_FEATS = ['Fp1', 'F3', 'C3', 'P3', 'F7', 'T3',\n             'T5','O1', 'Fp2', 'F4', 'C4', 'P4',\n             'F8', 'T4', 'T6', 'O2', 'Fz', 'Cz', 'Pz']\n\nIMP_FEATS_index = {y:x for x,y in enumerate(IMP_FEATS)}\n\nBANANA = [['Fp1','F7','T3','T5','O1'],\n         ['Fp1','F3','C3','P3','O1'],\n         ['Fp2','F8','T4','T6','O2'],\n         ['Fp2','F4','C4','P4','O2']]\n\nCENTER = ['Fz', 'Cz', 'Pz']","metadata":{"execution":{"iopub.status.busy":"2024-05-10T08:20:51.025962Z","iopub.execute_input":"2024-05-10T08:20:51.026672Z","iopub.status.idle":"2024-05-10T08:20:51.035467Z","shell.execute_reply.started":"2024-05-10T08:20:51.026637Z","shell.execute_reply":"2024-05-10T08:20:51.033836Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data Loader","metadata":{}},{"cell_type":"code","source":"TARS = {'Seizure':0, 'LPD':1, 'GPD':2, 'LRDA':3, 'GRDA':4, 'Other':5}\nTARS2 = {x:y for y,x in TARS.items()}\nfile_path = '/kaggle/input/hms-harmful-brain-activity-classification/test_eegs/'\nclass DataGenerator(tf.keras.utils.Sequence):\n    'Generate data for keras'\n    def __init__(self, data, batch_size = 32, shuffle = False, mode='train', IMP_FEATS = IMP_FEATS ,\n                 file_path = file_path, BANANA = BANANA, CENTER = CENTER):\n\n        self.data = data\n        self.batch_size = batch_size\n        self.shuffle = shuffle\n        self.mode = mode\n        self.BANANA = BANANA\n        self.CENTER = CENTER\n        self.IMP_FEATS = IMP_FEATS\n        if isinstance(file_path, str):\n            self.file_path = file_path\n        else: print('file_path must be a path to the training file signals in parquet format')\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 on_epoch_end(self):\n        'Updates indexes after each epoch'\n        self.indexes = np.arange(len(self.data))\n        if self.shuffle == True: np.random.shuffle(self.indexes)\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        X1, y = self.__data_generation(indexes)\n        return X1, y\n\n\n    def __data_generation(self, indexes):\n        'Generates data containing batch_size samples'\n\n        X1 = np.zeros((len(indexes), 10000, 18, 1), dtype='float32')\n        y = np.zeros((len(indexes),6),dtype='float32')\n\n        for j,i in enumerate(indexes):\n\n            row = self.data.iloc[i]\n            eeg = pd.read_parquet(f'{self.file_path}{row.eeg_id}.parquet', columns = self.IMP_FEATS)\n            middle = (len(eeg)-10_000)//2\n            eeg = eeg.iloc[middle:middle+10_000]\n            count = 0\n            # Calculate BANANA Features\n            for k in range(4):\n                COLS = self.BANANA[k]\n                coeff = []\n                for kk in range(4):\n                    \n                    # Calculate the differences\n                    x = eeg[COLS[kk]].values - eeg[COLS[kk+1]].values\n                    \n                    # Standardize\n                    x = np.clip(x, -1024, 1024)\n                    x = np.nan_to_num(x, nan = 0) / 32.0\n                    \n                    # Add dimension to make it compatible with cwt layer input\n                    X1[j,:,k + kk + count, :] = np.expand_dims(x, axis = -1)\n                    \n                count += 3\n            # Calculate CENTER Features\n            for m in range(2):\n                z = eeg[self.CENTER[m]].values - eeg[self.CENTER[m + 1]].values\n                \n                z = np.clip(z, -1024, 1024)\n                z = np.nan_to_num(z, nan = 0) / 32.0\n                \n                X1[j,:,-1 - m, :] = np.expand_dims(z, axis = -1)\n                \n            if self.mode != 'test':\n                y[j,] = row[TARGETS]\n\n        return X1, y","metadata":{"execution":{"iopub.status.busy":"2024-05-10T08:20:51.043721Z","iopub.execute_input":"2024-05-10T08:20:51.044633Z","iopub.status.idle":"2024-05-10T08:20:51.070844Z","shell.execute_reply.started":"2024-05-10T08:20:51.044485Z","shell.execute_reply":"2024-05-10T08:20:51.069662Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# CWT Layer","metadata":{}},{"cell_type":"code","source":"%cd /kaggle/input/cmorlet-tensorflow-3/cmorlet-tensorflow-3/CWT","metadata":{"execution":{"iopub.status.busy":"2024-05-10T08:20:51.072210Z","iopub.execute_input":"2024-05-10T08:20:51.072654Z","iopub.status.idle":"2024-05-10T08:20:51.094245Z","shell.execute_reply.started":"2024-05-10T08:20:51.072615Z","shell.execute_reply":"2024-05-10T08:20:51.093138Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import cwt","metadata":{"execution":{"iopub.status.busy":"2024-05-10T08:20:51.095809Z","iopub.execute_input":"2024-05-10T08:20:51.096223Z","iopub.status.idle":"2024-05-10T08:20:51.116629Z","shell.execute_reply.started":"2024-05-10T08:20:51.096187Z","shell.execute_reply":"2024-05-10T08:20:51.115322Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Magnitude Layer","metadata":{}},{"cell_type":"code","source":"@keras.saving.register_keras_serializable()\nclass Magnitude_of_Complex_CWT(Layer):\n\n    \"\"\"\n    Custom Keras layer to compute the magnitude of complex Tensor at the last axis.\n    \"\"\"\n    def __init__(self, magnitude = True, **kwargs):\n        super().__init__(**kwargs)\n        self.magnitude = magnitude\n        \n    def call(self, inputs):\n        if self.magnitude:\n            real_part = inputs[:, :, :, 0]\n            imag_part = inputs[:, :, :, 1]\n            result = tf.math.sqrt(tf.math.square(real_part) + tf.math.square(imag_part))\n            result = tf.expand_dims(result, axis=-1)\n            return result\n        else:\n            print(\"Layer is not activated!\")\n            \n    def get_config(self):\n        return {\"magnitude\": self.magnitude}","metadata":{"execution":{"iopub.status.busy":"2024-05-10T08:20:51.117935Z","iopub.execute_input":"2024-05-10T08:20:51.118273Z","iopub.status.idle":"2024-05-10T08:20:51.129149Z","shell.execute_reply.started":"2024-05-10T08:20:51.118244Z","shell.execute_reply":"2024-05-10T08:20:51.127644Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Scale Layer","metadata":{}},{"cell_type":"code","source":"@keras.saving.register_keras_serializable()\nclass scale_to_255(Layer):\n    \"\"\"\n    Layer to Normalize the Image between values 0 and 255\n    \"\"\"\n    def __init__(self, scale = True, **kwargs):\n        super().__init__(**kwargs)\n        self.scale = scale\n\n    def call(self, x):\n        if self.scale:\n            min_val = tf.reduce_min(x)\n            max_val = tf.reduce_max(x)\n            return 255.0 * (x - min_val) / (max_val - min_val + 1e-7)\n        else:\n            print(\"layer is not acitvated!\")\n            \n    def get_config(self):\n        return {\"scale\": self.scale}","metadata":{"execution":{"iopub.status.busy":"2024-05-10T08:20:51.130602Z","iopub.execute_input":"2024-05-10T08:20:51.131004Z","iopub.status.idle":"2024-05-10T08:20:51.146839Z","shell.execute_reply.started":"2024-05-10T08:20:51.130973Z","shell.execute_reply":"2024-05-10T08:20:51.145532Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Initialize the 3 custom Layers for Training","metadata":{}},{"cell_type":"markdown","source":"## cwt","metadata":{}},{"cell_type":"code","source":"cwt_layer = cwt.ComplexMorletCWT(\n    wavelet_width=7,  # Example wavelet width (adjust as needed)\n    fs=200,            # Example sampling frequency (adjust as needed)\n    stride=16,\n    border_crop=1,\n    lower_freq=0.5,       # Example lower frequency (adjust as needed)\n    upper_freq=40,      # Example upper frequency (adjust as needed)\n    n_scales=40,        # Example number of scales (adjust as needed)\n    trainable=False     # Example setting for wavelet width trainability (adjust as needed)\n)","metadata":{"execution":{"iopub.status.busy":"2024-05-10T08:20:51.148282Z","iopub.execute_input":"2024-05-10T08:20:51.149085Z","iopub.status.idle":"2024-05-10T08:20:51.266977Z","shell.execute_reply.started":"2024-05-10T08:20:51.149004Z","shell.execute_reply":"2024-05-10T08:20:51.265870Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Scale and Magnitude","metadata":{}},{"cell_type":"code","source":"# Initialize Instance for Magnitude_of_Complex_CWT Layer\nmos = Magnitude_of_Complex_CWT()\n# Initialize Instance for scale_to_255 Layer\nscale = scale_to_255()","metadata":{"execution":{"iopub.status.busy":"2024-05-10T08:20:51.270386Z","iopub.execute_input":"2024-05-10T08:20:51.270803Z","iopub.status.idle":"2024-05-10T08:20:51.278247Z","shell.execute_reply.started":"2024-05-10T08:20:51.270772Z","shell.execute_reply":"2024-05-10T08:20:51.276851Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load the Model","metadata":{}},{"cell_type":"code","source":"eff_net_model = keras_cv.models.ImageClassifier.from_preset(\"efficientnetv2_b2_imagenet\", num_classes = 6)","metadata":{"execution":{"iopub.status.busy":"2024-05-10T08:20:51.279642Z","iopub.execute_input":"2024-05-10T08:20:51.280002Z","iopub.status.idle":"2024-05-10T08:20:57.672796Z","shell.execute_reply.started":"2024-05-10T08:20:51.279973Z","shell.execute_reply":"2024-05-10T08:20:57.671756Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def build_model_MK():\n    # Addiding the Last Dimension for compatibility with cwt_layer input shape which represent the channel axis\n    inp = tf.keras.Input(shape = (10000, 18, 1))\n    \n    scalogram_0 = cwt_layer(inp[:,:,0])\n    scalogram_0 = mos(scalogram_0)\n    scalogram_1 = cwt_layer(inp[:,:,1])\n    scalogram_1 = mos(scalogram_1)\n    scalogram_2 = cwt_layer(inp[:,:,2])\n    scalogram_2 = mos(scalogram_2)\n    scalogram_3 = cwt_layer(inp[:,:,3])\n    scalogram_3 = mos(scalogram_3)\n    scalogram_4 = cwt_layer(inp[:,:,4])\n    scalogram_4 = mos(scalogram_4)\n    scalogram_5 = cwt_layer(inp[:,:,5])\n    scalogram_5 = mos(scalogram_5)\n    scalogram_6 = cwt_layer(inp[:,:,6])\n    scalogram_6 = mos(scalogram_6)\n    scalogram_7 = cwt_layer(inp[:,:,7])\n    scalogram_7 = mos(scalogram_7)\n    scalogram_8 = cwt_layer(inp[:,:,8])\n    scalogram_8 = mos(scalogram_8)\n    scalogram_9 = cwt_layer(inp[:,:,9])\n    scalogram_9 = mos(scalogram_9)\n    scalogram_10 = cwt_layer(inp[:,:,10])\n    scalogram_10 = mos(scalogram_10)\n    scalogram_11 = cwt_layer(inp[:,:,11])\n    scalogram_11 = mos(scalogram_11)\n    scalogram_12 = cwt_layer(inp[:,:,12])\n    scalogram_12 = mos(scalogram_12)\n    scalogram_13 = cwt_layer(inp[:,:,13])\n    scalogram_13 = mos(scalogram_13)\n    scalogram_14 = cwt_layer(inp[:,:,14])\n    scalogram_14 = mos(scalogram_14)\n    scalogram_15 = cwt_layer(inp[:,:,15])\n    scalogram_15 = mos(scalogram_15)\n    scalogram_16 = cwt_layer(inp[:,:,16])\n    scalogram_16 = mos(scalogram_16)\n    scalogram_17 = cwt_layer(inp[:,:,17])\n    scalogram_17 = mos(scalogram_17)\n    x1 = tf.keras.layers.Concatenate(axis = 2)([scalogram_0, scalogram_1,scalogram_2, scalogram_3,\n                                              scalogram_4, scalogram_5, scalogram_6, scalogram_7,\n                                              scalogram_8, scalogram_9, scalogram_10, scalogram_11,\n                                              scalogram_12, scalogram_13, scalogram_14, scalogram_15,\n                                               scalogram_16, scalogram_17])\n    \n    x2 = Permute((2,1,3))(x1)\n    x3 = tf.keras.layers.Resizing(height=512, width=512, interpolation='nearest')(x2)\n    x4 = scale(x3)\n    x5 = tf.keras.layers.Concatenate(axis=3)([x4,x4,x4])\n    \n    out = eff_net_model(x5)\n    \n    final_model = Model(inputs = inp, outputs = out)\n    \n    opt = tf.keras.optimizers.Adam(learning_rate=1e-3)\n    loss = tf.keras.losses.KLDivergence()\n    final_model.compile(loss=loss, optimizer = opt)\n    \n    return final_model","metadata":{"execution":{"iopub.status.busy":"2024-05-10T08:20:57.674140Z","iopub.execute_input":"2024-05-10T08:20:57.674567Z","iopub.status.idle":"2024-05-10T08:20:57.694026Z","shell.execute_reply.started":"2024-05-10T08:20:57.674537Z","shell.execute_reply":"2024-05-10T08:20:57.692792Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = build_model_MK()\nmodel.load_weights(\"/kaggle/input/effnet-keras-hms-models/Eff_Net_v10_f1.keras\")","metadata":{"execution":{"iopub.status.busy":"2024-05-10T08:20:57.696371Z","iopub.execute_input":"2024-05-10T08:20:57.696794Z","iopub.status.idle":"2024-05-10T08:21:09.270359Z","shell.execute_reply.started":"2024-05-10T08:20:57.696750Z","shell.execute_reply":"2024-05-10T08:21:09.269070Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Make Prediction on Test Data","metadata":{}},{"cell_type":"markdown","source":"## Read Test Data","metadata":{}},{"cell_type":"code","source":"# Reading Testing data\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-05-10T08:21:09.271988Z","iopub.execute_input":"2024-05-10T08:21:09.272338Z","iopub.status.idle":"2024-05-10T08:21:09.309641Z","shell.execute_reply.started":"2024-05-10T08:21:09.272309Z","shell.execute_reply":"2024-05-10T08:21:09.308139Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Generate Test data ","metadata":{}},{"cell_type":"code","source":"test_gen = DataGenerator(test, shuffle = False, batch_size = 64, mode = 'test')","metadata":{"execution":{"iopub.status.busy":"2024-05-10T08:21:09.311275Z","iopub.execute_input":"2024-05-10T08:21:09.311687Z","iopub.status.idle":"2024-05-10T08:21:09.317110Z","shell.execute_reply.started":"2024-05-10T08:21:09.311653Z","shell.execute_reply":"2024-05-10T08:21:09.315949Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Predictions","metadata":{}},{"cell_type":"code","source":"pred = model.predict(test_gen, verbose=1)","metadata":{"execution":{"iopub.status.busy":"2024-05-10T08:21:09.318900Z","iopub.execute_input":"2024-05-10T08:21:09.319251Z","iopub.status.idle":"2024-05-10T08:21:14.487404Z","shell.execute_reply.started":"2024-05-10T08:21:09.319223Z","shell.execute_reply":"2024-05-10T08:21:14.486367Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Submit to CSV file","metadata":{}},{"cell_type":"code","source":"TARGETS = ['seizure_vote', 'lpd_vote', 'gpd_vote', 'lrda_vote', 'grda_vote', 'other_vote']\nsub = pd.DataFrame({'eeg_id':test.eeg_id.values})\nsub[TARGETS] = pred\nsub.to_csv('/kaggle/working/submission.csv',index=False)\nprint('Submissionn shape',sub.shape)\nsub.head()","metadata":{"execution":{"iopub.status.busy":"2024-05-10T08:21:14.488998Z","iopub.execute_input":"2024-05-10T08:21:14.489319Z","iopub.status.idle":"2024-05-10T08:21:14.514608Z","shell.execute_reply.started":"2024-05-10T08:21:14.489293Z","shell.execute_reply":"2024-05-10T08:21:14.513338Z"},"trusted":true},"execution_count":null,"outputs":[]}]}