{"metadata":{"kaggle":{"accelerator":"none","dataSources":[{"sourceId":59093,"databundleVersionId":7469972,"sourceType":"competition"},{"sourceId":160674831,"sourceType":"kernelVersion"},{"sourceId":160700706,"sourceType":"kernelVersion"},{"sourceId":161586765,"sourceType":"kernelVersion"}],"dockerImageVersionId":30635,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false},"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":32.293878,"end_time":"2024-02-05T15:16:39.983407","environment_variables":{},"exception":null,"input_path":"__notebook__.ipynb","output_path":"__notebook__.ipynb","parameters":{},"start_time":"2024-02-05T15:16:07.689529","version":"2.4.0"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"## 📌 Overview","metadata":{"papermill":{"duration":0.00473,"end_time":"2024-02-05T15:16:12.345582","exception":false,"start_time":"2024-02-05T15:16:12.340852","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"#### 📋 Key Aspects of the Notebook\nThis notebook is used for the inference of three pretrained models, ResNet34d, EfficientNetB0 and EfficientnetB1: trained exclusively on the Kaggle-provided data (EEG spectrograms) using a batch size of 16. \n* links:\n    * https://www.kaggle.com/code/andreasbis/hms-train-resnet34d\n    * https://www.kaggle.com/code/andreasbis/hms-train-efficientnetb0\n    * https://www.kaggle.com/code/andreasbis/hms-train-efficientnetb1\n\n\n### 🙏 Acknowledgement\nInspired by the work of @yunsuxiaozi. Don't forget to upvote their work if you find it helpful!\n* links:\n    * https://www.kaggle.com/code/yunsuxiaozi/hms-baseline-resnet34d-512-512-training-5-folds\n    * https://www.kaggle.com/code/yunsuxiaozi/hms-baseline-resnet34d-512-512-inference-6-models","metadata":{"papermill":{"duration":0.002912,"end_time":"2024-02-05T15:16:12.352364","exception":false,"start_time":"2024-02-05T15:16:12.349452","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"## 📙 Import libraries and modules","metadata":{"papermill":{"duration":0.003315,"end_time":"2024-02-05T15:16:12.358850","exception":false,"start_time":"2024-02-05T15:16:12.355535","status":"completed"},"tags":[]}},{"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.execute_input":"2024-02-05T15:16:12.369929Z","iopub.status.busy":"2024-02-05T15:16:12.369295Z","iopub.status.idle":"2024-02-05T15:16:21.495098Z","shell.execute_reply":"2024-02-05T15:16:21.493703Z"},"papermill":{"duration":9.135464,"end_time":"2024-02-05T15:16:21.498701","exception":false,"start_time":"2024-02-05T15:16:12.363237","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## ⚙️ Configuration","metadata":{"papermill":{"duration":0.003531,"end_time":"2024-02-05T15:16:21.506120","exception":false,"start_time":"2024-02-05T15:16:21.502589","status":"completed"},"tags":[]}},{"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.execute_input":"2024-02-05T15:16:21.523632Z","iopub.status.busy":"2024-02-05T15:16:21.523103Z","iopub.status.idle":"2024-02-05T15:16:21.537653Z","shell.execute_reply":"2024-02-05T15:16:21.535824Z"},"papermill":{"duration":0.02447,"end_time":"2024-02-05T15:16:21.540525","exception":false,"start_time":"2024-02-05T15:16:21.516055","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 📂 Data Loading","metadata":{"papermill":{"duration":0.004294,"end_time":"2024-02-05T15:16:21.548986","exception":false,"start_time":"2024-02-05T15:16:21.544692","status":"completed"},"tags":[]}},{"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)\n    \n    # Load the trained weights from the corresponding file\n    model_resnet.load_state_dict(torch.load(f'/kaggle/input/hms-train-resnet34d/resnet34d_fold{i}.pth', map_location=torch.device('cpu')))\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)\n    \n    # Load the trained weights from the corresponding file\n    model_effnet_b0.load_state_dict(torch.load(f'/kaggle/input/hms-train-efficientnetb0/efficientnet_b0_fold{j}.pth', map_location=torch.device('cpu')))\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)\n    \n    # Load the trained weights from the corresponding file\n    model_effnet_b1.load_state_dict(torch.load(f'/kaggle/input/hms-train-efficientnetb1/efficientnet_b1_fold{k}.pth', map_location=torch.device('cpu')))\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.execute_input":"2024-02-05T15:16:21.560516Z","iopub.status.busy":"2024-02-05T15:16:21.560032Z","iopub.status.idle":"2024-02-05T15:16:33.298155Z","shell.execute_reply":"2024-02-05T15:16:33.296986Z"},"papermill":{"duration":11.746399,"end_time":"2024-02-05T15:16:33.300965","exception":false,"start_time":"2024-02-05T15:16:21.554566","status":"completed"},"tags":[]},"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.execute_input":"2024-02-05T15:16:33.313180Z","iopub.status.busy":"2024-02-05T15:16:33.312356Z","iopub.status.idle":"2024-02-05T15:16:33.625020Z","shell.execute_reply":"2024-02-05T15:16:33.623722Z"},"papermill":{"duration":0.322518,"end_time":"2024-02-05T15:16:33.627798","exception":false,"start_time":"2024-02-05T15:16:33.305280","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 🎰 Predictions","metadata":{"papermill":{"duration":0.003477,"end_time":"2024-02-05T15:16:33.635896","exception":false,"start_time":"2024-02-05T15:16:33.632419","status":"completed"},"tags":[]}},{"cell_type":"code","source":"# Define the weights for each model\nweight_resnet34d = 0.32\nweight_effnetb0 = 0.36\nweight_effnetb1 = 0.32\n\n# Get file paths for test spectrograms\npaths = submission['path'].values\ntest_preds = []\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)))[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_preds.append(weighted_pred)\n\n# Convert the list of predictions to a NumPy array for further processing\ntest_preds = np.array(test_preds)\n\n# Reclaim memory no longer in use\ngc.collect()","metadata":{"execution":{"iopub.execute_input":"2024-02-05T15:16:33.646459Z","iopub.status.busy":"2024-02-05T15:16:33.646007Z","iopub.status.idle":"2024-02-05T15:16:37.957169Z","shell.execute_reply":"2024-02-05T15:16:37.956139Z"},"papermill":{"duration":4.319949,"end_time":"2024-02-05T15:16:37.959646","exception":false,"start_time":"2024-02-05T15:16:33.639697","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 🚀 Submission","metadata":{"papermill":{"duration":0.004433,"end_time":"2024-02-05T15:16:37.968145","exception":false,"start_time":"2024-02-05T15:16:37.963712","status":"completed"},"tags":[]}},{"cell_type":"code","source":"# Load the sample submission file and update it with model predictions for each label\nsubmission = pd.read_csv(\"/kaggle/input/hms-harmful-brain-activity-classification/sample_submission.csv\")\nlabels = ['seizure', 'lpd', 'gpd', 'lrda', 'grda', 'other']\n\n# Assign model predictions to respective columns in the submission DataFrame\nfor i in range(len(labels)):\n    submission[f'{labels[i]}_vote'] = test_preds[:, i]\n\n# Save the updated DataFrame as the final submission file\nsubmission.to_csv(\"submission.csv\", index=None)\n\n# Display the first few rows of the submission file\ndisplay(submission.head())\n\n# Reclaim memory no longer in use.\ngc.collect()","metadata":{"execution":{"iopub.execute_input":"2024-02-05T15:16:37.979237Z","iopub.status.busy":"2024-02-05T15:16:37.978679Z","iopub.status.idle":"2024-02-05T15:16:38.245997Z","shell.execute_reply":"2024-02-05T15:16:38.244647Z"},"papermill":{"duration":0.275437,"end_time":"2024-02-05T15:16:38.248291","exception":false,"start_time":"2024-02-05T15:16:37.972854","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]}]}