{"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":"gpu","dataSources":[{"sourceId":13451,"databundleVersionId":1188070,"sourceType":"competition"}],"dockerImageVersionId":30664,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import re\nimport os\nimport torch\nimport pydicom\nimport numpy as np\nimport random\nimport pandas as pd\nimport torch.nn as nn\nfrom torch import optim\nfrom torchvision import transforms\nimport torchvision\nfrom torchvision.models import inception_v3\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom torch.utils.data import Dataset\n\nrandom.seed(42)\nnp.random.seed(42)\ntorch.manual_seed(42)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-03-10T03:51:25.251596Z","iopub.execute_input":"2024-03-10T03:51:25.251938Z","iopub.status.idle":"2024-03-10T03:51:32.587351Z","shell.execute_reply.started":"2024-03-10T03:51:25.251909Z","shell.execute_reply":"2024-03-10T03:51:32.586392Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import warnings\nwarnings.simplefilter(action='ignore', category=FutureWarning)","metadata":{"execution":{"iopub.status.busy":"2024-03-10T03:51:32.589388Z","iopub.execute_input":"2024-03-10T03:51:32.590171Z","iopub.status.idle":"2024-03-10T03:51:32.595185Z","shell.execute_reply.started":"2024-03-10T03:51:32.590135Z","shell.execute_reply":"2024-03-10T03:51:32.594315Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TRAIN_PATH= r'/kaggle/input/rsna-intracranial-hemorrhage-detection/rsna-intracranial-hemorrhage-detection/stage_2_train'\ndevice= 'cuda' if torch.cuda.is_available() else 'cpu'","metadata":{"execution":{"iopub.status.busy":"2024-03-10T03:51:32.596148Z","iopub.execute_input":"2024-03-10T03:51:32.596436Z","iopub.status.idle":"2024-03-10T03:51:32.62745Z","shell.execute_reply.started":"2024-03-10T03:51:32.596413Z","shell.execute_reply":"2024-03-10T03:51:32.626637Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def preprocess(path):\n    traindf= pd.read_csv('/kaggle/input/rsna-intracranial-hemorrhage-detection/rsna-intracranial-hemorrhage-detection/stage_2_train.csv')\n    traindf[['ID','Subtype']]= traindf['ID'].str.rsplit(pat='_',n=1,expand=True)\n    traindf= traindf.pivot_table(columns='Subtype',values='Label',index='ID').reset_index()\n    traindf.replace([np.inf, -np.inf], np.nan, inplace=True)\n    traindf['any']= traindf['any'].apply(lambda x : 0.0 if x==1.0 else 1.0)\n    \n    return sample(traindf)","metadata":{"execution":{"iopub.status.busy":"2024-03-10T03:51:32.628657Z","iopub.execute_input":"2024-03-10T03:51:32.62889Z","iopub.status.idle":"2024-03-10T03:51:32.646551Z","shell.execute_reply.started":"2024-03-10T03:51:32.628869Z","shell.execute_reply":"2024-03-10T03:51:32.645591Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def sample(traindf):\n    not_any= traindf[traindf['any']==1.0]\n    epidural = traindf[traindf['epidural']==1.0]\n    intraparenchymal = traindf[traindf['intraparenchymal']==1.0]\n    intraventricular = traindf[traindf['intraventricular']==1.0]\n    subarachnoid = traindf[traindf['subarachnoid']==1.0]\n    subdural = traindf[traindf['subdural']==1.0]\n    data= [not_any, epidural, intraparenchymal, intraventricular, subarachnoid, subdural]\n    lim= min([i.shape[0] for i in data])\n    n= not_any.sample(lim*4)\n    df= pd.concat([i.sample(lim) for i in data], axis=0)\n    df= pd.concat([df,n],axis=0)\n    return df","metadata":{"execution":{"iopub.status.busy":"2024-03-10T03:51:32.649176Z","iopub.execute_input":"2024-03-10T03:51:32.649497Z","iopub.status.idle":"2024-03-10T03:51:32.656958Z","shell.execute_reply.started":"2024-03-10T03:51:32.649467Z","shell.execute_reply":"2024-03-10T03:51:32.656068Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = preprocess(r'/kaggle/input/rsna-intracranial-hemorrhage-detection/rsna-intracranial-hemorrhage-detection/stage_2_train.csv')","metadata":{"execution":{"iopub.status.busy":"2024-03-10T03:51:32.658239Z","iopub.execute_input":"2024-03-10T03:51:32.658765Z","iopub.status.idle":"2024-03-10T03:51:54.639911Z","shell.execute_reply.started":"2024-03-10T03:51:32.658733Z","shell.execute_reply":"2024-03-10T03:51:54.639068Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class DicomDataset(Dataset):\n    def __init__(self, img_dir, df, transform=None, labels=True):\n        self.transform = transform\n        self.img_dir = img_dir\n        self.df = df\n        self.labels=labels\n        \n    def correct_dcm(self, dcm):\n        x = dcm.pixel_array + 1000\n        px_mode = 4096\n        x[x>=px_mode] = x[x>=px_mode] - px_mode\n        dcm.PixelData = x.tobytes()\n        dcm.RescaleIntercept = -1000\n\n    def window_image(self, dcm, window_center, window_width):\n\n        if (dcm.BitsStored == 12) and (dcm.PixelRepresentation == 0) and (int(dcm.RescaleIntercept) > -100):\n            self.correct_dcm(dcm)\n\n        img = dcm.pixel_array * dcm.RescaleSlope + dcm.RescaleIntercept\n        img_min = window_center - window_width // 2\n        img_max = window_center + window_width // 2\n        img = np.clip(img, img_min, img_max)\n\n        return img\n\n    def bsb_window(self, dcm):\n        brain_img = self.window_image(dcm, 40, 80)\n        subdural_img = self.window_image(dcm, 80, 200)\n        soft_img = self.window_image(dcm, 40, 380)\n\n        brain_img = (brain_img - 0) / 80\n        subdural_img = (subdural_img - (-20)) / 200\n        soft_img = (soft_img - (-150)) / 380\n        bsb_img = np.array([brain_img, subdural_img, soft_img]).transpose(1,2,0)\n\n        return bsb_img\n    \n#     def zero_center(self, image):\n#         image = image - PIXEL_MEAN\n#         return image\n    \n    \n    def __len__(self):\n        return len(self.df)\n    \n    def __getitem__(self, idx):\n        if torch.is_tensor(idx):\n            idx = idx.tolist()\n            \n        img_path = os.path.join(self.img_dir, self.df.iloc[idx, 0]+'.dcm')\n        data = pydicom.read_file(img_path)\n        img = self.bsb_window(data)\n        \n        if self.transform:       \n            augmented = self.transform(image=img)\n            img = augmented['image']\n        \n        if self.labels:\n            label = torch.tensor(self.df.iloc[idx, 1:],dtype=torch.float64)#.astype(float).to_numpy()\n            return {'image': img, 'labels': label} \n#         img = GET WINDOWED, NORMALIZED and SCALED PIXEL ARRAY HERE\n        return {'image': img}","metadata":{"execution":{"iopub.status.busy":"2024-03-10T03:51:54.641083Z","iopub.execute_input":"2024-03-10T03:51:54.641401Z","iopub.status.idle":"2024-03-10T03:51:54.655018Z","shell.execute_reply.started":"2024-03-10T03:51:54.641374Z","shell.execute_reply":"2024-03-10T03:51:54.653995Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import albumentations as A\nfrom albumentations import Compose, CenterCrop, HorizontalFlip, Normalize, RandomRotate90\nfrom albumentations.pytorch import ToTensorV2\n\ntransform_train = Compose([CenterCrop(299,299),\n                           Normalize(mean=0.5, std=1.0),\n                           A.OneOf([\n                                RandomRotate90(p=0.3),\n                                HorizontalFlip(p=0.3)\n                           ]),\n                           ToTensorV2()\n])\n\ntransform_test= Compose([CenterCrop(299,299),\n                         Normalize(mean=0.5, std=1.0),\n                         ToTensorV2()\n])","metadata":{"execution":{"iopub.status.busy":"2024-03-10T03:51:54.656161Z","iopub.execute_input":"2024-03-10T03:51:54.656423Z","iopub.status.idle":"2024-03-10T03:51:55.157139Z","shell.execute_reply.started":"2024-03-10T03:51:54.656394Z","shell.execute_reply":"2024-03-10T03:51:55.156368Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\nX,Y= train_test_split(df, test_size=0.2, shuffle=True)\n\ntrain_dataset= DicomDataset(TRAIN_PATH, X, transform=transform_train, labels=True)\ntest_dataset= DicomDataset(TRAIN_PATH, Y, transform=transform_test, labels=True)","metadata":{"execution":{"iopub.status.busy":"2024-03-10T03:51:55.158202Z","iopub.execute_input":"2024-03-10T03:51:55.158912Z","iopub.status.idle":"2024-03-10T03:51:55.169985Z","shell.execute_reply.started":"2024-03-10T03:51:55.158883Z","shell.execute_reply":"2024-03-10T03:51:55.169225Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_loader_train = torch.utils.data.DataLoader(train_dataset, batch_size=32, shuffle=True, num_workers=4)\ndata_loader_test = torch.utils.data.DataLoader(test_dataset, batch_size=32, shuffle=False, num_workers=4)","metadata":{"execution":{"iopub.status.busy":"2024-03-10T03:51:55.171131Z","iopub.execute_input":"2024-03-10T03:51:55.171437Z","iopub.status.idle":"2024-03-10T03:51:55.176659Z","shell.execute_reply.started":"2024-03-10T03:51:55.171402Z","shell.execute_reply":"2024-03-10T03:51:55.17573Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class GoogLeNet(nn.Module):\n    def __init__(self, aux_logits=True, num_classes=1000):\n        super(GoogLeNet, self).__init__()\n        assert aux_logits == True or aux_logits == False\n        self.aux_logits = aux_logits\n\n        # Write in_channels, etc, all explicit in self.conv1, rest will write to\n        # make everything as compact as possible, kernel_size=3 instead of (3,3)\n        self.conv1 = conv_block(\n            in_channels=3,\n            out_channels=64,\n            kernel_size=7,\n            stride=2,\n            padding=3,\n        )\n\n        self.maxpool1 = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)\n        self.conv2 = conv_block(64, 192, kernel_size=3, stride=1, padding=1)\n        self.maxpool2 = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)\n\n        # In this order: in_channels, out_1x1, red_3x3, out_3x3, red_5x5, out_5x5, out_1x1pool\n        self.skip_3 = conv_block(192, 480 ,kernel_size=1)\n        self.inception3a = Inception_block(192, 64, 96, 128, 16, 32, 32)\n        self.inception3b = Inception_block(256, 128, 128, 192, 32, 96, 64)\n        self.maxpool3 = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)\n        \n        self.skip_4a = conv_block(480, 512 ,kernel_size=1)\n        self.inception4a = Inception_block(480, 192, 96, 208, 16, 48, 64)\n        self.inception4b = Inception_block(512, 160, 112, 224, 24, 64, 64)\n        self.inception4c = Inception_block(512, 128, 128, 256, 24, 64, 64)\n        self.skip_4b = conv_block(512, 832, kernel_size=1)\n        self.inception4d = Inception_block(512, 112, 144, 288, 32, 64, 64)\n        self.inception4e = Inception_block(528, 256, 160, 320, 32, 128, 128)\n        self.maxpool4 = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)\n\n        self.skip_5 = conv_block(832, 1024, kernel_size=1)\n        self.inception5a = Inception_block(832, 256, 160, 320, 32, 128, 128)\n        self.inception5b = Inception_block(832, 384, 192, 384, 48, 128, 128)\n\n        self.avgpool = nn.AvgPool2d(kernel_size=7, stride=1)\n        self.dropout = nn.Dropout(p=0.4)\n        self.fc1 = nn.Linear(16384, num_classes)\n\n        if self.aux_logits:\n            self.aux1 = InceptionAux(512, num_classes)\n            self.aux2 = InceptionAux(528, num_classes)\n        else:\n            self.aux1 = self.aux2 = None\n\n    def forward(self, x):\n        x = self.conv1(x)\n        x = self.maxpool1(x)\n        x = self.conv2(x)\n        x = self.maxpool2(x)\n        \n        s3= self.skip_3(x)\n        x = self.inception3a(x)\n        x = self.inception3b(x)\n        x += s3\n        x = self.maxpool3(x)\n        \n        s4a = self.skip_4a(x)\n        x = self.inception4a(x)\n\n        # Auxiliary Softmax classifier 1\n        if self.aux_logits and self.training:\n            aux1 = self.aux1(x)\n\n        x = self.inception4b(x)\n        x += s4a\n        x = self.inception4c(x)\n        s4b = self.skip_4b(x)\n        x = self.inception4d(x)\n        \n        \n        # Auxiliary Softmax classifier 2\n        if self.aux_logits and self.training:\n            aux2 = self.aux2(x)\n\n        x = self.inception4e(x)\n        x += s4b\n        x = self.maxpool4(x)\n        s5 = self.skip_5(x)\n        x = self.inception5a(x)\n        x = self.inception5b(x)\n        x += s5\n        x = self.avgpool(x)\n        x = x.reshape(x.shape[0], -1)\n        x = self.dropout(x)\n        x = self.fc1(x)\n\n        if self.aux_logits and self.training:\n            return aux1, aux2, x\n        else:\n            return x\n\n\nclass Inception_block(nn.Module):\n    def __init__(\n        self, in_channels, out_1x1, red_3x3, out_3x3, red_5x5, out_5x5, out_1x1pool\n    ):\n        super(Inception_block, self).__init__()\n        self.branch1 = conv_block(in_channels, out_1x1, kernel_size=1)\n\n        self.branch2 = nn.Sequential(\n            conv_block(in_channels, red_3x3, kernel_size=1),\n            conv_block(red_3x3, out_3x3, kernel_size=(3, 3), padding=1),\n        )\n\n        self.branch3 = nn.Sequential(\n            conv_block(in_channels, red_5x5, kernel_size=1),\n            conv_block(red_5x5, out_5x5, kernel_size=5, padding=2),\n        )\n\n        self.branch4 = nn.Sequential(\n            nn.MaxPool2d(kernel_size=3, stride=1, padding=1),\n            conv_block(in_channels, out_1x1pool, kernel_size=1),\n        )\n\n    def forward(self, x):\n        return torch.cat(\n            [self.branch1(x), self.branch2(x), self.branch3(x), self.branch4(x)], 1\n        )\n\n\nclass InceptionAux(nn.Module):\n    def __init__(self, in_channels, num_classes):\n        super(InceptionAux, self).__init__()\n        self.relu = nn.ReLU()\n        self.dropout = nn.Dropout(p=0.7)\n        self.pool = nn.AvgPool2d(kernel_size=5, stride=3)\n        self.conv = conv_block(in_channels, 128, kernel_size=1)\n        self.fc1 = nn.Linear(2048, 1024)\n        self.fc2 = nn.Linear(1024, num_classes)\n\n    def forward(self, x):\n        x = self.pool(x)\n        x = self.conv(x)\n        x = x.reshape(x.shape[0], -1)\n        x = self.relu(self.fc1(x))\n        x = self.dropout(x)\n        x = self.fc2(x)\n        return x\n\n\nclass conv_block(nn.Module):\n    def __init__(self, in_channels, out_channels, **kwargs):\n        super(conv_block, self).__init__()\n        self.relu = nn.ReLU()\n        self.conv = nn.Conv2d(in_channels, out_channels, **kwargs)\n        self.batchnorm = nn.BatchNorm2d(out_channels)\n\n    def forward(self, x):\n        return self.relu(self.batchnorm(self.conv(x)))","metadata":{"execution":{"iopub.status.busy":"2024-03-10T03:56:49.990931Z","iopub.execute_input":"2024-03-10T03:56:49.991303Z","iopub.status.idle":"2024-03-10T03:56:50.020764Z","shell.execute_reply.started":"2024-03-10T03:56:49.991275Z","shell.execute_reply":"2024-03-10T03:56:50.019853Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"classes = 6\n\nmodel = GoogLeNet(aux_logits=False, num_classes=classes)\nmodel.to(device)\n\ncriterion= nn.BCEWithLogitsLoss()\noptimizer= optim.Adam(model.parameters(),lr=2e-5)","metadata":{"execution":{"iopub.status.busy":"2024-03-10T03:56:50.606242Z","iopub.execute_input":"2024-03-10T03:56:50.607086Z","iopub.status.idle":"2024-03-10T03:56:50.731642Z","shell.execute_reply.started":"2024-03-10T03:56:50.607054Z","shell.execute_reply":"2024-03-10T03:56:50.730812Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tqdm import tqdm\nfrom sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score\n\nn_epochs = 50\nhistory = {'accuracy': [], 'precision': [], 'loss': [], 'f1': []}\n\nfor epoch in range(n_epochs):\n    print('Epoch {}/{}'.format(epoch, n_epochs - 1))\n    print('-' * 10)\n\n    model.train()\n    tr_loss = 0\n    y_true = []\n    y_pred = []\n\n    total_batches = len(data_loader_train)\n    tk0 = tqdm(data_loader_train, total=total_batches, desc=\"Iteration\", position=0, leave=True)\n\n    for step, batch in enumerate(tk0):\n        inputs = batch[\"image\"]\n        labels = batch[\"labels\"]\n\n        inputs = inputs.to(device, dtype=torch.float)\n        labels = labels.to(device, dtype=torch.float)\n\n        outputs = model(inputs)\n        \n        loss = criterion(outputs, labels)\n\n        loss.backward()\n\n        tr_loss += loss.item()\n\n        optimizer.step()\n        optimizer.zero_grad()\n\n        # Collect true and predicted labels for metrics calculation\n        y_true.extend(labels.cpu().numpy())\n        y_pred.extend(outputs.cpu().detach().numpy())\n\n        if epoch == 1 and step > 6000:\n            epoch_loss = tr_loss / 6000\n            print('Training Loss: {:.4f}'.format(epoch_loss))\n            break\n        \n    if epoch and (epoch % 10 == 0):\n        torch.save({\n                'epoch': epoch,\n                'model_state_dict': model.state_dict(),\n                'optimizer_state_dict': optimizer.state_dict(),\n            }, f'chkpt_{epoch}.tar')\n    # Calculate training loss for the epoch\n    epoch_loss = tr_loss / len(data_loader_train)\n    print('Training Loss: {:.4f}'.format(epoch_loss))\n    history['loss'].append(epoch_loss)\n\n    # Calculate and append accuracy, precision, and F1 score to history\n#     y_true = np.round(y_true).astype(int)\n    y_true= np.argmax(y_true, axis=1)\n#     y_pred = np.round(y_pred).astype(int)\n    y_pred= np.argmax(y_pred,axis=1)\n\n    accuracy = accuracy_score(y_true, y_pred)\n    precision = precision_score(y_true, y_pred, average='weighted')\n    f1 = f1_score(y_true, y_pred, average='weighted')\n\n    print('Accuracy: {:.4f}'.format(accuracy))\n    print('Precision: {:.4f}'.format(precision))\n    print('F1 Score: {:.4f}'.format(f1))\n\n    history['accuracy'].append(accuracy)\n    history['precision'].append(precision)\n    history['f1'].append(f1)","metadata":{"execution":{"iopub.status.busy":"2024-03-10T03:57:14.227692Z","iopub.execute_input":"2024-03-10T03:57:14.228578Z","iopub.status.idle":"2024-03-10T06:12:31.356527Z","shell.execute_reply.started":"2024-03-10T03:57:14.228537Z","shell.execute_reply":"2024-03-10T06:12:31.355376Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"torch.save({\n                'epoch': epoch,\n                'model_state_dict': model.state_dict(),\n                'optimizer_state_dict': optimizer.state_dict(),\n            }, 'chkpt_final.tar')","metadata":{"execution":{"iopub.status.busy":"2024-03-10T06:15:47.121355Z","iopub.execute_input":"2024-03-10T06:15:47.122011Z","iopub.status.idle":"2024-03-10T06:15:47.340028Z","shell.execute_reply.started":"2024-03-10T06:15:47.121974Z","shell.execute_reply":"2024-03-10T06:15:47.339186Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dd= pd.DataFrame(history)\ndd.to_csv('stats.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2024-03-10T06:15:47.911494Z","iopub.execute_input":"2024-03-10T06:15:47.912394Z","iopub.status.idle":"2024-03-10T06:15:47.922083Z","shell.execute_reply.started":"2024-03-10T06:15:47.912344Z","shell.execute_reply":"2024-03-10T06:15:47.921131Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}