{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":99552,"databundleVersionId":13762876,"sourceType":"competition"}],"dockerImageVersionId":31090,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport sys\nimport gc\nimport json\nimport shutil\nimport warnings\nfrom pathlib import Path\nfrom typing import List, Tuple, Dict, Optional\n\nimport numpy as np\nimport polars as pl\nimport pandas as pd\nimport pydicom\nimport cv2\nfrom scipy import ndimage\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.cuda.amp import autocast\nimport timm\n\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2\n\nimport kaggle_evaluation.rsna_inference_server\n\nwarnings.filterwarnings('ignore')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-18T12:07:12.940131Z","iopub.execute_input":"2025-09-18T12:07:12.94104Z","iopub.status.idle":"2025-09-18T12:07:12.946593Z","shell.execute_reply.started":"2025-09-18T12:07:12.941011Z","shell.execute_reply":"2025-09-18T12:07:12.94579Z"}},"outputs":[],"execution_count":3},{"cell_type":"code","source":"#Для первой модели, которая определяет положение аневризмы, я добавил один доп класс, чтобы модель могла работать с сериями, в которых\n# нет аневризмы. Я просто потом создам новую фичу, которая будет дублировать AP фичу, но реверснутую, мол 0 если есть аневризма и 1 если нет.\nlabels_dataset = pd.read_csv('/kaggle/input/rsna-intracranial-aneurysm-detection/train.csv')\nlabels_dataset['None'] = 1 - labels_dataset['Aneurysm Present']\nlabels_dataset = labels_dataset.drop(columns=['PatientAge', 'PatientSex', 'Modality','Aneurysm Present'])\nLABEL_DICT = {\n1:'Other Posterior Circulation',\n2:'Basilar Tip',\n3:'Right Posterior Communicating Artery',\n4:'Left Posterior Communicating Artery',\n5:'Right Infraclinoid Internal Carotid Artery',\n6:'Left Infraclinoid Internal Carotid Artery',\n7:'Right Supraclinoid Internal Carotid Artery',\n8:\t'Left Supraclinoid Internal Carotid Artery',\n9:\t'Right Middle Cerebral Artery',\n10:\t'Left Middle Cerebral Artery',\n11:\t'Right Anterior Cerebral Artery',\n12:'Left Anterior Cerebral Artery',\n13:\t'Anterior Communicating Artery',\n14: 'None'\n}\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n# Competition constants\nID_COL = 'SeriesInstanceUID'\nLABEL_COLS = [\n    'Left Infraclinoid Internal Carotid Artery',\n    'Right Infraclinoid Internal Carotid Artery',\n    'Left Supraclinoid Internal Carotid Artery',\n    'Right Supraclinoid Internal Carotid Artery',\n    'Left Middle Cerebral Artery',\n    'Right Middle Cerebral Artery',\n    'Anterior Communicating Artery',\n    'Left Anterior Cerebral Artery',\n    'Right Anterior Cerebral Artery',\n    'Left Posterior Communicating Artery',\n    'Right Posterior Communicating Artery',\n    'Basilar Tip',\n    'Other Posterior Circulation',\n    'Aneurysm Present',\n]\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-18T12:07:15.718434Z","iopub.execute_input":"2025-09-18T12:07:15.718697Z","iopub.status.idle":"2025-09-18T12:07:15.811171Z","shell.execute_reply.started":"2025-09-18T12:07:15.71868Z","shell.execute_reply":"2025-09-18T12:07:15.810364Z"}},"outputs":[],"execution_count":4},{"cell_type":"code","source":"#4 головы для 4 типов фоточег и один VGG экстрактор\nclass VGG16_EXTRACT(nn.Module):\n    def __init__(self):\n        super().__init__()\n        self.adaptive_pool = nn.AdaptiveAvgPool2d((256, 256))  \n        self.conv = nn.Sequential(\n            nn.Conv2d(in_channels=32,out_channels=64,padding=1,kernel_size=(3,3)),\n            nn.LeakyReLU(),\n            nn.Conv2d(in_channels=64,out_channels=64,padding=1,kernel_size=(3,3)),\n            nn.LeakyReLU(),\n            nn.MaxPool2d(kernel_size=(3,3),stride=1),\n            \n            nn.Conv2d(in_channels=64,out_channels=128,padding=1,kernel_size=(3,3)),\n            nn.LeakyReLU(),\n            nn.Conv2d(in_channels=128,out_channels=128,padding=1,kernel_size=(3,3)),\n            nn.LeakyReLU(),\n            nn.MaxPool2d(kernel_size=(3,3),stride=1),\n            \n            nn.Conv2d(in_channels=128,out_channels=256,padding=1,kernel_size=(3,3)),\n            nn.LeakyReLU(),\n            nn.Conv2d(in_channels=256,out_channels=256,padding=1,kernel_size=(3,3)),\n            nn.LeakyReLU(),\n            nn.Conv2d(in_channels=256,out_channels=256,padding=1,kernel_size=(3,3)),\n            nn.LeakyReLU(),\n            nn.MaxPool2d(kernel_size=(3,3),stride=1),\n\n            nn.Conv2d(in_channels=256,out_channels=512,padding=1,kernel_size=(3,3)),\n            nn.LeakyReLU(),\n            nn.Conv2d(in_channels=512,out_channels=512,padding=1,kernel_size=(3,3)),\n            nn.LeakyReLU(),\n            nn.Conv2d(in_channels=512,out_channels=512,padding=1,kernel_size=(3,3)),\n            nn.LeakyReLU(),\n            nn.MaxPool2d(kernel_size=(3,3),stride=1),\n\n            #nn.Conv2d(in_channels=512,out_channels=512,padding=1,kernel_size=(3,3)),\n            #nn.LeakyReLU(),\n            #nn.Conv2d(in_channels=512,out_channels=512,padding=1,kernel_size=(3,3)),\n            #nn.LeakyReLU(),\n            #nn.Conv2d(in_channels=512,out_channels=512,padding=1,kernel_size=(3,3)),\n            #nn.LeakyReLU(),\n            #nn.MaxPool2d(kernel_size=(3,3),stride=1)\n        )\n    def forward(self,batch):\n        batch = self.conv(batch)\n        batch = self.adaptive_pool(batch)\n        batch = torch.flatten(batch,start_dim=1)\n        return batch\n\nclass MRIT1HEAD(nn.Module):\n    def __init__(self):\n        super().__init__()\n        self.lin = nn.Sequential(\n            nn.Linear(71616512,100),\n            nn.LeakyReLU(),\n            nn.Dropout(0.5),\n            nn.Linear(100,14),\n        )\n    def forward(self,batch):\n        return self.lin(batch)\n\nclass CTAHEAD(nn.Module):\n    def __init__(self):\n        super().__init__()\n        self.lin = nn.Sequential(\n            nn.Linear(32*32,4096),\n            nn.LeakyReLU(),\n            nn.Dropout(0.5),\n            nn.Linear(4096,4096),\n            nn.LeakyReLU(),\n            nn.Dropout(0.5),\n            nn.Linear(4096,14),\n        )\n    def forward(self,batch):\n        return self.lin(batch)\n\nclass MRIT2HEAD(nn.Module):\n    def __init__(self):\n        super().__init__()\n        self.lin = nn.Sequential(\n            nn.Linear(32*32,4096),\n            nn.LeakyReLU(),\n            nn.Dropout(0.5),\n            nn.Linear(4096,4096),\n            nn.LeakyReLU(),\n            nn.Dropout(0.5),\n            nn.Linear(4096,14),\n        )\n    def forward(self,batch):\n        return self.lin(batch)\n\nclass MRAHEAD(nn.Module):\n    def __init__(self):\n        super().__init__()\n        self.lin = nn.Sequential(\n            nn.Linear(16*15,1000),\n            nn.LeakyReLU(),\n            nn.Dropout(0.5),\n            nn.Linear(1000,14),\n        )\n    def forward(self,batch):\n        return self.lin(batch)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-18T12:02:58.067931Z","iopub.execute_input":"2025-09-18T12:02:58.068295Z","iopub.status.idle":"2025-09-18T12:02:58.080539Z","shell.execute_reply.started":"2025-09-18T12:02:58.068271Z","shell.execute_reply":"2025-09-18T12:02:58.079691Z"}},"outputs":[],"execution_count":16},{"cell_type":"code","source":"#основная модель\ntable = pd.read_csv('/kaggle/input/rsna-intracranial-aneurysm-detection/train.csv')\nclass VGG16_with_MHA(nn.Module):\n    def __init__(self):\n        super().__init__()\n        self.extract = VGG16_EXTRACT()\n        self.head =  MRIT1HEAD()\n        \n    \n    def forward(self,data):\n        extracted_feature_maps = self.extract(data)\n        output = self.head(extracted_feature_maps)\n        return output","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-18T12:03:01.030265Z","iopub.execute_input":"2025-09-18T12:03:01.030558Z","iopub.status.idle":"2025-09-18T12:03:01.049892Z","shell.execute_reply.started":"2025-09-18T12:03:01.030537Z","shell.execute_reply":"2025-09-18T12:03:01.049122Z"}},"outputs":[],"execution_count":17},{"cell_type":"code","source":"from torch import tensor\nimport tqdm\nmodel = VGG16_with_MHA()\nmodel.to(device)\ncriterion = nn.CrossEntropyLoss()\noptimizer = torch.optim.AdamW(model.parameters(), lr=1e-3, weight_decay=1e-4)\nscheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, patience=5)\n\nfor epoch in tqdm(range(100)):\n    total_loss = 0\n    model.train()\n    seq_ids = os.listdir('/kaggle/input/rsna-intracranial-aneurysm-detection/series')\n    for seq_id in seq_ids: \n        series_path = os.path.join('/kaggle/input/rsna-intracranial-aneurysm-detection/series',seq_id)\n        data = np.expand_dims(process_dicom_series_safe(series_path, CFG.target_shape),axis=0)\n        data = tensor(data).to(device).float()\n        print('screen transfered to device')\n        break\n        optimizer.zero_grad()\n        output = model(data).cpu().numpy()\n        y_true = labels_dataset.iloc[labels_dataset['SeriesInstanceUID'] == seq_id].to_numpy()\n        loss = criterion(output,y_true)\n        loss.backward()\n        optimizer.step()\n        total_loss+=loss.item\n    \n    print(f'epoch:{epoch},total_loss:{total_loss}')\n        \n   \n    ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-18T12:03:03.890514Z","iopub.execute_input":"2025-09-18T12:03:03.891161Z","execution_failed":"2025-09-18T12:03:11.37Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"if __name__ == '__main__':\n    # Pre-load models at startup\n    load_models()\n\n    # Initialize and run the inference server\n    inference_server = kaggle_evaluation.rsna_inference_server.RSNAInferenceServer(predict)\n\n    # Check environment and run accordingly\n    if os.getenv('KAGGLE_IS_COMPETITION_RERUN'):\n        inference_server.serve()\n    else:\n        # For local testing, run the gateway\n        inference_server.run_local_gateway()\n        \n        # Display local submission file for verification\n        if os.path.exists('/kaggle/working/submission.parquet'):\n            submission_df = pl.read_parquet('/kaggle/working/submission.parquet')\n            print(\"Local submission file created:\")\n            print(submission_df)","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}