{"metadata":{"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":59093,"databundleVersionId":7469972,"sourceType":"competition"},{"sourceId":7713961,"sourceType":"datasetVersion","datasetId":4504881},{"sourceId":7751576,"sourceType":"datasetVersion","datasetId":4503036},{"sourceId":7805987,"sourceType":"datasetVersion","datasetId":4571300},{"sourceId":7841450,"sourceType":"datasetVersion","datasetId":4590753},{"sourceId":7841553,"sourceType":"datasetVersion","datasetId":4597152},{"sourceId":160674831,"sourceType":"kernelVersion"},{"sourceId":160700706,"sourceType":"kernelVersion"},{"sourceId":165876189,"sourceType":"kernelVersion"}],"dockerImageVersionId":30635,"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":25.124296,"end_time":"2024-01-31T13:44:37.422577","environment_variables":{},"exception":null,"input_path":"__notebook__.ipynb","output_path":"__notebook__.ipynb","parameters":{},"start_time":"2024-01-31T13:44:12.298281","version":"2.4.0"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Introduction\n## Acknowledgements\nThe original base of this notebook was copied from @andreasbis. We thank them for supplying a useful baseline to expand upon. Please take a look at their work: https://www.kaggle.com/code/andreasbis/hms-inference-lb-0-41.","metadata":{"papermill":{"duration":0.004736,"end_time":"2024-01-31T13:44:16.548762","exception":false,"start_time":"2024-01-31T13:44:16.544026","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"# Imports","metadata":{"papermill":{"duration":0.003795,"end_time":"2024-01-31T13:44:16.565112","exception":false,"start_time":"2024-01-31T13:44:16.561317","status":"completed"},"tags":[]}},{"cell_type":"code","source":"import gc\nimport os\nimport random\nimport warnings\nimport numpy as np\nimport pandas as pd\nfrom IPython.display import display\n\nimport timm\nimport torch\nimport torch.nn as nn  \nimport torch.optim as optim\nimport torch.nn.functional as F\nimport torchvision.transforms as transforms\n\nfrom scipy import signal\n\nwarnings.filterwarnings('ignore', category=Warning)\ngc.collect()","metadata":{"papermill":{"duration":7.316411,"end_time":"2024-01-31T13:44:23.88558","exception":false,"start_time":"2024-01-31T13:44:16.569169","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-03-14T12:44:28.958138Z","iopub.execute_input":"2024-03-14T12:44:28.958503Z","iopub.status.idle":"2024-03-14T12:44:29.282733Z","shell.execute_reply.started":"2024-03-14T12:44:28.958474Z","shell.execute_reply":"2024-03-14T12:44:29.281690Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Configuration","metadata":{"papermill":{"duration":0.004284,"end_time":"2024-01-31T13:44:23.894634","exception":false,"start_time":"2024-01-31T13:44:23.89035","status":"completed"},"tags":[]}},{"cell_type":"code","source":"class Config:\n    seed = 3131\n    image_transform = transforms.Resize((512, 512))\n    num_folds = 5\n    dataset_wide_mean = -0.2972692229201065 #From Train notebook\n    dataset_wide_std = 2.5997336315611026 #From Train notebook\n    ownspec_mean = 7.29084372799223e-05 \n    ownspec_std = 4.510082606216031\n    \ndef set_seed(seed):\n    torch.backends.cudnn.deterministic = True\n    torch.backends.cudnn.benchmark = True\n    \n    torch.manual_seed(seed)\n    np.random.seed(seed)\n    random.seed(seed)\n    \nset_seed(Config.seed)","metadata":{"papermill":{"duration":0.020203,"end_time":"2024-01-31T13:44:23.919672","exception":false,"start_time":"2024-01-31T13:44:23.899469","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-03-14T12:44:30.674007Z","iopub.execute_input":"2024-03-14T12:44:30.674361Z","iopub.status.idle":"2024-03-14T12:44:30.681748Z","shell.execute_reply.started":"2024-03-14T12:44:30.674333Z","shell.execute_reply":"2024-03-14T12:44:30.680904Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data Loading","metadata":{}},{"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\")\n\nsubmission = submission.merge(test_df, on='eeg_id', how='left')\nsubmission['path_spec'] = submission['spectrogram_id'].apply(lambda x: f\"/kaggle/input/hms-harmful-brain-activity-classification/test_spectrograms/{x}.parquet\")\nsubmission['path_eeg'] = submission['eeg_id'].apply(lambda x: f\"/kaggle/input/hms-harmful-brain-activity-classification/test_eegs/{x}.parquet\")\n\ndisplay(submission)\n\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2024-03-14T12:44:31.965927Z","iopub.execute_input":"2024-03-14T12:44:31.966272Z","iopub.status.idle":"2024-03-14T12:44:32.287394Z","shell.execute_reply.started":"2024-03-14T12:44:31.966245Z","shell.execute_reply":"2024-03-14T12:44:32.286537Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model Loading","metadata":{"papermill":{"duration":0.004821,"end_time":"2024-01-31T13:44:23.929301","exception":false,"start_time":"2024-01-31T13:44:23.92448","status":"completed"},"tags":[]}},{"cell_type":"code","source":"models = []\n\nfor i in range(Config.num_folds):\n\n    model_effnet_b0 = timm.create_model('efficientnet_b0', pretrained=False, num_classes=6, in_chans=1)\n    model_effnet_b0.load_state_dict(torch.load(f'/kaggle/input/hms-train-efficientnetb0/efficientnet_b0_fold{i}.pth', map_location=torch.device('cpu')))\n    models.append(model_effnet_b0)\n    \nmodels_datawide1 = []\n\nfor i in range(Config.num_folds):\n    model_effnet_b1 = timm.create_model('efficientnet_b1', pretrained=False, num_classes=6, in_chans=1)\n    model_effnet_b1.load_state_dict(torch.load(f'/kaggle/input/train/efficientnet_b1_fold{i}.pth', map_location=torch.device('cpu')))\n    models_datawide1.append(model_effnet_b1)\n    \nmodels_ownspec = []\nfor i in range(Config.num_folds):\n    model_effnet_b1 = timm.create_model('efficientnet_b1', pretrained=False, num_classes=6, in_chans=1)\n    model_effnet_b1.load_state_dict(torch.load(f'/kaggle/input/efficientnet-b1-ownspectrograms/efficientnet_b1_fold{i}_datawide_CosineAnnealingLR_0.001_False.pth', map_location=torch.device('cpu')))\n    models_ownspec.append(model_effnet_b1)\n    \ngc.collect()","metadata":{"papermill":{"duration":8.323585,"end_time":"2024-01-31T13:44:32.257623","exception":false,"start_time":"2024-01-31T13:44:23.934038","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-03-14T12:44:33.655349Z","iopub.execute_input":"2024-03-14T12:44:33.655732Z","iopub.status.idle":"2024-03-14T12:44:36.398060Z","shell.execute_reply.started":"2024-03-14T12:44:33.655700Z","shell.execute_reply":"2024-03-14T12:44:36.397149Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model Prediction","metadata":{"papermill":{"duration":0.005046,"end_time":"2024-01-31T13:44:32.51501","exception":false,"start_time":"2024-01-31T13:44:32.509964","status":"completed"},"tags":[]}},{"cell_type":"code","source":"def create_spectrogram(data):\n    nperseg = 150  # Length of each segment\n    noverlap = 128  # Overlap between segments\n    NFFT = max(256, 2 ** int(np.ceil(np.log2(nperseg))))\n\n    # LL Spec = ( spec(Fp1 - F7) + spec(F7 - T3) + spec(T3 - T5) + spec(T5 - O1) )/4\n    freqs, t,spectrum_LL1 = signal.spectrogram(data['Fp1']-data['F7'],nfft=NFFT,noverlap = noverlap,nperseg=nperseg)\n    freqs, t,spectrum_LL2 = signal.spectrogram(data['F7']-data['T3'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n    freqs, t,spectrum_LL3 = signal.spectrogram(data['T3']-data['T5'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n    freqs, t,spectrum_LL4 = signal.spectrogram(data['T5']-data['O1'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n\n    LL = (spectrum_LL1+ spectrum_LL2 +spectrum_LL3 + spectrum_LL4)/4\n\n    # LP Spec = ( spec(Fp1 - F3) + spec(F3 - C3) + spec(C3 - P3) + spec(P3 - O1) )/4\n    freqs, t,spectrum_LP1 = signal.spectrogram(data['Fp1']-data['F3'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n    freqs, t,spectrum_LP2 = signal.spectrogram(data['F3']-data['C3'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n    freqs, t,spectrum_LP3 = signal.spectrogram(data['C3']-data['P3'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n    freqs, t,spectrum_LP4 = signal.spectrogram(data['P3']-data['O1'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n\n    LP = (spectrum_LP1+ spectrum_LP2 +spectrum_LP3 + spectrum_LP4)/4\n\n    # RP Spec = ( spec(Fp2 - F4) + spec(F4 - C4) + spec(C4 - P4) + spec(P4 - O2) )/4\n    freqs, t,spectrum_RP1 = signal.spectrogram(data['Fp2']-data['F4'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n    freqs, t,spectrum_RP2 = signal.spectrogram(data['F4']-data['C4'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n    freqs, t,spectrum_RP3 = signal.spectrogram(data['C4']-data['P4'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n    freqs, t,spectrum_RP4 = signal.spectrogram(data['P4']-data['O2'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n\n    RP = (spectrum_RP1+ spectrum_RP2 +spectrum_RP3 + spectrum_RP4)/4\n\n\n    # RL Spec = ( spec(Fp2 - F8) + spec(F8 - T4) + spec(T4 - T6) + spec(T6 - O2) )/4\n    freqs, t,spectrum_RL1 = signal.spectrogram(data['Fp2']-data['F8'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n    freqs, t,spectrum_RL2 = signal.spectrogram(data['F8']-data['T4'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n    freqs, t,spectrum_RL3 = signal.spectrogram(data['T4']-data['T6'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n    freqs, t,spectrum_RL4 = signal.spectrogram(data['T6']-data['O2'],nfft=NFFT, noverlap = noverlap,nperseg=nperseg)\n    RL = (spectrum_RL1+ spectrum_RL2 +spectrum_RL3 + spectrum_RL4)/4\n    spectogram = np.concatenate((LL, LP,RP,RL), axis=0)\n    return spectogram\n\ndef preprocess_ownspec(path_to_parquet):\n    data = pd.read_parquet(path_to_parquet)\n    data = create_spectrogram(data)\n    mask = np.isnan(data)\n    data[mask] = -1\n    data = np.clip(data, np.exp(-6), np.exp(10))\n    data = np.log(data)\n    \n    return data \n\ndef preprocess(path_to_parquet):\n    data = pd.read_parquet(path_to_parquet)\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    return data\n\n\ndef normalize_datawide1(data_point):\n    eps = 1e-6\n\n    data_point = (data_point - Config.dataset_wide_mean) / (Config.dataset_wide_std + eps)\n\n    data_tensor = torch.unsqueeze(torch.Tensor(data_point), dim=0)\n    data_point = Config.image_transform(data_tensor)\n\n    return data_point\n\ndef normalize_datawide2(data,data_mean,data_std):\n    eps = 1e-6\n    \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    return data\n\ndef normalize_datawide_ownspec(data):\n    eps = 1e-6\n    \n    data = (data - Config.ownspec_mean) / (Config.ownspec_std + eps)\n    data_tensor = torch.unsqueeze(torch.Tensor(data), dim=0)\n    data = Config.image_transform(data_tensor)\n    \n    return data\n\n\ndef normalize_instance_wise(data_point):\n    eps = 1e-6\n    \n    data_mean = data_point.mean(axis=(0, 1))\n    data_std = data_point.std(axis=(0, 1))\n    data_point = (data_point - data_mean) / (data_std + eps)\n    \n    data_tensor = torch.unsqueeze(torch.Tensor(data_point), dim=0)\n    data_point = Config.image_transform(data_tensor)\n    \n    return data_point\n\ntest_predictions = []\ntest_predictions_avg = []\n\n# for path in paths_to_parquets:\nfor index in submission.index:\n    test_predictions_per_model = []\n    \n    preprocessed_data = preprocess(submission.iloc[index]['path_spec'])\n    preprocessed_data_ownspec = preprocess_ownspec(submission.iloc[index]['path_eeg'])\n    \n    for i in range(len(models)):\n        models[i].eval()\n        \n        current_parquet_data = normalize_instance_wise(preprocessed_data).unsqueeze(0)\n        \n        with torch.no_grad():\n            model_output = models[i](current_parquet_data)\n            current_model_prediction = F.softmax(model_output)[0].detach().cpu().numpy()\n            \n        test_predictions_per_model.append(current_model_prediction)\n    \n    for i in range(len(models_datawide1)):\n        models_datawide1[i].eval()\n        \n        current_parquet_data = normalize_datawide1(preprocessed_data).unsqueeze(0)\n        \n        with torch.no_grad():\n            model_output = models_datawide1[i](current_parquet_data)\n            current_model_prediction = F.softmax(model_output)[0].detach().cpu().numpy()\n            \n        test_predictions_per_model.append(current_model_prediction)\n    \n    for i in range(len(models_ownspec)):\n        models_ownspec[i].eval()\n        \n        current_parquet_data = normalize_datawide_ownspec(preprocessed_data_ownspec).unsqueeze(0)\n        \n        with torch.no_grad():\n            model_output = models_ownspec[i](current_parquet_data)\n            current_model_prediction = F.softmax(model_output)[0].detach().cpu().numpy()\n            \n        test_predictions_per_model.append(current_model_prediction)\n        \n    test_predictions_avg.append(np.mean(test_predictions_per_model, axis=0))\n    test_predictions.append(test_predictions_per_model)\n\nprint(test_predictions)\nprint(test_predictions_avg)\n\ngc.collect()","metadata":{"papermill":{"duration":3.347489,"end_time":"2024-01-31T13:44:35.868241","exception":false,"start_time":"2024-01-31T13:44:32.520752","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-03-14T12:44:44.036016Z","iopub.execute_input":"2024-03-14T12:44:44.036370Z","iopub.status.idle":"2024-03-14T12:44:46.783743Z","shell.execute_reply.started":"2024-03-14T12:44:44.036340Z","shell.execute_reply":"2024-03-14T12:44:46.782781Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def make_df(data):\n    labels = ['seizure', 'lpd', 'gpd', 'lrda', 'grda', 'other']\n    meta_df = pd.DataFrame(columns=['training_instance','model_id']+labels)\n    \n    count = 0\n    for i, instance in enumerate(data):\n        for j, model in enumerate(instance):\n            meta_df.loc[count] = [i, j, model[0], model[1], model[2], model[3], model[4], model[5]]\n            count += 1\n    return meta_df\n\ndf = make_df(test_predictions)\ndisplay(df)","metadata":{"execution":{"iopub.status.busy":"2024-03-14T12:45:01.131123Z","iopub.execute_input":"2024-03-14T12:45:01.131474Z","iopub.status.idle":"2024-03-14T12:45:01.168417Z","shell.execute_reply.started":"2024-03-14T12:45:01.131443Z","shell.execute_reply":"2024-03-14T12:45:01.167550Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels = ['seizure', 'lpd', 'gpd', 'lrda', 'grda', 'other']\nmax_df = df.groupby(['training_instance'])[labels].agg('max').reset_index()\nmin_df = df.groupby(['training_instance'])[labels].agg('min').reset_index()\nmean_df = df.groupby(['training_instance'])[labels].agg('mean').reset_index()\nmedian_df = df.groupby(['training_instance'])[labels].agg('median').reset_index()\nstd_df = df.groupby(['training_instance'])[labels].agg('std').reset_index()","metadata":{"execution":{"iopub.status.busy":"2024-03-14T12:45:04.346449Z","iopub.execute_input":"2024-03-14T12:45:04.347064Z","iopub.status.idle":"2024-03-14T12:45:04.364423Z","shell.execute_reply.started":"2024-03-14T12:45:04.347029Z","shell.execute_reply":"2024-03-14T12:45:04.363359Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def df2tensor(df):\n    max_list = df[labels].values.tolist()\n    max_tensor = torch.tensor(max_list)\n    max_tensor.shape\n    return max_tensor\n\nmax_tensor = df2tensor(max_df)\nmin_tensor = df2tensor(min_df)\nmean_tensor = df2tensor(mean_df)\nmedian_tensor = df2tensor(median_df)\nstd_tensor = df2tensor(std_df)","metadata":{"execution":{"iopub.status.busy":"2024-03-14T12:45:04.666252Z","iopub.execute_input":"2024-03-14T12:45:04.666724Z","iopub.status.idle":"2024-03-14T12:45:04.678264Z","shell.execute_reply.started":"2024-03-14T12:45:04.666686Z","shell.execute_reply":"2024-03-14T12:45:04.677323Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"input_data = torch.tensor(test_predictions)\ninput_meta = torch.cat([max_tensor.unsqueeze(1), min_tensor.unsqueeze(1), \n                        mean_tensor.unsqueeze(1), std_tensor.unsqueeze(1), median_tensor.unsqueeze(1)], 1)\ninput_meta.shape","metadata":{"execution":{"iopub.status.busy":"2024-03-14T12:54:35.152625Z","iopub.execute_input":"2024-03-14T12:54:35.152988Z","iopub.status.idle":"2024-03-14T12:54:35.161736Z","shell.execute_reply.started":"2024-03-14T12:54:35.152959Z","shell.execute_reply":"2024-03-14T12:54:35.160633Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class MLP(nn.Module):\n    def __init__(self, input_size):\n        super(MLP, self).__init__()\n        self.layers = nn.Sequential(\n            nn.Linear(input_size*6, 600),\n            nn.ReLU(),\n            nn.Linear(600, 1200),\n            nn.ReLU(),\n            nn.Linear(1200, 1000),\n            nn.ReLU(),\n            nn.Linear(1000, 600),\n            nn.ReLU(),\n            nn.Linear(600, 6),\n            nn.Softmax(1)\n        )\n        \n    def forward(self, x):\n        # convert tensor (64, 20, 6) --> (64, 20*6)\n        x = x.view(x.size(0), -1)\n        x = self.layers(x)\n        return x\n\n    \nmeta_model = MLP(input_meta.shape[1])\nmeta_model.load_state_dict(torch.load('/kaggle/input/d/mariekevanvreeswijk/meta-model/meta_model_best.pth'))\nmeta_model","metadata":{"execution":{"iopub.status.busy":"2024-03-14T12:55:52.233718Z","iopub.execute_input":"2024-03-14T12:55:52.234459Z","iopub.status.idle":"2024-03-14T12:55:52.276676Z","shell.execute_reply.started":"2024-03-14T12:55:52.234427Z","shell.execute_reply":"2024-03-14T12:55:52.275820Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with torch.no_grad():\n    test_prediction_final = meta_model(input_meta).numpy()","metadata":{"execution":{"iopub.status.busy":"2024-03-14T12:54:42.460342Z","iopub.execute_input":"2024-03-14T12:54:42.461191Z","iopub.status.idle":"2024-03-14T12:54:42.467373Z","shell.execute_reply.started":"2024-03-14T12:54:42.461154Z","shell.execute_reply":"2024-03-14T12:54:42.466294Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Submission","metadata":{"papermill":{"duration":0.005407,"end_time":"2024-01-31T13:44:35.879854","exception":false,"start_time":"2024-01-31T13:44:35.874447","status":"completed"},"tags":[]}},{"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']\n\nfor i in range(len(labels)):\n    submission[f'{labels[i]}_vote'] = test_prediction_final[:, i]\n\nsubmission.to_csv(\"submission.csv\", index=None)\ndisplay(submission)\n\ngc.collect()","metadata":{"papermill":{"duration":0.205534,"end_time":"2024-01-31T13:44:36.090899","exception":false,"start_time":"2024-01-31T13:44:35.885365","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-03-13T12:05:19.598812Z","iopub.execute_input":"2024-03-13T12:05:19.599510Z","iopub.status.idle":"2024-03-13T12:05:20.619776Z","shell.execute_reply.started":"2024-03-13T12:05:19.599478Z","shell.execute_reply":"2024-03-13T12:05:20.618391Z"},"trusted":true},"execution_count":null,"outputs":[]}]}