{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":10338,"databundleVersionId":862042,"sourceType":"competition"}],"dockerImageVersionId":30804,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Import Library","metadata":{}},{"cell_type":"code","source":"from pathlib import Path\nimport pydicom\nimport numpy as np\nimport cv2\nimport pandas as pd\nimport matplotlib.pyplot as plt\nfrom tqdm.notebook import tqdm","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T17:12:18.036016Z","iopub.execute_input":"2025-01-05T17:12:18.036321Z","iopub.status.idle":"2025-01-05T17:12:18.819275Z","shell.execute_reply.started":"2025-01-05T17:12:18.036294Z","shell.execute_reply":"2025-01-05T17:12:18.818614Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# File Directory","metadata":{}},{"cell_type":"code","source":"# /kaggle/input/rsna-pneumonia-detection-challenge/stage_2_test_images\n# /kaggle/input/rsna-pneumonia-detection-challenge/stage_2_train_images\n# /kaggle/input/rsna-pneumonia-detection-challenge/GCP Credits Request Link - RSNA.txt\n# /kaggle/input/rsna-pneumonia-detection-challenge/stage_2_sample_submission.csv\n# /kaggle/input/rsna-pneumonia-detection-challenge/stage_2_train_labels.csv","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T17:12:18.820759Z","iopub.execute_input":"2025-01-05T17:12:18.821101Z","iopub.status.idle":"2025-01-05T17:12:18.824786Z","shell.execute_reply.started":"2025-01-05T17:12:18.821075Z","shell.execute_reply":"2025-01-05T17:12:18.824001Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Preprocessing The Images","metadata":{}},{"cell_type":"code","source":"labels = pd.read_csv('/kaggle/input/rsna-pneumonia-detection-challenge/stage_2_train_labels.csv')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T17:12:18.825709Z","iopub.execute_input":"2025-01-05T17:12:18.825917Z","iopub.status.idle":"2025-01-05T17:12:18.897849Z","shell.execute_reply.started":"2025-01-05T17:12:18.825895Z","shell.execute_reply":"2025-01-05T17:12:18.896975Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"labels.head(6)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T17:12:18.899107Z","iopub.execute_input":"2025-01-05T17:12:18.899457Z","iopub.status.idle":"2025-01-05T17:12:18.918223Z","shell.execute_reply.started":"2025-01-05T17:12:18.899412Z","shell.execute_reply":"2025-01-05T17:12:18.917495Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"labels = labels.drop_duplicates('patientId')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T17:12:18.919256Z","iopub.execute_input":"2025-01-05T17:12:18.919689Z","iopub.status.idle":"2025-01-05T17:12:18.933646Z","shell.execute_reply.started":"2025-01-05T17:12:18.919641Z","shell.execute_reply":"2025-01-05T17:12:18.932952Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"labels.patientId.iloc[0]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T17:12:18.936235Z","iopub.execute_input":"2025-01-05T17:12:18.936492Z","iopub.status.idle":"2025-01-05T17:12:18.942138Z","shell.execute_reply.started":"2025-01-05T17:12:18.936467Z","shell.execute_reply":"2025-01-05T17:12:18.941298Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"ROOT_PATH = Path('/kaggle/input/rsna-pneumonia-detection-challenge/stage_2_train_images')\nSAVE_PATH = Path('/kaggle/working/Processed')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T17:12:18.943232Z","iopub.execute_input":"2025-01-05T17:12:18.943549Z","iopub.status.idle":"2025-01-05T17:12:18.950447Z","shell.execute_reply.started":"2025-01-05T17:12:18.943514Z","shell.execute_reply":"2025-01-05T17:12:18.949517Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Sample Image Visualization","metadata":{}},{"cell_type":"code","source":"fig, axis = plt.subplots(3,3,figsize=(9,9))\nc=0\nfor i in range(3):\n    for j in range(3):\n        patient_id = labels.patientId.iloc[c]\n        dcm_path = ROOT_PATH/patient_id\n        dcm_path = dcm_path.with_suffix('.dcm')\n        dcm = pydicom.dcmread(dcm_path).pixel_array\n        \n        label = labels['Target'].iloc[c]\n        axis[i][j].imshow(dcm,cmap='bone')\n        axis[i][j].set_title(label)\n        c += 1","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T17:12:18.951411Z","iopub.execute_input":"2025-01-05T17:12:18.951681Z","iopub.status.idle":"2025-01-05T17:12:21.232918Z","shell.execute_reply.started":"2025-01-05T17:12:18.951657Z","shell.execute_reply":"2025-01-05T17:12:21.232026Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Normalization","metadata":{}},{"cell_type":"code","source":"sums, sums_squared = 0, 0\n\nfor c, patient_id in enumerate(tqdm(labels.patientId)):\n    patient_id = labels.patientId.iloc[c]\n    dcm_path = ROOT_PATH/patient_id\n    dcm_path = dcm_path.with_suffix('.dcm')\n    dcm = pydicom.dcmread(dcm_path).pixel_array / 255\n\n    dcm_array = cv2.resize(dcm, (224,224)).astype(np.float16)\n    label = labels.Target.iloc[c]\n    train_or_val = 'train' if c < 24000 else 'val'\n\n    current_save_path = SAVE_PATH/train_or_val/str(label)\n    current_save_path.mkdir(parents=True,exist_ok=True)\n    np.save(current_save_path/patient_id, dcm_array)\n\n    normalizer = 224 * 224\n    if train_or_val == 'train':\n        sums += np.sum(dcm_array) / normalizer\n        sums_squared += (dcm_array ** 2).sum() / normalizer","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T17:12:21.233789Z","iopub.execute_input":"2025-01-05T17:12:21.234031Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"mean = sums / 24000\nstd = np.sqrt((sums_squared / 24000) - mean**2)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"mean, std","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Train","metadata":{}},{"cell_type":"code","source":"import torch\nimport torchvision\nfrom torchvision import transforms\nimport torchmetrics\nimport pytorch_lightning as pl\nfrom pytorch_lightning.callbacks import ModelCheckpoint\nfrom pytorch_lightning.loggers import TensorBoardLogger\nfrom tqdm.notebook import tqdm\nimport numpy as np\nimport matplotlib.pyplot as plt","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def load_file(path):\n    return np.load(path).astype(np.float32)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_transforms = transforms.Compose([\n    transforms.ToTensor(),\n    transforms.Normalize(0.49,0.248),\n    transforms.RandomAffine(degrees=(-5,5), translate=(0,0.05), scale=(0.9,1.1)),\n    transforms.RandomResizedCrop((224,224),scale=(0.35,1))\n])\n\nval_transforms = transforms.Compose([\n    transforms.ToTensor(),\n    transforms.Normalize(0.49,0.248),\n])","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_dataset = torchvision.datasets.DatasetFolder('/kaggle/working/Processed/train/',loader=load_file, extensions='npy',transform=train_transforms)\nval_dataset = torchvision.datasets.DatasetFolder('/kaggle/working/Processed/val/',loader=load_file, extensions='npy',transform=val_transforms)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_dataset","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"x_ray, label = train_dataset[0]","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"x_ray","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"type(x_ray)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.imshow(x_ray[0])","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"label","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"fig, axis = plt.subplots(2,2,figsize=(9,9))\n\nfor i in range(2):\n    for j in range(2):\n        random_index = np.random.randint(0,24000)\n        x_ray, labek = train_dataset[random_index]\n        axis[i][j].imshow(x_ray[0],cmap='bone')\n        axis[i][j].set_title(label)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"batch_size = 64\nnum_workers = 4\n\ntrain_loader = torch.utils.data.DataLoader(train_dataset,batch_size=batch_size,num_workers=num_workers,shuffle=True)\nval_loader = torch.utils.data.DataLoader(val_dataset,batch_size=batch_size,num_workers=num_workers,shuffle=False)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"np.unique(train_dataset.targets, return_counts=True)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"There we see Class: 0 contains 18,593 images and Class: 1 contains 5,407 images which is far small. So the dataset is imbalanced. We can handle the situation in three ways:\n\n* Do nothing\n* Awaited Loss Fucntion\n* Over Sampling","metadata":{}},{"cell_type":"markdown","source":"# Model","metadata":{}},{"cell_type":"code","source":"torchvision.models.resnet18()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# class PneumoniaModel(pl.LightningModule):\n\n#     def __init__(self):\n#         super().__init__()\n        \n#         self.model = torchvision.models.resnet18()\n#         self.model.conv1 = torch.nn.Conv2d(1, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)\n#         self.model.fc = torch.nn.Linear(in_features=512, out_features=1, bias=True)\n\n#         self.optimizer = torch.optim.Adam(self.model.parameters(), lr=1e-4)\n#         self.loss_fn = torch.nn.BCEWithLogitsLoss(pos_weight=torch.tensor([3]))\n\n#         self.train_acc = torchmetrics.Accuracy()\n#         self.val_acc = torchmetrics.Accuracy()\n\n#     def forward(self, data):\n#         pred = self.model(data)\n#         return pred\n\n#     def training_step(self, batch, batch_idx):\n#         x_ray, label = batch\n#         label = label.float()\n#         pred = self(x_ray)[:,0]\n#         loss = self.loss_fn(pred,label)\n\n#         self.log(\"Train Loss\", loss)\n#         self.log(\"Step Train ACC\", self.train_acc(torch.sigmoid(pred), label.int()))\n\n#         return loss\n\n#     def training_epoch_end(self,outs):\n#         self.log(\"Train ACC\", self.train_acc.compute())\n#         self.train_acc.reset()\n\n#     def validation_step(self, batch, batch_idx):\n#         x_ray, label = batch\n#         label = label.float()\n#         pred = self(x_ray)[:,0]\n#         loss = self.loss_fn(pred,label)\n\n#         self.log(\"Val Loss\", loss)\n#         self.log(\"Step Val ACC\", self.val_acc(torch.sigmoid(pred), label.int()))\n\n\n#     def validation_epoch_end(self,outs):\n#         self.log(\"Val ACC\", self.val_acc.compute())\n#         self.val_acc.reset()\n\n#     def configure_optimizers(self):\n#         return [self.optimizer]","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pytorch_lightning as pl\nimport torch\nimport torchvision\nimport torchmetrics\n\nclass PneumoniaModel(pl.LightningModule):\n    def __init__(self):\n        super().__init__()  # Call the parent class constructor\n        \n        # Define the model\n        self.model = torchvision.models.resnet18()\n        self.model.conv1 = torch.nn.Conv2d(1, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)\n        self.model.fc = torch.nn.Linear(in_features=512, out_features=1, bias=True)\n        \n        # Define optimizer and loss function\n        self.optimizer = torch.optim.Adam(self.model.parameters(), lr=1e-4)\n        self.loss_fn = torch.nn.BCEWithLogitsLoss(pos_weight=torch.tensor([3.0]))\n        \n        # Define metrics for binary classification\n        self.train_acc = torchmetrics.Accuracy(task=\"binary\")\n        self.val_acc = torchmetrics.Accuracy(task=\"binary\")\n\n    def forward(self, data):\n        pred = self.model(data)\n        return pred\n\n    def training_step(self, batch, batch_idx):\n        x_ray, label = batch\n        label = label.float()\n        pred = self(x_ray)[:, 0]\n        loss = self.loss_fn(pred, label)\n\n        self.log(\"Train Loss\", loss)\n        self.log(\"Step Train ACC\", self.train_acc(torch.sigmoid(pred), label.int()))\n\n        return loss\n\n    def on_train_epoch_end(self):\n        self.log(\"Train ACC\", self.train_acc.compute())\n        self.train_acc.reset()\n\n    def validation_step(self, batch, batch_idx):\n        x_ray, label = batch\n        label = label.float()\n        pred = self(x_ray)[:, 0]\n        loss = self.loss_fn(pred, label)\n\n        self.log(\"Val Loss\", loss)\n        self.log(\"Step Val ACC\", self.val_acc(torch.sigmoid(pred), label.int()))\n\n    def on_validation_epoch_end(self):\n        self.log(\"Val ACC\", self.val_acc.compute())\n        self.val_acc.reset()\n\n    def configure_optimizers(self):\n        return self.optimizer\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = PneumoniaModel()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"[0] * 5","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"checkpoint_callback = ModelCheckpoint(\n    monitor = 'Val ACC',\n    save_top_k=10,\n    mode='max'\n)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"gpus = 1\ntrainer = pl.Trainer( logger=TensorBoardLogger(save_dir='./logs'),\n                    log_every_n_steps=1,callbacks=checkpoint_callback,max_epochs=10)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"trainer.fit(model,train_loader,val_loader)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')\n\nmodel = PneumoniaModel.load_from_checkpoint('/kaggle/working/logs/lightning_logs/version_0/checkpoints/epoch=9-step=3750.ckpt')\nmodel.eval()\nmodel.to(device)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"preds = []\nlabels = []\n\nwith torch.no_grad():\n    for data, label in tqdm(val_dataset):\n        data = data.to(device).float().unsqueeze(0)\n        pred = torch.sigmoid(model(data)[0].cpu())\n        preds.append(pred)\n        labels.append(label)\npreds = torch.tensor(preds)\nlabels = torch.tensor(labels).int()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# /kaggle/working/Processed/val/0/0053ee32-1e03-4dc2-a103-f46ad0448787.npy","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"preds[:10]","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"labels[:10]","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"acc= torchmetrics.Accuracy(task=\"binary\")(preds,labels)\nprecision = torchmetrics.Precision(task=\"binary\")(preds,labels)\nrecall = torchmetrics.Recall(task=\"binary\")(preds,labels)\ncm = torchmetrics.ConfusionMatrix(num_classes=2,task=\"binary\")(preds,labels)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"acc","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"precision","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"recall","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"cm","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}