{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":59093,"databundleVersionId":7469972,"sourceType":"competition"},{"sourceId":7392733,"sourceType":"datasetVersion","datasetId":4297749},{"sourceId":7392775,"sourceType":"datasetVersion","datasetId":4297782},{"sourceId":7447509,"sourceType":"datasetVersion","datasetId":4334995},{"sourceId":7585255,"sourceType":"datasetVersion","datasetId":4415285}],"dockerImageVersionId":30648,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"This is based on the [EfficientNetB0 Starter](https://www.kaggle.com/code/cdeotte/efficientnetb0-starter-lb-0-43) notebook, modified for Pytorch. The original notebook is implemented in Tensorflow.\n\n* Change to pytorch's Dataset and Dataloader\n* Use efficientnet_b0 from torchvision\n* Use pytorch lightning for building the model and training\n* Inference using Trainer on multiple GPUs (DDP strategy) requires adding predictions gathering code, otherwise it will hang waiting for other nodes. So the raw pytorch's inference loop is used in the CV part. This needs to be done after training all the folds since the manual torch's GPU device initialization can't be mixed with lightning's DDP strategy.","metadata":{}},{"cell_type":"code","source":"import os\nimport sys\nimport gc\nsys.path.append('/kaggle/input/kaggle-kl-div')\nfrom kaggle_kl_div import score\n\nimport torch\nfrom torch import nn\nimport torch.nn.functional as F\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision.models import efficientnet_b0, EfficientNet_B0_Weights\nimport pytorch_lightning as pl\nimport pandas as pd, numpy as np\nimport matplotlib.pyplot as plt\nimport albumentations as albu\nfrom sklearn.model_selection import KFold, GroupKFold","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-02-08T02:51:13.494609Z","iopub.execute_input":"2024-02-08T02:51:13.495058Z","iopub.status.idle":"2024-02-08T02:51:13.501648Z","shell.execute_reply.started":"2024-02-08T02:51:13.495012Z","shell.execute_reply":"2024-02-08T02:51:13.500650Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data Loading","metadata":{}},{"cell_type":"code","source":"VER = 5\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/hms-efficientnetb0-pt-ckpts/'\n\nUSE_KAGGLE_SPECTROGRAMS = True\nUSE_EEG_SPECTROGRAMS = True","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-02-08T02:51:13.503791Z","iopub.execute_input":"2024-02-08T02:51:13.504169Z","iopub.status.idle":"2024-02-08T02:51:13.514027Z","shell.execute_reply.started":"2024-02-08T02:51:13.504134Z","shell.execute_reply":"2024-02-08T02:51:13.513120Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv('/kaggle/input/hms-harmful-brain-activity-classification/train.csv')\nTARGETS = df.columns[-6:]\nprint('Train shape:', df.shape )\nprint('Targets', list(TARGETS))\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2024-02-08T02:51:13.515167Z","iopub.execute_input":"2024-02-08T02:51:13.515433Z","iopub.status.idle":"2024-02-08T02:51:13.799453Z","shell.execute_reply.started":"2024-02-08T02:51:13.515410Z","shell.execute_reply":"2024-02-08T02:51:13.798376Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = df.groupby('eeg_id')[\n    ['spectrogram_id', 'spectrogram_label_offset_seconds']\n].agg({'spectrogram_id': 'first', 'spectrogram_label_offset_seconds': 'min'})\ntrain.columns = ['spec_id', 'min']\n\ntmp = df.groupby('eeg_id')[\n    ['spectrogram_id','spectrogram_label_offset_seconds']\n].agg({'spectrogram_label_offset_seconds' :'max'})\ntrain['max'] = tmp\n\ntmp = df.groupby('eeg_id')[['patient_id']].agg('first')\ntrain['patient_id'] = tmp\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()\nprint('Train non-overlapp eeg_id shape:', train.shape )\ntrain.head()","metadata":{"execution":{"iopub.status.busy":"2024-02-08T02:51:13.801587Z","iopub.execute_input":"2024-02-08T02:51:13.801947Z","iopub.status.idle":"2024-02-08T02:51:13.904367Z","shell.execute_reply.started":"2024-02-08T02:51:13.801907Z","shell.execute_reply":"2024-02-08T02:51:13.903374Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"READ_SPEC_FILES = False\n\n# READ ALL SPECTROGRAMS\nPATH = '/kaggle/input/hms-harmful-brain-activity-classification/train_spectrograms/'\nfiles = os.listdir(PATH)\nprint(f'There are {len(files)} spectrogram parquets')\n\nif READ_SPEC_FILES:    \n    spectrograms = {}\n    for i,f in enumerate(files):\n        if i % 100 == 0:\n            print(i, ', ', end='')\n        tmp = pd.read_parquet(f'{PATH}{f}')\n        name = int(f.split('.')[0])\n        spectrograms[name] = tmp.iloc[:,1:].values\nelse:\n    spectrograms = np.load('/kaggle/input/brain-spectrograms/specs.npy',allow_pickle=True).item()","metadata":{"execution":{"iopub.status.busy":"2024-02-08T02:51:13.905581Z","iopub.execute_input":"2024-02-08T02:51:13.905867Z","iopub.status.idle":"2024-02-08T02:52:13.438088Z","shell.execute_reply.started":"2024-02-08T02:51:13.905842Z","shell.execute_reply":"2024-02-08T02:52:13.437203Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"READ_EEG_SPEC_FILES = False\n\nif READ_EEG_SPEC_FILES:\n    all_eegs = {}\n    for i,e in enumerate(train.eeg_id.values):\n        if i % 100 == 0:\n            print(i, ', ', end='')\n        x = np.load(f'/kaggle/input/brain-eeg-spectrograms/EEG_Spectrograms/{e}.npy')\n        all_eegs[e] = x\nelse:\n    all_eegs = np.load('/kaggle/input/brain-eeg-spectrograms/eeg_specs.npy',allow_pickle=True).item()","metadata":{"execution":{"iopub.status.busy":"2024-02-08T02:52:13.439250Z","iopub.execute_input":"2024-02-08T02:52:13.439521Z","iopub.status.idle":"2024-02-08T02:53:24.324298Z","shell.execute_reply.started":"2024-02-08T02:52:13.439498Z","shell.execute_reply":"2024-02-08T02:53:24.323240Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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()}\n\n\nclass EEGDataset(Dataset):\n    \n    def __init__(self, data, augment=False, mode='train', specs=spectrograms, eeg_specs=all_eegs): \n        self.data = data\n        self.augment = augment\n        self.mode = mode\n        self.specs = specs\n        self.eeg_specs = eeg_specs\n        \n    def __len__(self):\n        return len(self.data)\n    \n    def __getitem__(self, index):\n        return self.__getitems__([index])\n    \n    def __getitems__(self, indices):\n        X, y = self._generate_data(indices)\n        if self.augment:\n            X = self._augment(X) \n        if self.mode == 'train':\n            return list(zip(X, y))\n        else:\n            return X\n    \n    def _generate_data(self, indexes):\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(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-02-08T02:53:24.325782Z","iopub.execute_input":"2024-02-08T02:53:24.326119Z","iopub.status.idle":"2024-02-08T02:53:24.345022Z","shell.execute_reply.started":"2024-02-08T02:53:24.326089Z","shell.execute_reply":"2024-02-08T02:53:24.343712Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dataset = EEGDataset(train)\ndataloader = DataLoader(dataset, batch_size=32, shuffle=False)","metadata":{"execution":{"iopub.status.busy":"2024-02-08T02:53:24.346857Z","iopub.execute_input":"2024-02-08T02:53:24.347466Z","iopub.status.idle":"2024-02-08T02:53:24.362302Z","shell.execute_reply.started":"2024-02-08T02:53:24.347436Z","shell.execute_reply":"2024-02-08T02:53:24.361094Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ROWS = 2\nCOLS = 3\nBATCHES = 2\n\nfor i, (x, y) in enumerate(dataloader):\n    plt.figure(figsize=(20, 8))\n    for j in range(ROWS):\n        for k in range(COLS):\n            plt.subplot(ROWS, COLS, j*COLS + k + 1)\n            t = y[j*COLS + k]\n            img = torch.flip(x[j*COLS+k, :, :, 0], (0,))\n            mn = img.flatten().min()\n            mx = img.flatten().max()\n            img = (img-mn)/(mx-mn)\n            plt.imshow(img)\n            tars = f'[{t[0]:0.2f}]'\n            for s in t[1:]:\n                tars += f', {s:0.2f}'\n            eeg = train.eeg_id.values[i*32+j*COLS+k]\n            plt.title(f'EEG = {eeg}\\nTarget = {tars}',size=12)\n            plt.yticks([])\n            plt.ylabel('Frequencies (Hz)',size=14)\n            plt.xlabel('Time (sec)',size=16)\n    plt.show()\n    if i == BATCHES-1:\n        break","metadata":{"execution":{"iopub.status.busy":"2024-02-08T02:53:24.366877Z","iopub.execute_input":"2024-02-08T02:53:24.367195Z","iopub.status.idle":"2024-02-08T02:53:27.015842Z","shell.execute_reply.started":"2024-02-08T02:53:24.367171Z","shell.execute_reply":"2024-02-08T02:53:27.014911Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"del dataset, dataloader\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2024-02-08T02:53:27.017163Z","iopub.execute_input":"2024-02-08T02:53:27.017507Z","iopub.status.idle":"2024-02-08T02:53:27.403155Z","shell.execute_reply.started":"2024-02-08T02:53:27.017478Z","shell.execute_reply":"2024-02-08T02:53:27.402058Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training","metadata":{}},{"cell_type":"code","source":"WEIGHTS_FILE = '/kaggle/input/hms-efficientnetb0-pt-ckpts/efficientnet_b0_rwightman-7f5810bc.pth'\n\n\nclass EEGEffnetB0(pl.LightningModule):\n    \n    def __init__(self):\n        super().__init__()\n        self.base_model = efficientnet_b0()\n        self.base_model.load_state_dict(torch.load(WEIGHTS_FILE))\n        self.base_model.classifier[1] = nn.Linear(self.base_model.classifier[1].in_features, 6, dtype=torch.float32)\n        self.prob_out = nn.Softmax()\n        \n    def forward(self, x):\n        x1 = [x[:, :, :, i:i+1] for i in range(4)]\n        x1 = torch.concat(x1, dim=1)\n        x2 = [x[:, :, :, i+4:i+5] for i in range(4)]\n        x2 = torch.concat(x2, dim=1)\n        \n        if USE_KAGGLE_SPECTROGRAMS & USE_EEG_SPECTROGRAMS:\n            x = torch.concat([x1, x2], dim=2)\n        elif USE_EEG_SPECTROGRAMS:\n            x = x2\n        else:\n            x = x1\n        x = torch.concat([x, x, x], dim=3)\n        x = x.permute(0, 3, 1, 2)\n        \n        out = self.base_model(x)\n        return out\n    \n    def training_step(self, batch, batch_idx):\n        x, y = batch\n        out = self.forward(x)\n        out = F.log_softmax(out, dim=1)\n        kl_loss = nn.KLDivLoss(reduction='batchmean')\n        loss = kl_loss(out, y)\n        return loss\n    \n    def predict_step(self, batch, batch_idx, dataloader_idx=0):\n        return F.softmax(self(batch), dim=1)\n    \n    def configure_optimizers(self):\n        optimizer = torch.optim.Adam(self.parameters(), lr=1e-3)\n        return optimizer","metadata":{"execution":{"iopub.status.busy":"2024-02-08T02:53:27.404637Z","iopub.execute_input":"2024-02-08T02:53:27.405010Z","iopub.status.idle":"2024-02-08T02:53:27.419329Z","shell.execute_reply.started":"2024-02-08T02:53:27.404965Z","shell.execute_reply":"2024-02-08T02:53:27.418337Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"all_oof = []\nall_true = []\nvalid_loaders = []\n\ngkf = GroupKFold(n_splits=5)\nfor i, (train_index, valid_index) in enumerate(gkf.split(train, train.target, train.patient_id)):  \n    print('#'*25)\n    print(f'### Fold {i+1}')\n    \n    train_ds = EEGDataset(train.iloc[train_index])\n    train_loader = DataLoader(train_ds, shuffle=True, batch_size=32, num_workers=3)\n    valid_ds = EEGDataset(train.iloc[valid_index], mode='valid')\n    valid_loader = DataLoader(valid_ds, shuffle=False, batch_size=64, num_workers=3)\n    \n    print(f'### Train size: {len(train_index)}, Valid size: {len(valid_index)}')\n    print('#'*25)\n    \n    trainer = pl.Trainer(max_epochs=4)\n    model = EEGEffnetB0()\n    if LOAD_MODELS_FROM is None:\n        trainer.fit(model=model, train_dataloaders=train_loader)\n        trainer.save_checkpoint(f'EffNet_v{VER}_f{i}.ckpt')\n\n    valid_loaders.append(valid_loader)\n    all_true.append(train.iloc[valid_index][TARGETS].values)\n    del trainer, model\n    gc.collect()","metadata":{"execution":{"iopub.status.busy":"2024-02-08T02:53:27.421774Z","iopub.execute_input":"2024-02-08T02:53:27.422665Z","iopub.status.idle":"2024-02-08T02:53:31.160920Z","shell.execute_reply.started":"2024-02-08T02:53:27.422631Z","shell.execute_reply":"2024-02-08T02:53:31.159989Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")","metadata":{"execution":{"iopub.status.busy":"2024-02-08T02:53:31.162271Z","iopub.execute_input":"2024-02-08T02:53:31.162963Z","iopub.status.idle":"2024-02-08T02:53:31.167636Z","shell.execute_reply.started":"2024-02-08T02:53:31.162925Z","shell.execute_reply":"2024-02-08T02:53:31.166730Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i in range(5):\n    print('#'*25)\n    print(f'### Validating Fold {i+1}')\n\n    ckpt_file = f'EffNet_v{VER}_f{i}.ckpt' if LOAD_MODELS_FROM is None else f'{LOAD_MODELS_FROM}/EffNet_v{VER}_f{i}.ckpt'\n    model = EEGEffnetB0.load_from_checkpoint(ckpt_file)\n    model.to(device).eval()\n    with torch.inference_mode():\n        for val_batch in valid_loaders[i]:\n            val_batch = val_batch.to(device)\n            oof = torch.softmax(model(val_batch), dim=1).cpu().numpy()\n            all_oof.append(oof)\n    del model\n    gc.collect()\n\nall_oof = np.concatenate(all_oof)\nall_true = np.concatenate(all_true)","metadata":{"execution":{"iopub.status.busy":"2024-02-08T02:53:31.169039Z","iopub.execute_input":"2024-02-08T02:53:31.169436Z","iopub.status.idle":"2024-02-08T02:55:26.626298Z","shell.execute_reply.started":"2024-02-08T02:53:31.169399Z","shell.execute_reply":"2024-02-08T02:55:26.625351Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"oof = 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 KL-Div for EfficientNetB2 =',cv)","metadata":{"execution":{"iopub.status.busy":"2024-02-08T02:55:26.628966Z","iopub.execute_input":"2024-02-08T02:55:26.629858Z","iopub.status.idle":"2024-02-08T02:55:26.694344Z","shell.execute_reply.started":"2024-02-08T02:55:26.629818Z","shell.execute_reply":"2024-02-08T02:55:26.693333Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Inference","metadata":{}},{"cell_type":"code","source":"del all_eegs, spectrograms\ngc.collect()\n\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-02-08T02:55:26.695656Z","iopub.execute_input":"2024-02-08T02:55:26.695924Z","iopub.status.idle":"2024-02-08T02:55:27.035327Z","shell.execute_reply.started":"2024-02-08T02:55:26.695900Z","shell.execute_reply":"2024-02-08T02:55:27.034286Z"},"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:\n        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-02-08T02:55:27.036587Z","iopub.execute_input":"2024-02-08T02:55:27.036842Z","iopub.status.idle":"2024-02-08T02:55:27.357554Z","shell.execute_reply.started":"2024-02-08T02:55:27.036819Z","shell.execute_reply":"2024-02-08T02:55:27.356744Z"},"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\n# DENOISE FUNCTION\ndef maddest(d, axis=None):\n    return np.mean(np.absolute(d - np.mean(d, axis)), axis)\n\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\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-02-08T02:55:27.358744Z","iopub.execute_input":"2024-02-08T02:55:27.359072Z","iopub.status.idle":"2024-02-08T02:55:27.459030Z","shell.execute_reply.started":"2024-02-08T02:55:27.359043Z","shell.execute_reply":"2024-02-08T02:55:27.458299Z"},"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-02-08T02:55:27.460075Z","iopub.execute_input":"2024-02-08T02:55:27.460513Z","iopub.status.idle":"2024-02-08T02:55:38.487789Z","shell.execute_reply.started":"2024-02-08T02:55:27.460489Z","shell.execute_reply":"2024-02-08T02:55:38.486675Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# INFER EFFICIENTNET ON TEST\npreds = []\ntest_ds = EEGDataset(test, mode='test', specs=spectrograms2, eeg_specs=all_eegs2)\ntest_loader = DataLoader(test_ds, shuffle=False, batch_size=64, num_workers=3)\n\nfor i in range(5):\n    print('#'*25)\n    print(f'### Testing Fold {i+1}')\n\n    ckpt_file = f'EffNet_v{VER}_f{i}.ckpt' if LOAD_MODELS_FROM is None else f'{LOAD_MODELS_FROM}/EffNet_v{VER}_f{i}.ckpt'\n    model = EEGEffnetB0.load_from_checkpoint(ckpt_file)\n    model.to(device).eval()\n    fold_preds = []\n\n    with torch.inference_mode():\n        for test_batch in test_loader:\n            test_batch = test_batch.to(device)\n            pred = torch.softmax(model(test_batch), dim=1).cpu().numpy()\n            fold_preds.append(pred)\n        fold_preds = np.concatenate(fold_preds)\n\n    preds.append(fold_preds)\n\npred = np.mean(preds,axis=0)\nprint()\nprint('Test preds shape',pred.shape)","metadata":{"execution":{"iopub.status.busy":"2024-02-08T02:55:38.489048Z","iopub.execute_input":"2024-02-08T02:55:38.489535Z","iopub.status.idle":"2024-02-08T02:55:45.174470Z","shell.execute_reply.started":"2024-02-08T02:55:38.489506Z","shell.execute_reply":"2024-02-08T02:55:45.173233Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub = pd.DataFrame({'eeg_id': test.eeg_id.values})\nsub[TARGETS] = pred\nsub.to_csv('submission.csv',index=False)\nprint('Submissionn shape',sub.shape)\nsub.head()","metadata":{"execution":{"iopub.status.busy":"2024-02-08T02:55:45.176413Z","iopub.execute_input":"2024-02-08T02:55:45.176744Z","iopub.status.idle":"2024-02-08T02:55:45.200887Z","shell.execute_reply.started":"2024-02-08T02:55:45.176713Z","shell.execute_reply":"2024-02-08T02:55:45.199983Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# SANITY CHECK TO CONFIRM PREDICTIONS SUM TO ONE\nsub.iloc[:,-6:].sum(axis=1)","metadata":{"execution":{"iopub.status.busy":"2024-02-08T02:55:45.203251Z","iopub.execute_input":"2024-02-08T02:55:45.203614Z","iopub.status.idle":"2024-02-08T02:55:45.211856Z","shell.execute_reply.started":"2024-02-08T02:55:45.203581Z","shell.execute_reply":"2024-02-08T02:55:45.210860Z"},"trusted":true},"execution_count":null,"outputs":[]}]}