{"metadata":{"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":59093,"databundleVersionId":7469972,"sourceType":"competition"},{"sourceId":7392775,"sourceType":"datasetVersion","datasetId":4297782},{"sourceId":7402356,"sourceType":"datasetVersion","datasetId":4304475},{"sourceId":7450712,"sourceType":"datasetVersion","datasetId":4336944},{"sourceId":7570342,"sourceType":"datasetVersion","datasetId":4407194},{"sourceId":7581697,"sourceType":"datasetVersion","datasetId":4413439},{"sourceId":7581715,"sourceType":"datasetVersion","datasetId":4413451},{"sourceId":7581720,"sourceType":"datasetVersion","datasetId":4413454},{"sourceId":7752462,"sourceType":"datasetVersion","datasetId":4382744},{"sourceId":7776446,"sourceType":"datasetVersion","datasetId":4550181},{"sourceId":7818976,"sourceType":"datasetVersion","datasetId":4417235},{"sourceId":158958765,"sourceType":"kernelVersion"},{"sourceId":159333316,"sourceType":"kernelVersion"},{"sourceId":159396114,"sourceType":"kernelVersion"},{"sourceId":160674831,"sourceType":"kernelVersion"},{"sourceId":160700706,"sourceType":"kernelVersion"},{"sourceId":161586765,"sourceType":"kernelVersion"}],"dockerImageVersionId":30636,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true},"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":101.739864,"end_time":"2024-03-03T17:15:15.283704","environment_variables":{},"exception":null,"input_path":"__notebook__.ipynb","output_path":"__notebook__.ipynb","parameters":{},"start_time":"2024-03-03T17:13:33.54384","version":"2.4.0"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Model 1","metadata":{}},{"cell_type":"code","source":"import os, random\nimport tensorflow as tf\nimport tensorflow\nimport tensorflow.keras.backend as K\nimport pandas as pd, numpy as np\nimport matplotlib.pyplot as plt\nfrom tensorflow.keras.models import load_model\nimport albumentations as albu\nfrom scipy.signal import butter, lfilter\nimport librosa\nfrom sklearn.model_selection import KFold, GroupKFold\nimport tensorflow.keras.backend as K, gc\nfrom tensorflow.keras.layers import Input, Dense, Multiply, Add, Conv1D, Concatenate, LayerNormalization","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:32:32.664287Z","iopub.execute_input":"2024-03-13T10:32:32.664962Z","iopub.status.idle":"2024-03-13T10:32:53.195227Z","shell.execute_reply.started":"2024-03-13T10:32:32.66493Z","shell.execute_reply":"2024-03-13T10:32:53.194386Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"LOAD_BACKBONE_FROM = '/kaggle/input/efficientnetb-tf-keras/EfficientNetB2.h5'\nLOAD_MODELS_FROM = '/kaggle/input/features-head-starter-models'\nTARGETS = ['seizure_vote', 'lpd_vote', 'gpd_vote', 'lrda_vote', 'grda_vote', 'other_vote']","metadata":{"papermill":{"duration":15.019425,"end_time":"2024-03-03T17:13:52.258732","exception":false,"start_time":"2024-03-03T17:13:37.239307","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-03-13T10:32:53.196986Z","iopub.execute_input":"2024-03-13T10:32:53.197521Z","iopub.status.idle":"2024-03-13T10:32:53.202207Z","shell.execute_reply.started":"2024-03-13T10:32:53.197493Z","shell.execute_reply":"2024-03-13T10:32:53.201182Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Set random seeds\nnp.random.seed(42)\nrandom.seed(42)\ntf.random.set_seed(42)","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:32:53.203432Z","iopub.execute_input":"2024-03-13T10:32:53.203823Z","iopub.status.idle":"2024-03-13T10:32:53.215481Z","shell.execute_reply.started":"2024-03-13T10:32:53.203786Z","shell.execute_reply":"2024-03-13T10:32:53.214618Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# USE SINGLE GPU, MULTIPLE GPUS \ngpus = tf.config.list_physical_devices('GPU')\n# WE USE MIXED PRECISION\ntf.config.optimizer.set_experimental_options({\"auto_mixed_precision\": True})\nif len(gpus)>1:\n    strategy = tf.distribute.MirroredStrategy()\n    print(f'Using {len(gpus)} GPUs')\nelse:\n    strategy = tf.distribute.OneDeviceStrategy(device=\"/gpu:0\")\n    print(f'Using {len(gpus)} GPU')","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:32:53.216594Z","iopub.execute_input":"2024-03-13T10:32:53.216888Z","iopub.status.idle":"2024-03-13T10:32:55.085807Z","shell.execute_reply.started":"2024-03-13T10:32:53.216841Z","shell.execute_reply":"2024-03-13T10:32:55.08484Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"FEATS2 = ['Fp1','T3','C3','O1','Fp2','C4','T4','O2']\nFEAT2IDX = {x:y for x,y in zip(FEATS2,range(len(FEATS2)))}\nFEATS = [['Fp1','F7','T3','T5','O1'],\n         ['Fp1','F3','C3','P3','O1'],\n         ['Fp2','F8','T4','T6','O2'],\n         ['Fp2','F4','C4','P4','O2']]\nUSE_PROCESSED = True # Use processed downsampled Raw EEG \n    \nclass DataGenerator():\n    'Generates data for Keras'\n    def __init__(self, data, specs=None, eeg_specs=None, raw_eegs=None , augment=False, \n                 mode='train', data_type='KER'): \n        self.data = data\n        self.augment = augment\n        self.mode = mode\n        self.data_type = data_type\n        self.specs = specs\n        self.eeg_specs = eeg_specs\n        self.raw_eegs = raw_eegs\n        self.on_epoch_end()\n        \n    def __len__(self):\n        return self.data.shape[0]\n\n    def __getitem__(self, index):\n        X, y = self.data_generation(index)\n        if self.augment: X = self.augmentation(X)\n        return X, y\n    \n    def __call__(self):\n        for i in range(self.__len__()):\n            yield self.__getitem__(i)\n            \n            if i == self.__len__()-1:\n                self.on_epoch_end()\n                \n    def on_epoch_end(self):\n        if self.mode=='train': \n            self.data = self.data.sample(frac=1).reset_index(drop=True)\n    \n    def data_generation(self, index):\n        if self.data_type == 'KE':\n            X,y = self.generate_all_specs(index)\n        elif self.data_type == 'E' or self.data_type == 'K':\n            X,y = self.generate_specs(index)\n        elif self.data_type == 'R':\n            X,y = self.generate_raw(index)\n        elif self.data_type in ['ER','KR']:\n            X1,y = self.generate_specs(index)\n            X2,y = self.generate_raw(index)\n            X = (X1,X2)\n        elif self.data_type in ['KER']:\n            X1,y = self.generate_all_specs(index)\n            X2,y = self.generate_raw(index)\n            X = (X1,X2)\n        return X,y\n    \n    def generate_all_specs(self, index):\n        X = np.zeros((512,512,3),dtype='float32')\n        y = np.zeros((6,),dtype='float32')\n        \n        row = self.data.iloc[index]\n        if self.mode=='test': \n            offset = 0\n        else:\n            offset = int(row.offset/2)\n        \n        eeg = self.eeg_specs[row.eeg_id]\n        spec = self.specs[row.spec_id]\n        \n        imgs = [spec[offset:offset+300,k*100:(k+1)*100].T for k in [0,2,1,3]] # to match kaggle with eeg\n        img = np.stack(imgs,axis=-1)\n        # LOG TRANSFORM SPECTROGRAM\n        img = np.clip(img,np.exp(-4),np.exp(8))\n        img = np.log(img)\n            \n        # STANDARDIZE PER IMAGE\n        img = np.nan_to_num(img, nan=0.0)    \n            \n        mn = img.flatten().min()\n        mx = img.flatten().max()\n        ep = 1e-5\n        img = 255 * (img - mn) / (mx - mn + ep)\n        \n        X[0_0+56:100+56,:256,0] = img[:,22:-22,0] # LL_k\n        X[100+56:200+56,:256,0] = img[:,22:-22,2] # RL_k\n        X[0_0+56:100+56,:256,1] = img[:,22:-22,1] # LP_k\n        X[100+56:200+56,:256,1] = img[:,22:-22,3] # RP_k\n        X[0_0+56:100+56,:256,2] = img[:,22:-22,2] # RL_k\n        X[100+56:200+56,:256,2] = img[:,22:-22,1] # LP_k\n        \n        X[0_0+56:100+56,256:,0] = img[:,22:-22,0] # LL_k\n        X[100+56:200+56,256:,0] = img[:,22:-22,2] # RL_k\n        X[0_0+56:100+56,256:,1] = img[:,22:-22,1] # LP_k\n        X[100+56:200+56,256:,1] = img[:,22:-22,3] # RP_K\n        \n        # EEG\n        img = eeg\n        mn = img.flatten().min()\n        mx = img.flatten().max()\n        ep = 1e-5\n        img = 255 * (img - mn) / (mx - mn + ep)\n        X[200+56:300+56,:256,0] = img[:,22:-22,0] # LL_e\n        X[300+56:400+56,:256,0] = img[:,22:-22,2] # RL_e\n        X[200+56:300+56,:256,1] = img[:,22:-22,1] # LP_e\n        X[300+56:400+56,:256,1] = img[:,22:-22,3] # RP_e\n        X[200+56:300+56,:256,2] = img[:,22:-22,2] # RL_e\n        X[300+56:400+56,:256,2] = img[:,22:-22,1] # LP_e\n        \n        X[200+56:300+56,256:,0] = img[:,22:-22,0] # LL_e\n        X[300+56:400+56,256:,0] = img[:,22:-22,2] # RL_e\n        X[200+56:300+56,256:,1] = img[:,22:-22,1] # LP_e\n        X[300+56:400+56,256:,1] = img[:,22:-22,3] # RP_e\n\n        if self.mode!='test':\n            y[:] = row[TARGETS]\n        \n        return X,y\n    \n    def generate_specs(self, index):\n        X = np.zeros((512,512,3),dtype='float32')\n        y = np.zeros((6,),dtype='float32')\n        \n        row = self.data.iloc[index]\n        if self.mode=='test': \n            offset = 0\n        else:\n            offset = int(row.offset/2)\n            \n        if self.data_type in ['E','ER']:\n            img = self.eeg_specs[row.eeg_id]\n        elif self.data_type in ['K','KR']:\n            spec = self.specs[row.spec_id]\n            imgs = [spec[offset:offset+300,k*100:(k+1)*100].T for k in [0,2,1,3]] # to match kaggle with eeg\n            img = np.stack(imgs,axis=-1)\n            # LOG TRANSFORM SPECTROGRAM\n            img = np.clip(img,np.exp(-4),np.exp(8))\n            img = np.log(img)\n            \n            # STANDARDIZE PER IMAGE\n            img = np.nan_to_num(img, nan=0.0)    \n            \n        mn = img.flatten().min()\n        mx = img.flatten().max()\n        ep = 1e-5\n        img = 255 * (img - mn) / (mx - mn + ep)\n        \n        X[0_0+56:100+56,:256,0] = img[:,22:-22,0]\n        X[100+56:200+56,:256,0] = img[:,22:-22,2]\n        X[0_0+56:100+56,:256,1] = img[:,22:-22,1]\n        X[100+56:200+56,:256,1] = img[:,22:-22,3]\n        X[0_0+56:100+56,:256,2] = img[:,22:-22,2]\n        X[100+56:200+56,:256,2] = img[:,22:-22,1]\n        \n        X[0_0+56:100+56,256:,0] = img[:,22:-22,0]\n        X[100+56:200+56,256:,0] = img[:,22:-22,1]\n        X[0_0+56:100+56,256:,1] = img[:,22:-22,2]\n        X[100+56:200+56,256:,1] = img[:,22:-22,3]\n        \n        X[200+56:300+56,:256,0] = img[:,22:-22,0]\n        X[300+56:400+56,:256,0] = img[:,22:-22,1]\n        X[200+56:300+56,:256,1] = img[:,22:-22,2]\n        X[300+56:400+56,:256,1] = img[:,22:-22,3]\n        X[200+56:300+56,:256,2] = img[:,22:-22,3]\n        X[300+56:400+56,:256,2] = img[:,22:-22,2]\n        \n        X[200+56:300+56,256:,0] = img[:,22:-22,0]\n        X[300+56:400+56,256:,0] = img[:,22:-22,2]\n        X[200+56:300+56,256:,1] = img[:,22:-22,1]\n        X[300+56:400+56,256:,1] = img[:,22:-22,3]\n        \n        if self.mode!='test':\n            y[:] = row[TARGETS]\n        \n        return X,y\n    \n    def generate_raw(self,index):\n        if USE_PROCESSED and self.mode!='test':\n            X = np.zeros((2_000,8),dtype='float32')\n            y = np.zeros((6,),dtype='float32')\n            row = self.data.iloc[index]\n            X = self.raw_eegs[row.eeg_id]\n            y[:] = row[TARGETS]\n            return X,y\n        \n        X = np.zeros((10_000,8),dtype='float32')\n        y = np.zeros((6,),dtype='float32')\n        \n        row = self.data.iloc[index]\n        eeg = self.raw_eegs[row.eeg_id]\n            \n        # FEATURE ENGINEER\n        X[:,0] = eeg[:,FEAT2IDX['Fp1']] - eeg[:,FEAT2IDX['T3']]\n        X[:,1] = eeg[:,FEAT2IDX['T3']] - eeg[:,FEAT2IDX['O1']]\n            \n        X[:,2] = eeg[:,FEAT2IDX['Fp1']] - eeg[:,FEAT2IDX['C3']]\n        X[:,3] = eeg[:,FEAT2IDX['C3']] - eeg[:,FEAT2IDX['O1']]\n            \n        X[:,4] = eeg[:,FEAT2IDX['Fp2']] - eeg[:,FEAT2IDX['C4']]\n        X[:,5] = eeg[:,FEAT2IDX['C4']] - eeg[:,FEAT2IDX['O2']]\n            \n        X[:,6] = eeg[:,FEAT2IDX['Fp2']] - eeg[:,FEAT2IDX['T4']]\n        X[:,7] = eeg[:,FEAT2IDX['T4']] - eeg[:,FEAT2IDX['O2']]\n            \n        # STANDARDIZE\n        X = np.clip(X,-1024,1024)\n        X = np.nan_to_num(X, nan=0) / 32.0\n            \n        # BUTTER LOW-PASS FILTER\n        X = self.butter_lowpass_filter(X)\n        # Downsample\n        X = X[::5,:]\n        \n        if self.mode!='test':\n            y[:] = row[TARGETS]\n                \n        return X,y\n        \n    def butter_lowpass_filter(self, 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\n    \n    def resize(self, img,size):\n        composition = albu.Compose([\n                albu.Resize(size[0],size[1])\n            ])\n        return composition(image=img)['image']\n            \n    def augmentation(self, img):\n        composition = albu.Compose([\n                albu.HorizontalFlip(p=0.4)\n            ])\n        return composition(image=img)['image']","metadata":{"papermill":{"duration":2.248907,"end_time":"2024-03-03T17:13:54.628134","exception":false,"start_time":"2024-03-03T17:13:52.379227","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-03-13T10:32:55.089469Z","iopub.execute_input":"2024-03-13T10:32:55.089778Z","iopub.status.idle":"2024-03-13T10:32:55.149019Z","shell.execute_reply.started":"2024-03-13T10:32:55.089755Z","shell.execute_reply":"2024-03-13T10:32:55.14807Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def spectrogram_from_eeg(parquet_path):    \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((100,300,4),dtype='float32')\n\n    for k in range(4):\n        COLS = FEATS[k]\n        \n        for kk in range(4):\n            # FILL NANS\n            x1 = eeg[COLS[kk]].values\n            x2 = eeg[COLS[kk+1]].values\n            m = np.nanmean(x1)\n            if np.isnan(x1).mean()<1: x1 = np.nan_to_num(x1,nan=m)\n            else: x1[:] = 0\n            m = np.nanmean(x2)\n            if np.isnan(x2).mean()<1: x2 = np.nan_to_num(x2,nan=m)\n            else: x2[:] = 0\n                \n            # COMPUTE PAIR DIFFERENCES\n            x = x1 - x2\n\n            # RAW SPECTROGRAM\n            mel_spec = librosa.feature.melspectrogram(y=x, sr=200, hop_length=len(x)//300, \n                  n_fft=1024, n_mels=100, fmin=0, fmax=20, win_length=128)\n            \n            # LOG TRANSFORM\n            width = (mel_spec.shape[1]//30)*30\n            mel_spec_db = librosa.power_to_db(mel_spec, ref=np.max).astype(np.float32)[:,:width]\n            img[:,:,k] += mel_spec_db\n                \n        # AVERAGE THE 4 MONTAGE DIFFERENCES\n        img[:,:,k] /= 4.0\n          \n    return img\n\ndef eeg_from_parquet(parquet_path):\n\n    eeg = pd.read_parquet(parquet_path, columns=FEATS2)\n    rows = len(eeg)\n    offset = (rows-10_000)//2\n    eeg = eeg.iloc[offset:offset+10_000]\n    data = np.zeros((10_000,len(FEATS2)))\n    for j,col in enumerate(FEATS2):\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    return data","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:32:55.150161Z","iopub.execute_input":"2024-03-13T10:32:55.150556Z","iopub.status.idle":"2024-03-13T10:32:55.165788Z","shell.execute_reply.started":"2024-03-13T10:32:55.150522Z","shell.execute_reply":"2024-03-13T10:32:55.16483Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load testing features\ntest = pd.read_csv('/kaggle/input/hms-harmful-brain-activity-classification/test.csv')\n# Rename\ntest = test.rename({'spectrogram_id':'spec_id'},axis=1)\nprint('Test shape',test.shape)\ntest.head()\n# Read all spectrograms\nPATH = '/kaggle/input/hms-harmful-brain-activity-classification/test_spectrograms'\nfiles = os.listdir(PATH)\nprint(f'There are {len(files)} test spectrogram parquets')\nspectrograms = {}\nfor i,f in enumerate(files):\n    tmp = pd.read_parquet(f'{PATH}/{f}')\n    name = int(f.split('.')[0])\n    spectrograms[name] = tmp.iloc[:,1:].values\n# Read all EEG Spectrograms\nPATH = '/kaggle/input/hms-harmful-brain-activity-classification/test_eegs'\nDISPLAY = 0\nEEG_IDS = test.eeg_id.unique()\nall_eegs = {}\nprint('Converting Test EEG to Spectrograms...')\nfor i,eeg_id in enumerate(EEG_IDS):\n    # CREATE SPECTROGRAM FROM EEG PARQUET\n    img = spectrogram_from_eeg(f'{PATH}/{eeg_id}.parquet')\n    all_eegs[eeg_id] = img\n# Read all RAW EEG Signals\nall_raw_eegs = {}\nEEG_IDS = test.eeg_id.unique()\nPATH = '/kaggle/input/hms-harmful-brain-activity-classification/test_eegs'\nprint('Processing Test EEG parquets...')\nfor i,eeg_id in enumerate(EEG_IDS):\n    # SAVE EEG TO PYTHON DICTIONARY OF NUMPY ARRAYS\n    data = eeg_from_parquet(f'{PATH}/{eeg_id}.parquet')\n    all_raw_eegs[eeg_id] = data\n","metadata":{"papermill":{"duration":0.028182,"end_time":"2024-03-03T17:13:54.959119","exception":false,"start_time":"2024-03-03T17:13:54.930937","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-03-13T10:32:55.167117Z","iopub.execute_input":"2024-03-13T10:32:55.167405Z","iopub.status.idle":"2024-03-13T10:33:06.43853Z","shell.execute_reply.started":"2024-03-13T10:32:55.167381Z","shell.execute_reply":"2024-03-13T10:33:06.437497Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"DATA_TYPE = 'KER' # K|E|R|KE|KR|ER|KER\n# Submission ON TEST without ensemble\ndef preds_without_ensemble(VER=50):\n    preds = []\n    \n    test_dataset = dataset(test,mode='test',specs=spectrograms2, eeg_specs=all_eegs2, raw_eegs=all_raw_eegs2)\n    model = build_model()\n\n    for i in range(5):\n        print(f'Fold {i+1}')\n        model.load_weights(f'{LOAD_MODELS_FROM}/model_{DATA_TYPE}_{VER}_{i}.weights.h5')\n        pred = model.predict(test_dataset, verbose=1)\n        preds.append(pred)\n        \n    pred = np.mean(preds,axis=0)\n    print('Test preds shape',pred.shape)","metadata":{"papermill":{"duration":0.033962,"end_time":"2024-03-03T17:14:05.671441","exception":false,"start_time":"2024-03-03T17:14:05.637479","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-03-13T10:33:06.440432Z","iopub.execute_input":"2024-03-13T10:33:06.441452Z","iopub.status.idle":"2024-03-13T10:33:06.457134Z","shell.execute_reply.started":"2024-03-13T10:33:06.441412Z","shell.execute_reply":"2024-03-13T10:33:06.455821Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Setup for ensemble\nENSEMBLE = True\nLBs = [0.41,0.39,0.41,0.37,0.39,0.38,0.36] # K|E|R|KE|KR|ER|KER for weighted ensemble we use LBs of each model\nVER_K = 43 # Kaggle's spectrogram model version\nVER_E = 42 # EEG's spectrogram model version\nVER_R = 37 # EEG's Raw wavenet model version, trained on single GPU\nVER_KE = 47 # Kaggle's and EEG's spectrogram model version\nVER_KR = 48 # Kaggle's spectrogram and Raw model version\nVER_ER = 49 # EEG's spectrogram and Raw model version\nVER_KER = 50 # EEG's, Kaggle's spectrograms and Raw model version","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:33:06.463453Z","iopub.execute_input":"2024-03-13T10:33:06.466894Z","iopub.status.idle":"2024-03-13T10:33:06.479811Z","shell.execute_reply.started":"2024-03-13T10:33:06.466818Z","shell.execute_reply":"2024-03-13T10:33:06.478406Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def create_dataset(data, mode='train', batch_size=8, data_type=DATA_TYPE, \n            augment=False, specs=None, eeg_specs=None, raw_eegs=None):\n    \n    BATCH_SIZE_PER_REPLICA = batch_size\n    BATCH_SIZE = BATCH_SIZE_PER_REPLICA * strategy.num_replicas_in_sync\n    gen = DataGenerator(data,mode=mode, data_type=data_type, augment=augment,\n                       specs=specs, eeg_specs=eeg_specs, raw_eegs=raw_eegs)\n    if data_type in ['K','E','KE']: \n        inp = tf.TensorSpec(shape=(512,512,3), dtype=tf.float32)\n    elif data_type in ['KR','ER','KER']:\n        inp = (tf.TensorSpec(shape=(512,512,3), dtype=tf.float32),tf.TensorSpec(shape=(2000,8), dtype=tf.float32))\n    elif data_type in ['R']:\n        inp = tf.TensorSpec(shape=(2000,8), dtype=tf.float32)\n        \n    output_signature = (inp,tf.TensorSpec(shape=(6,), dtype=tf.float32))\n    dataset = tf.data.Dataset.from_generator(generator=gen, output_signature=output_signature).batch(\n        BATCH_SIZE)\n    return dataset","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:33:06.48611Z","iopub.execute_input":"2024-03-13T10:33:06.489555Z","iopub.status.idle":"2024-03-13T10:33:06.508228Z","shell.execute_reply.started":"2024-03-13T10:33:06.489504Z","shell.execute_reply":"2024-03-13T10:33:06.506932Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def build_spec_model(hybrid=False):  \n    inp = tf.keras.layers.Input((512,512,3))\n    base_model = load_model(f'{LOAD_BACKBONE_FROM}')    \n    x = base_model(inp)\n    x = tf.keras.layers.GlobalAveragePooling2D()(x)\n    if not hybrid:\n        x = tf.keras.layers.Dense(6,activation='softmax', dtype='float32')(x)\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    model.compile(loss=loss, optimizer=opt)  \n    return model\n\ndef build_wave_model(hybrid=False):\n    def wave_block(x, filters, kernel_size, n):\n        dilation_rates = [2**i for i in range(n)]\n        x = Conv1D(filters = filters,\n                   kernel_size = 1,\n                   padding = 'same')(x)\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\n    \n        \n    # INPUT \n    inp = tf.keras.Input(shape=(2_000,8))\n    \n    ############\n    # FEATURE EXTRACTION SUB MODEL\n    inp2 = tf.keras.Input(shape=(2_000,1))\n    x = wave_block(inp2, 8, 4, 6)\n    x = wave_block(x, 16, 4, 6)\n    x = wave_block(x, 32, 4, 6)\n    x = wave_block(x, 64, 4, 6)\n    model2 = tf.keras.Model(inputs=inp2, outputs=x)\n    ###########\n    \n    # LEFT TEMPORAL CHAIN\n    x1 = model2(inp[:,:,0:1])\n    x1 = tf.keras.layers.GlobalAveragePooling1D()(x1)\n    x2 = model2(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 = model2(inp[:,:,2:3])\n    x1 = tf.keras.layers.GlobalAveragePooling1D()(x1)\n    x2 = model2(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 = model2(inp[:,:,4:5])\n    x1 = tf.keras.layers.GlobalAveragePooling1D()(x1)\n    x2 = model2(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 = model2(inp[:,:,6:7])\n    x1 = tf.keras.layers.GlobalAveragePooling1D()(x1)\n    x2 = model2(inp[:,:,7:8])\n    x2 = tf.keras.layers.GlobalAveragePooling1D()(x2)\n    z4 = tf.keras.layers.Average()([x1,x2])\n    \n    # COMBINE CHAINS\n    y = tf.keras.layers.Concatenate()([z1,z2,z3,z4])\n    if not hybrid:\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\n\ndef build_hybrid_model():\n    model_spec = build_spec_model(True)\n    model_wave = build_wave_model(True)\n    inputs = [model_spec.input, model_wave.input]\n    x = [model_spec.output, model_wave.output]\n    x = tf.keras.layers.Concatenate()(x)\n    x = tf.keras.layers.Dense(6,activation='softmax', dtype='float32')(x)\n    \n    # COMPILE MODEL\n    model = tf.keras.Model(inputs=inputs, outputs=x)\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-13T10:33:06.514262Z","iopub.execute_input":"2024-03-13T10:33:06.51769Z","iopub.status.idle":"2024-03-13T10:33:06.561885Z","shell.execute_reply.started":"2024-03-13T10:33:06.517641Z","shell.execute_reply":"2024-03-13T10:33:06.560857Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Submission ON TEST with ensemble\ndef preds_with_ensemble():\n    preds = []\n    params = {'specs':spectrograms, 'eeg_specs':all_eegs, 'raw_eegs':all_raw_eegs}\n    test_dataset_K = create_dataset(test, data_type='K', mode='test', **params)\n    test_dataset_E = create_dataset(test, data_type='E', mode='test', **params)\n    test_dataset_R = create_dataset(test, data_type='R', mode='test', **params)\n    test_dataset_KE = create_dataset(test, data_type='KE', mode='test', **params)\n    test_dataset_KR = create_dataset(test, data_type='KR', mode='test', **params)\n    test_dataset_ER = create_dataset(test, data_type='ER', mode='test', **params)\n    test_dataset_KER = create_dataset(test, data_type='KER', mode='test', **params)\n\n    # LB SCORE WEIGHTS FOR EACH MODEL\n    lbs = 1 - np.array(LBs)\n    weights = lbs/lbs.sum()\n    model_spec = build_spec_model()\n    model_wave = build_wave_model()\n    model_hybrid = build_hybrid_model()\n    \n    for i in range(5):\n        print(f'Fold {i+1}')\n        # Kaggle's spectrogram model \n        model_spec.load_weights(f'{LOAD_MODELS_FROM}/model_K_{VER_K}_{i}.weights.h5')\n        pred_K = model_spec.predict(test_dataset_K, verbose=1)\n        # EEG's spectrogram model\n        model_spec.load_weights(f'{LOAD_MODELS_FROM}/model_E_{VER_E}_{i}.weights.h5')\n        pred_E = model_spec.predict(test_dataset_E, verbose=1)\n        # EEG's Raw wavenet model\n        model_wave.load_weights(f'{LOAD_MODELS_FROM}/model_R_{VER_R}_{i}.weights.h5')\n        pred_R = model_wave.predict(test_dataset_R, verbose=1)\n        # Kaggle's and EEG's spectrogram model\n        model_spec.load_weights(f'{LOAD_MODELS_FROM}/model_KE_{VER_KE}_{i}.weights.h5')\n        pred_KE = model_spec.predict(test_dataset_KE, verbose=1)\n        # Kaggle's spectrogram and Raw model\n        model_hybrid.load_weights(f'{LOAD_MODELS_FROM}/model_KR_{VER_KR}_{i}.weights.h5')\n        pred_KR = model_hybrid.predict(test_dataset_KR, verbose=1)\n        # EEG's spectrogram and Raw model\n        model_hybrid.load_weights(f'{LOAD_MODELS_FROM}/model_ER_{VER_ER}_{i}.weights.h5')\n        pred_ER = model_hybrid.predict(test_dataset_ER, verbose=1)\n        # EEG's, Kaggle's spectrograms and Raw model\n        model_hybrid.load_weights(f'{LOAD_MODELS_FROM}/model_KER_{VER_KER}_{i}.weights.h5')\n        pred_KER = model_hybrid.predict(test_dataset_KER, verbose=1)\n        # Combine the predictions from all the model with different weights \n        pred = np.array([pred_K,pred_E,pred_R,pred_KE,pred_KR,pred_ER,pred_KER])\n        pred = np.average(pred,axis=0,weights=weights)\n        preds.append(pred)\n        \n    pred = np.mean(preds,axis=0)\n    return pred\n# Prediction with \nmodel_pred = preds_with_ensemble()","metadata":{"papermill":{"duration":66.385954,"end_time":"2024-03-03T17:15:12.067289","exception":false,"start_time":"2024-03-03T17:14:05.681335","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-03-13T10:33:06.563955Z","iopub.execute_input":"2024-03-13T10:33:06.564634Z","iopub.status.idle":"2024-03-13T10:35:30.650975Z","shell.execute_reply.started":"2024-03-13T10:33:06.564606Z","shell.execute_reply":"2024-03-13T10:35:30.650152Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_pred","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:35:30.653164Z","iopub.execute_input":"2024-03-13T10:35:30.653471Z","iopub.status.idle":"2024-03-13T10:35:30.660753Z","shell.execute_reply.started":"2024-03-13T10:35:30.653445Z","shell.execute_reply":"2024-03-13T10:35:30.659734Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model 2","metadata":{}},{"cell_type":"code","source":"# Importing essential libraries\nimport gc\nimport os\nimport random\nimport warnings\nimport numpy as np\nimport pandas as pd\nfrom IPython.display import display\n\n# PyTorch for deep learning\nimport timm\nimport torch\nimport torch.nn as nn  \nimport torch.optim as optim\nimport torch.nn.functional as F\n\n# torchvision for image processing and augmentation\nimport torchvision.transforms as transforms\n\n# Suppressing minor warnings to keep the output clean\nwarnings.filterwarnings('ignore', category=Warning)\n\n# Reclaim memory no longer in use.\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:35:30.666302Z","iopub.execute_input":"2024-03-13T10:35:30.666707Z","iopub.status.idle":"2024-03-13T10:35:39.188407Z","shell.execute_reply.started":"2024-03-13T10:35:30.666681Z","shell.execute_reply":"2024-03-13T10:35:39.187377Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Config:\n    seed=42\n    image_transform=transforms.Resize((512, 512))\n    num_folds=5\n    \n# Set the seed for reproducibility across multiple libraries\ndef set_seed(seed):\n    torch.backends.cudnn.deterministic = True\n    torch.backends.cudnn.benchmark = True\n    torch.manual_seed(seed)\n    np.random.seed(seed)\n    random.seed(seed)\n    \nset_seed(Config.seed)","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:35:39.189699Z","iopub.execute_input":"2024-03-13T10:35:39.190094Z","iopub.status.idle":"2024-03-13T10:35:39.205274Z","shell.execute_reply.started":"2024-03-13T10:35:39.190065Z","shell.execute_reply":"2024-03-13T10:35:39.204255Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"use_cuda = torch.cuda.is_available()\nif use_cuda:\n    device = torch.device(\"cuda:0\")\n    if torch.cuda.device_count() > 1:\n        print(f'Using {torch.cuda.device_count()} GPUs')\n    else:\n        print(f'Using {torch.cuda.device_count()} GPU')\nelse:\n    device = torch.device(\"cpu\")\n    print('Using CPU')","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:35:39.206565Z","iopub.execute_input":"2024-03-13T10:35:39.206912Z","iopub.status.idle":"2024-03-13T10:35:39.243393Z","shell.execute_reply.started":"2024-03-13T10:35:39.206881Z","shell.execute_reply":"2024-03-13T10:35:39.242431Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load and store the trained models for each fold into a list\nmodels = []\n\n# Load ResNet34d\nfor i in range(Config.num_folds):\n    # Create the same model architecture as during training\n    model_resnet = timm.create_model('resnet34d', pretrained=False, num_classes=6, in_chans=1).to(device)\n    \n    # Load the trained weights from the corresponding file\n    model_resnet.load_state_dict(torch.load(f'/kaggle/input/resnet34d/hms-train-resnet34d/resnet34d_fold{i}.pth', map_location=device))\n    \n    # Append the loaded model to the models list\n    models.append(model_resnet)\n\n# Reclaim memory no longer in use.\ngc.collect()\n\n# Load EfficientNetB0\nfor j in range(Config.num_folds):\n    # Create the same model architecture as during training\n    model_effnet_b0 = timm.create_model('efficientnet_b0', pretrained=False, num_classes=6, in_chans=1).to(device)\n    \n    # Load the trained weights from the corresponding file\n    model_effnet_b0.load_state_dict(torch.load(f'/kaggle/input/efficientnetb0/hms-train-efficientnetb0/efficientnet_b0_fold{j}.pth', map_location=device))\n    \n    # Append the loaded model to the models list\n    models.append(model_effnet_b0)\n    \n# Reclaim memory no longer in use.\ngc.collect()\n    \n# Load EfficientNetB1\nfor k in range(Config.num_folds):\n    # Create the same model architecture as during training\n    model_effnet_b1 = timm.create_model('efficientnet_b1', pretrained=False, num_classes=6, in_chans=1).to(device)\n    \n    # Load the trained weights from the corresponding file\n    model_effnet_b1.load_state_dict(torch.load(f'/kaggle/input/efficientnetb1/hms-train-efficientnetb1/efficientnet_b1_fold{k}.pth', map_location=device))\n    \n    # Append the loaded model to the models list\n    models.append(model_effnet_b1)\n\n# Reclaim memory no longer in use.\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:35:39.24483Z","iopub.execute_input":"2024-03-13T10:35:39.245235Z","iopub.status.idle":"2024-03-13T10:35:51.385469Z","shell.execute_reply.started":"2024-03-13T10:35:39.245201Z","shell.execute_reply":"2024-03-13T10:35:51.384416Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load test data and sample submission dataframe\ntest_df = pd.read_csv(\"/kaggle/input/hms-harmful-brain-activity-classification/test.csv\")\nsubmission = pd.read_csv(\"/kaggle/input/hms-harmful-brain-activity-classification/sample_submission.csv\")\n\n# Merge the submission dataframe with the test data on EEG IDs\nsubmission = submission.merge(test_df, on='eeg_id', how='left')\n\n# Generate file paths for each spectrogram based on the EEG data in the submission dataframe\nsubmission['path'] = submission['spectrogram_id'].apply(lambda x: f\"/kaggle/input/hms-harmful-brain-activity-classification/test_spectrograms/{x}.parquet\")\n\n# Display the first few rows of the submission dataframe\ndisplay(submission.head())\n\n# Reclaim memory no longer in use\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:35:51.386823Z","iopub.execute_input":"2024-03-13T10:35:51.387636Z","iopub.status.idle":"2024-03-13T10:35:51.821637Z","shell.execute_reply.started":"2024-03-13T10:35:51.3876Z","shell.execute_reply":"2024-03-13T10:35:51.820663Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define the weights for each model\nweight_resnet34d = 0.26\nweight_effnetb0 = 0.48\nweight_effnetb1 = 0.26\n\n# Get file paths for test spectrograms\npaths = submission['path'].values\ntest_predss = []\n\n# Generate predictions for each spectrogram using all models\nfor path in paths:\n    eps = 1e-6\n    # Read and preprocess spectrogram data\n    data = pd.read_parquet(path)\n    data = data.fillna(-1).values[:, 1:].T\n    data = np.clip(data, np.exp(-6), np.exp(10))\n    data = np.log(data)\n    \n    # Normalize the data\n    data_mean = data.mean(axis=(0, 1))\n    data_std = data.std(axis=(0, 1))\n    data = (data - data_mean) / (data_std + eps)\n    data_tensor = torch.unsqueeze(torch.Tensor(data), dim=0)\n    data = Config.image_transform(data_tensor)\n\n    test_pred = []\n    \n    # Generate predictions using all models\n    for model in models:\n        model.eval()\n        with torch.no_grad():\n            pred = F.softmax(model(data.unsqueeze(0).to(device)))[0]\n            pred = pred.detach().cpu().numpy()\n        test_pred.append(pred)\n\n    # Combine predictions from all models using weighted voting\n    weighted_pred = weight_resnet34d * np.mean(test_pred[:Config.num_folds], axis=0) + \\\n                     weight_effnetb0 * np.mean(test_pred[Config.num_folds:2*Config.num_folds], axis=0) + \\\n                     weight_effnetb1 * np.mean(test_pred[2*Config.num_folds:], axis=0)\n    \n    test_predss.append(weighted_pred)\n\n# Convert the list of predictions to a NumPy array for further processing\ntest_predss = np.array(test_predss)\n\n# Reclaim memory no longer in use\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:35:51.822901Z","iopub.execute_input":"2024-03-13T10:35:51.823225Z","iopub.status.idle":"2024-03-13T10:35:53.824778Z","shell.execute_reply.started":"2024-03-13T10:35:51.8232Z","shell.execute_reply":"2024-03-13T10:35:53.823796Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with torch.no_grad():\n    torch.cuda.empty_cache()\ndel models\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:35:53.826033Z","iopub.execute_input":"2024-03-13T10:35:53.826326Z","iopub.status.idle":"2024-03-13T10:35:54.224916Z","shell.execute_reply.started":"2024-03-13T10:35:53.826301Z","shell.execute_reply":"2024-03-13T10:35:54.223908Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_predss","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:35:54.226286Z","iopub.execute_input":"2024-03-13T10:35:54.226647Z","iopub.status.idle":"2024-03-13T10:35:54.232991Z","shell.execute_reply.started":"2024-03-13T10:35:54.226616Z","shell.execute_reply":"2024-03-13T10:35:54.23196Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model 3","metadata":{}},{"cell_type":"code","source":"import os, gc\nos.environ[\"CUDA_VISIBLE_DEVICES\"]=\"0,1\"\nimport tensorflow as tf\nimport pandas as pd, numpy as np\nimport matplotlib.pyplot as plt\nprint('TensorFlow version =',tf.__version__)\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')\n\nVER = 5\n\n# IF THIS EQUALS NONE, THEN WE TRAIN NEW MODELS\n# IF THIS EQUALS DISK PATH, THEN WE LOAD PREVIOUSLY TRAINED MODELS\nLOAD_MODELS_FROM = '/kaggle/input/brain-efficientnet-models-v3-v4-v5/'\n\nUSE_KAGGLE_SPECTROGRAMS = True\nUSE_EEG_SPECTROGRAMS = True","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:35:54.234186Z","iopub.execute_input":"2024-03-13T10:35:54.234495Z","iopub.status.idle":"2024-03-13T10:35:54.248011Z","shell.execute_reply.started":"2024-03-13T10:35:54.234472Z","shell.execute_reply":"2024-03-13T10:35:54.247043Z"},"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-13T10:35:54.249417Z","iopub.execute_input":"2024-03-13T10:35:54.249909Z","iopub.status.idle":"2024-03-13T10:35:54.262957Z","shell.execute_reply.started":"2024-03-13T10:35:54.249877Z","shell.execute_reply":"2024-03-13T10:35:54.262101Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import albumentations as albu\nTARS = {'Seizure':0, 'LPD':1, 'GPD':2, 'LRDA':3, 'GRDA':4, 'Other':5}\nTARS2 = {x:y for y,x in TARS.items()}\n\nclass DataGenerator(tf.keras.utils.Sequence):\n    'Generates data for Keras'\n    def __init__(self, data, specs, eeg_specs, batch_size=32, shuffle=False, augment=False, mode='train'): \n\n        self.data = data\n        self.batch_size = batch_size\n        self.shuffle = shuffle\n        self.augment = augment\n        self.mode = mode\n        self.specs = specs\n        self.eeg_specs = eeg_specs\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        if self.augment: X = self.__augment_batch(X) \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,8),dtype='float32')\n        y = np.zeros((len(indexes),6),dtype='float32')\n        img = np.ones((128,256),dtype='float32')\n        \n        for j,i in enumerate(indexes):\n            row = self.data.iloc[i]\n            if self.mode=='test': \n                r = 0\n            else: \n                r = int( (row['min'] + row['max'])//4 )\n\n            for k in range(4):\n                # EXTRACT 300 ROWS OF SPECTROGRAM\n                img = self.specs[row.spec_id][r:r+300,k*100:(k+1)*100].T\n                \n                # LOG TRANSFORM SPECTROGRAM\n                img = np.clip(img,np.exp(-4),np.exp(8))\n                img = np.log(img)\n                \n                # STANDARDIZE PER IMAGE\n                ep = 1e-6\n                m = np.nanmean(img.flatten())\n                s = np.nanstd(img.flatten())\n                img = (img-m)/(s+ep)\n                img = np.nan_to_num(img, nan=0.0)\n                \n                # CROP TO 256 TIME STEPS\n                X[j,14:-14,:,k] = img[:,22:-22] / 2.0\n        \n            # EEG SPECTROGRAMS\n            img = self.eeg_specs[row.eeg_id]\n            X[j,:,:,4:] = img\n                \n            if self.mode!='test':\n                y[j,] = row[TARGETS]\n            \n        return X,y\n    \n    def __random_transform(self, img):\n        composition = albu.Compose([\n            albu.HorizontalFlip(p=0.5),\n            #albu.CoarseDropout(max_holes=8,max_height=32,max_width=32,fill_value=0,p=0.5),\n        ])\n        return composition(image=img)['image']\n            \n    def __augment_batch(self, img_batch):\n        for i in range(img_batch.shape[0]):\n            img_batch[i, ] = self.__random_transform(img_batch[i, ])\n        return img_batch","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:35:54.264361Z","iopub.execute_input":"2024-03-13T10:35:54.264724Z","iopub.status.idle":"2024-03-13T10:35:54.283363Z","shell.execute_reply.started":"2024-03-13T10:35:54.264694Z","shell.execute_reply":"2024-03-13T10:35:54.282492Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install --no-index --find-links=/kaggle/input/tf-efficientnet-whl-files /kaggle/input/tf-efficientnet-whl-files/efficientnet-1.1.1-py3-none-any.whl","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:35:54.284564Z","iopub.execute_input":"2024-03-13T10:35:54.285547Z","iopub.status.idle":"2024-03-13T10:36:08.676544Z","shell.execute_reply.started":"2024-03-13T10:35:54.285518Z","shell.execute_reply":"2024-03-13T10:36:08.67521Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import efficientnet.tfkeras as efn\n\ndef build_model():\n    \n    inp = tf.keras.Input(shape=(128,256,8))\n    base_model = efn.EfficientNetB0(include_top=False, weights=None, input_shape=None)\n    base_model.load_weights('/kaggle/input/tf-efficientnet-imagenet-weights/efficientnet-b0_weights_tf_dim_ordering_tf_kernels_autoaugment_notop.h5')\n    \n    # RESHAPE INPUT 128x256x8 => 512x512x3 MONOTONE IMAGE\n    # KAGGLE SPECTROGRAMS\n    x1 = [inp[:,:,:,i:i+1] for i in range(4)]\n    x1 = tf.keras.layers.Concatenate(axis=1)(x1)\n    # EEG SPECTROGRAMS\n    x2 = [inp[:,:,:,i+4:i+5] for i in range(4)]\n    x2 = tf.keras.layers.Concatenate(axis=1)(x2)\n    # MAKE 512X512X3\n    if USE_KAGGLE_SPECTROGRAMS & USE_EEG_SPECTROGRAMS:\n        x = tf.keras.layers.Concatenate(axis=2)([x1,x2])\n    elif USE_EEG_SPECTROGRAMS: x = x2\n    else: x = x1\n    x = tf.keras.layers.Concatenate(axis=3)([x,x,x])\n    \n    # OUTPUT\n    x = base_model(x)\n    x = tf.keras.layers.GlobalAveragePooling2D()(x)\n    x = tf.keras.layers.Dense(6,activation='softmax', dtype='float32')(x)\n        \n    # COMPILE MODEL\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":{"execution":{"iopub.status.busy":"2024-03-13T10:36:08.678549Z","iopub.execute_input":"2024-03-13T10:36:08.678969Z","iopub.status.idle":"2024-03-13T10:36:08.711532Z","shell.execute_reply.started":"2024-03-13T10:36:08.678926Z","shell.execute_reply":"2024-03-13T10:36:08.710484Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#del all_eegs, spectrograms; 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-13T10:36:08.712838Z","iopub.execute_input":"2024-03-13T10:36:08.713676Z","iopub.status.idle":"2024-03-13T10:36:08.728408Z","shell.execute_reply.started":"2024-03-13T10:36:08.713643Z","shell.execute_reply":"2024-03-13T10:36:08.727454Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# READ ALL SPECTROGRAMS\nPATH2 = '/kaggle/input/hms-harmful-brain-activity-classification/test_spectrograms/'\nfiles2 = os.listdir(PATH2)\nprint(f'There are {len(files2)} test spectrogram parquets')\n    \nspectrograms2 = {}\nfor i,f in enumerate(files2):\n    if i%100==0: print(i,', ',end='')\n    tmp = pd.read_parquet(f'{PATH2}{f}')\n    name = int(f.split('.')[0])\n    spectrograms2[name] = tmp.iloc[:,1:].values\n    \n# RENAME FOR DATALOADER\ntest = test.rename({'spectrogram_id':'spec_id'},axis=1)","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:36:08.729569Z","iopub.execute_input":"2024-03-13T10:36:08.729831Z","iopub.status.idle":"2024-03-13T10:36:08.77793Z","shell.execute_reply.started":"2024-03-13T10:36:08.729809Z","shell.execute_reply":"2024-03-13T10:36:08.777099Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pywt, librosa\n\nUSE_WAVELET = None \n\nNAMES = ['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\n# 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\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        for kk in range(4):\n        \n            # COMPUTE PAIR DIFFERENCES\n            x = eeg[COLS[kk]].values - eeg[COLS[kk+1]].values\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            signals.append(x)\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            img[:,:,k] += mel_spec_db\n                \n        # AVERAGE THE 4 MONTAGE DIFFERENCES\n        img[:,:,k] /= 4.0\n        \n        if display:\n            plt.subplot(2,2,k+1)\n            plt.imshow(img[:,:,k],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":{"execution":{"iopub.status.busy":"2024-03-13T10:36:08.779262Z","iopub.execute_input":"2024-03-13T10:36:08.779614Z","iopub.status.idle":"2024-03-13T10:36:08.805284Z","shell.execute_reply.started":"2024-03-13T10:36:08.779583Z","shell.execute_reply":"2024-03-13T10:36:08.803994Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# READ ALL EEG SPECTROGRAMS\nPATH2 = '/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    img = spectrogram_from_eeg(f'{PATH2}{eeg_id}.parquet', i<DISPLAY)\n    all_eegs2[eeg_id] = img","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:36:08.806558Z","iopub.execute_input":"2024-03-13T10:36:08.806924Z","iopub.status.idle":"2024-03-13T10:36:10.77037Z","shell.execute_reply.started":"2024-03-13T10:36:08.806892Z","shell.execute_reply":"2024-03-13T10:36:10.769411Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# INFER EFFICIENTNET ON TEST\npreds = []\nmodel = build_model()\ntest_gen = DataGenerator(test, shuffle=False, batch_size=64, mode='test',\n                         specs = spectrograms2, eeg_specs = all_eegs2)\n\nfor i in range(5):\n    print(f'Fold {i+1}')\n    if LOAD_MODELS_FROM:\n        model.load_weights(f'{LOAD_MODELS_FROM}EffNet_v{VER}_f{i}.h5')\n    else:\n        model.load_weights(f'EffNet_v{VER}_f{i}.h5')\n    pred = model.predict(test_gen, verbose=1)\n    preds.append(pred)\npred = np.mean(preds,axis=0)\nprint()\nprint('Test preds shape',pred.shape)","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:36:10.77203Z","iopub.execute_input":"2024-03-13T10:36:10.77247Z","iopub.status.idle":"2024-03-13T10:36:18.735417Z","shell.execute_reply.started":"2024-03-13T10:36:10.772434Z","shell.execute_reply":"2024-03-13T10:36:18.734442Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preds_combine = pred\npreds_combine","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:36:18.736718Z","iopub.execute_input":"2024-03-13T10:36:18.737086Z","iopub.status.idle":"2024-03-13T10:36:18.743639Z","shell.execute_reply.started":"2024-03-13T10:36:18.737058Z","shell.execute_reply":"2024-03-13T10:36:18.742604Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model 4","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport torch \nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torchvision.transforms as transforms\nimport random\nimport warnings\nwarnings.filterwarnings('ignore')","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:36:18.74481Z","iopub.execute_input":"2024-03-13T10:36:18.745206Z","iopub.status.idle":"2024-03-13T10:36:18.752981Z","shell.execute_reply.started":"2024-03-13T10:36:18.745179Z","shell.execute_reply":"2024-03-13T10:36:18.752211Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Config:\n    seed=2024\n    image_transform=transforms.Resize((512, 512))\n    num_folds=5","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:36:18.753997Z","iopub.execute_input":"2024-03-13T10:36:18.754243Z","iopub.status.idle":"2024-03-13T10:36:18.765916Z","shell.execute_reply.started":"2024-03-13T10:36:18.754221Z","shell.execute_reply":"2024-03-13T10:36:18.765189Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"use_cuda = torch.cuda.is_available()\nif use_cuda:\n    device = torch.device(\"cuda:0\")\n    if torch.cuda.device_count() > 1:\n        print(f'Using {torch.cuda.device_count()} GPUs')\n    else:\n        print(f'Using {torch.cuda.device_count()} GPU')\nelse:\n    device = torch.device(\"cpu\")\n    print('Using CPU')","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:36:18.766876Z","iopub.execute_input":"2024-03-13T10:36:18.76718Z","iopub.status.idle":"2024-03-13T10:36:18.780282Z","shell.execute_reply.started":"2024-03-13T10:36:18.767157Z","shell.execute_reply":"2024-03-13T10:36:18.779458Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"models=[]\nfor i in range(Config.num_folds):\n    model = torch.load(f'/kaggle/input/hms-baseline-resnet34d-512-512-training-5-folds/HMS_resnet_fold{i}.pth').to(device)\n    models.append(model)\nmodel = torch.load(\"/kaggle/input/hms-baseline-resnet34d-512-512-training/HMS_resnet.pth\").to(device)\nmodels.append(model)","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:36:18.781315Z","iopub.execute_input":"2024-03-13T10:36:18.78163Z","iopub.status.idle":"2024-03-13T10:36:24.533995Z","shell.execute_reply.started":"2024-03-13T10:36:18.781605Z","shell.execute_reply":"2024-03-13T10:36:24.533161Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def seed_everything(seed):\n    torch.backends.cudnn.deterministic = True#将cuda加速的随机数生成器设为确定性模式\n    torch.backends.cudnn.benchmark = True#关闭CuDNN框架的自动寻找最优卷积算法的功能，以避免不同的算法对结果产生影响\n    torch.manual_seed(seed)#pytorch的随机种子\n    np.random.seed(seed)#numpy的随机种子\n    random.seed(seed)#python内置的随机种子\nseed_everything(Config.seed)","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:36:24.535081Z","iopub.execute_input":"2024-03-13T10:36:24.535371Z","iopub.status.idle":"2024-03-13T10:36:24.540636Z","shell.execute_reply.started":"2024-03-13T10:36:24.535346Z","shell.execute_reply":"2024-03-13T10:36:24.539725Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df=pd.read_csv(\"/kaggle/input/hms-harmful-brain-activity-classification/test.csv\")\nsubmission=pd.read_csv(\"/kaggle/input/hms-harmful-brain-activity-classification/sample_submission.csv\")\nsubmission=submission.merge(test_df,on='eeg_id',how='left')\nsubmission['path']=submission['spectrogram_id'].apply(lambda x: \"/kaggle/input/hms-harmful-brain-activity-classification/test_spectrograms/\"+str(x)+\".parquet\" )\nsubmission.head()","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:36:24.542012Z","iopub.execute_input":"2024-03-13T10:36:24.542333Z","iopub.status.idle":"2024-03-13T10:36:24.574457Z","shell.execute_reply.started":"2024-03-13T10:36:24.542301Z","shell.execute_reply":"2024-03-13T10:36:24.573611Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"paths=submission['path'].values\ntest_preds=[]\nfor path in paths:\n    eps=1e-6\n    data=pd.read_parquet(path)\n    #这里最小值是0,故用-1填充.第一列是时间列,故去掉 ,行是不同列,列是时间\n    data = data.fillna(-1).values[:,1:].T\n    #选取一段时间的数据进行训练\n    data=data[:,0:300]#(400,300)\n    data=np.clip(data,np.exp(-6),np.exp(10))#最大值为89209464.0\n    data= np.log(data)#对数变换\n    #对数据进行归一化\n    data_mean=data.mean(axis=(0,1))\n    data_std=data.std(axis=(0,1))\n    data=(data-data_mean)/(data_std+eps)\n    data_tensor = torch.unsqueeze(torch.Tensor(data), dim=0)\n    data=Config.image_transform(data_tensor)\n    test_pred=[]\n    for model in models:\n        model.eval()\n        with torch.no_grad():\n            pred=F.softmax(model(data.unsqueeze(0).to(device)))[0]\n            pred=pred.detach().cpu().numpy()\n        test_pred.append(pred)\n    test_pred=np.array(test_pred).mean(axis=0)\n    test_preds.append(test_pred)\ntest_preds=np.array(test_preds)\ntest_preds","metadata":{"execution":{"iopub.status.busy":"2024-03-13T10:36:24.575546Z","iopub.execute_input":"2024-03-13T10:36:24.575831Z","iopub.status.idle":"2024-03-13T10:36:24.726339Z","shell.execute_reply.started":"2024-03-13T10:36:24.575807Z","shell.execute_reply":"2024-03-13T10:36:24.725456Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Create Submission CSV","metadata":{}},{"cell_type":"code","source":"submission=pd.read_csv(\"/kaggle/input/hms-harmful-brain-activity-classification/sample_submission.csv\")\nlabels=['seizure','lpd','gpd','lrda','grda','other']\nfor i in range(len(labels)):\n    submission[f'{labels[i]}_vote']=( test_predss[:, i]*0.05 + model_pred[:, i] * 0.95 )\nsubmission.to_csv(\"submission.csv\",index=None)\ndisplay(submission.head())","metadata":{"papermill":{"duration":0.030287,"end_time":"2024-03-03T17:15:12.110333","exception":false,"start_time":"2024-03-03T17:15:12.080046","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-03-13T10:36:24.727511Z","iopub.execute_input":"2024-03-13T10:36:24.727808Z","iopub.status.idle":"2024-03-13T10:36:24.746767Z","shell.execute_reply.started":"2024-03-13T10:36:24.727783Z","shell.execute_reply":"2024-03-13T10:36:24.745904Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# SANITY CHECK TO CONFIRM PREDICTIONS SUM TO ONE\nsubmission.iloc[:,-6:].sum(axis=1)","metadata":{"papermill":{"duration":0.020742,"end_time":"2024-03-03T17:15:12.143017","exception":false,"start_time":"2024-03-03T17:15:12.122275","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-03-13T10:36:24.75343Z","iopub.execute_input":"2024-03-13T10:36:24.753683Z","iopub.status.idle":"2024-03-13T10:36:24.761711Z","shell.execute_reply.started":"2024-03-13T10:36:24.753662Z","shell.execute_reply":"2024-03-13T10:36:24.760702Z"},"trusted":true},"execution_count":null,"outputs":[]}]}