{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"from pathlib import Path\nimport pydicom\nimport cv2\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nfrom tqdm.notebook import tqdm\n\n# pytorch libraries for deep learning modelling\nimport 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","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-10-01T14:50:56.619519Z","iopub.execute_input":"2023-10-01T14:50:56.619804Z","iopub.status.idle":"2023-10-01T14:51:04.704166Z","shell.execute_reply.started":"2023-10-01T14:50:56.619775Z","shell.execute_reply":"2023-10-01T14:51:04.703045Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# reading labels data\nlabels = pd.read_csv(\"/kaggle/input/rsna-pneumonia-detection-challenge/stage_2_train_labels.csv\")\nlabels.head()","metadata":{"execution":{"iopub.status.busy":"2023-10-01T14:51:04.706465Z","iopub.execute_input":"2023-10-01T14:51:04.707103Z","iopub.status.idle":"2023-10-01T14:51:04.781055Z","shell.execute_reply.started":"2023-10-01T14:51:04.70706Z","shell.execute_reply":"2023-10-01T14:51:04.779897Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# defining the root path to importing images and files and save path to save the models and images\nROOT_PATH = Path(\"/kaggle/input/rsna-pneumonia-detection-challenge/stage_2_train_images/\")\nSAVE_PATH = Path(\"/kaggle/working/\")","metadata":{"execution":{"iopub.status.busy":"2023-10-01T14:51:04.782719Z","iopub.execute_input":"2023-10-01T14:51:04.783094Z","iopub.status.idle":"2023-10-01T14:51:04.788234Z","shell.execute_reply.started":"2023-10-01T14:51:04.783056Z","shell.execute_reply":"2023-10-01T14:51:04.787007Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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.read_file(dcm_path).pixel_array\n        \n        label = labels['Target'].iloc[c]\n        \n        axis[i][j].imshow(dcm, cmap=\"bone\")\n        axis[i][j].set_title(label)\n        c += 1","metadata":{"execution":{"iopub.status.busy":"2023-10-01T14:51:04.791224Z","iopub.execute_input":"2023-10-01T14:51:04.792453Z","iopub.status.idle":"2023-10-01T14:51:06.775511Z","shell.execute_reply.started":"2023-10-01T14:51:04.792413Z","shell.execute_reply":"2023-10-01T14:51:06.774483Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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.read_file(dcm_path).pixel_array / 255\n        \n        dcm_array = cv2.resize(dcm, (224, 224)).astype(np.float16)\n        \n        label = labels.Target.iloc[c]\n        \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\n\nmean = sums / 24000\nstd = np.sqrt((sums_squared / 24000) - mean ** 2)\nmean, std","metadata":{"execution":{"iopub.status.busy":"2023-10-01T14:51:06.776659Z","iopub.execute_input":"2023-10-01T14:51:06.776997Z","iopub.status.idle":"2023-10-01T15:00:51.845066Z","shell.execute_reply.started":"2023-10-01T14:51:06.776963Z","shell.execute_reply":"2023-10-01T15:00:51.843922Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# to load .npy file \ndef load_file(path):\n    return np.load(path).astype(np.float32)","metadata":{"execution":{"iopub.status.busy":"2023-10-01T15:00:51.846586Z","iopub.execute_input":"2023-10-01T15:00:51.847212Z","iopub.status.idle":"2023-10-01T15:00:51.852544Z","shell.execute_reply.started":"2023-10-01T15:00:51.847175Z","shell.execute_reply":"2023-10-01T15:00:51.85153Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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.5), 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":{"execution":{"iopub.status.busy":"2023-10-01T15:00:51.854233Z","iopub.execute_input":"2023-10-01T15:00:51.854708Z","iopub.status.idle":"2023-10-01T15:00:51.866152Z","shell.execute_reply.started":"2023-10-01T15:00:51.854669Z","shell.execute_reply":"2023-10-01T15:00:51.865212Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset = torchvision.datasets.DatasetFolder(\"/kaggle/working/train/\", loader=load_file, extensions=\"npy\", transform=train_transforms)\nval_dataset = torchvision.datasets.DatasetFolder(\"/kaggle/working/val/\", loader=load_file, extensions=\"npy\", transform=val_transforms)","metadata":{"execution":{"iopub.status.busy":"2023-10-01T15:00:51.867545Z","iopub.execute_input":"2023-10-01T15:00:51.868818Z","iopub.status.idle":"2023-10-01T15:00:51.963396Z","shell.execute_reply.started":"2023-10-01T15:00:51.868779Z","shell.execute_reply":"2023-10-01T15:00:51.962495Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Let's visualize 4 images from train dataset that are transformed \n\nfig, 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, len(train_dataset))\n        x_ray, label = train_dataset[random_index]\n        axis[i][j].imshow(x_ray[0], cmap='bone')\n        axis[i][j].set_title(label)","metadata":{"execution":{"iopub.status.busy":"2023-10-01T15:00:51.9645Z","iopub.execute_input":"2023-10-01T15:00:51.965274Z","iopub.status.idle":"2023-10-01T15:00:52.76637Z","shell.execute_reply.started":"2023-10-01T15:00:51.965239Z","shell.execute_reply":"2023-10-01T15:00:52.765441Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch_size = 64\nnum_workers = 2\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, shuffle=False)\n","metadata":{"execution":{"iopub.status.busy":"2023-10-01T15:00:52.770308Z","iopub.execute_input":"2023-10-01T15:00:52.77096Z","iopub.status.idle":"2023-10-01T15:00:52.777377Z","shell.execute_reply.started":"2023-10-01T15:00:52.770908Z","shell.execute_reply":"2023-10-01T15:00:52.776283Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"np.unique(train_dataset.targets, return_counts=True)","metadata":{"execution":{"iopub.status.busy":"2023-10-01T15:00:52.778856Z","iopub.execute_input":"2023-10-01T15:00:52.779687Z","iopub.status.idle":"2023-10-01T15:00:52.795388Z","shell.execute_reply.started":"2023-10-01T15:00:52.77965Z","shell.execute_reply":"2023-10-01T15:00:52.794337Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class PneumoniaModel(pl.LightningModule):\n    def __init__(self):\n        super(PneumoniaModel, self).__init__()\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(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 training_epoch_end(self, outs):\n        self.log(\"Train ACC\", self.train_acc.compute())\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                 \n    def configure_optimizers(self):\n        return [self.optimizer]\n               \n","metadata":{"execution":{"iopub.status.busy":"2023-10-01T15:00:52.796722Z","iopub.execute_input":"2023-10-01T15:00:52.797739Z","iopub.status.idle":"2023-10-01T15:00:52.810363Z","shell.execute_reply.started":"2023-10-01T15:00:52.797704Z","shell.execute_reply":"2023-10-01T15:00:52.809319Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = PneumoniaModel()","metadata":{"execution":{"iopub.status.busy":"2023-10-01T15:00:52.811913Z","iopub.execute_input":"2023-10-01T15:00:52.812626Z","iopub.status.idle":"2023-10-01T15:00:53.017255Z","shell.execute_reply.started":"2023-10-01T15:00:52.812591Z","shell.execute_reply":"2023-10-01T15:00:53.016215Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"checkpoint_callback = ModelCheckpoint(\n    monitor = 'Val ACC',\n    save_top_k = 10,\n    mode = 'max'\n)","metadata":{"execution":{"iopub.status.busy":"2023-10-01T15:00:53.018656Z","iopub.execute_input":"2023-10-01T15:00:53.019276Z","iopub.status.idle":"2023-10-01T15:00:53.02606Z","shell.execute_reply.started":"2023-10-01T15:00:53.019237Z","shell.execute_reply":"2023-10-01T15:00:53.024995Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"devices = 1\ntrainer = pl.Trainer(accelerator='gpu', devices=devices, logger=TensorBoardLogger(save_dir='./log'),\n                    log_every_n_steps=1,\n                    callbacks=checkpoint_callback, max_epochs=10)","metadata":{"execution":{"iopub.status.busy":"2023-10-01T15:00:53.027837Z","iopub.execute_input":"2023-10-01T15:00:53.028649Z","iopub.status.idle":"2023-10-01T15:00:53.080919Z","shell.execute_reply.started":"2023-10-01T15:00:53.028612Z","shell.execute_reply":"2023-10-01T15:00:53.079838Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainer.fit(model, train_loader, val_loader)","metadata":{"execution":{"iopub.status.busy":"2023-10-01T15:00:53.083171Z","iopub.execute_input":"2023-10-01T15:00:53.084115Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\ndevice","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.eval()\nmodel.to(device)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"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)\n        \npreds = torch.tensor(preds)\nlabels = torch.tensor(labels).int()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"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(task='binary', num_classes=2)(preds, labels)\n\nprint(f\"Val Accuracy {acc}\")\nprint(f\"Val Precision {precision}\")\nprint(f\"Val Recall {recall}\")\nprint(f\"Confusion Matrix {cm}\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}