{"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":"# Some useful libraries imported\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport torch\nimport torchvision\nimport torchvision.transforms as transforms\nimport torch.optim as optim\nimport time\nimport torch.nn.functional as F\nimport torch.nn as nn\nfrom torchvision import models\nimport pytorch_lightning as pl\n\n# Input data files are available in the read-only \"../input/\" directory\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\nprint(device)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from pathlib import Path\n\nDATADIR = Path('../input/ranzcr-clip-catheter-line-classification')\nTRAINDIR = DATADIR.joinpath('train')\nTESTDIR = '../input/ranzcr-clip-catheter-line-classification/test'\n\nTRAIN_PATH = '../input/ranzcr-clip-catheter-line-classification/train'\ntrain = pd.read_csv('../input/ranzcr-clip-catheter-line-classification/train.csv')\ntest = pd.read_csv('../input/ranzcr-clip-catheter-line-classification/sample_submission.csv')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### **DATA PREPROCESSING**","metadata":{}},{"cell_type":"markdown","source":"#### Creating New columns in the dataframe denoting the presence(1)/absence(0) of each medical device.","metadata":{}},{"cell_type":"code","source":"# ETT labels\nTrain_ETT_Ab = train[\"ETT - Abnormal\"]\nETT_Ab_array = Train_ETT_Ab.to_numpy()\nTest_ETT_Ab = test[\"ETT - Abnormal\"]\nETT_Ab_array_test = Test_ETT_Ab.to_numpy()\n\nTrain_ETT_Nm = train[\"ETT - Normal\"]\nETT_Nm_array = Train_ETT_Nm.to_numpy()\nTest_ETT_Nm = test[\"ETT - Normal\"]\nETT_Nm_array_test = Test_ETT_Nm.to_numpy()\n\nTrain_ETT_Bl = train[\"ETT - Borderline\"]\nETT_Bl_array = Train_ETT_Bl.to_numpy()\nTest_ETT_Bl = test[\"ETT - Borderline\"]\nETT_Bl_array_test = Test_ETT_Bl.to_numpy()\n\n# NGT labels\nTrain_NGT_Ab = train[\"NGT - Abnormal\"]\nNGT_Ab_array = Train_NGT_Ab.to_numpy()\nTest_NGT_Ab = test[\"NGT - Abnormal\"]\nNGT_Ab_array_test = Test_NGT_Ab.to_numpy()\n\nTrain_NGT_Nm = train[\"NGT - Normal\"]\nNGT_Nm_array = Train_NGT_Nm.to_numpy()\nTest_NGT_Nm = test[\"NGT - Normal\"]\nNGT_Nm_array_test = Test_NGT_Nm.to_numpy()\n\nTrain_NGT_Bl = train[\"NGT - Borderline\"]\nNGT_Bl_array = Train_NGT_Bl.to_numpy()\nTest_NGT_Bl = test[\"NGT - Borderline\"]\nNGT_Bl_array_test = Test_NGT_Bl.to_numpy()\n\nTrain_NGT_II = train[\"NGT - Incompletely Imaged\"]\nNGT_II_array = Train_NGT_II.to_numpy()\nTest_NGT_II = test[\"NGT - Incompletely Imaged\"]\nNGT_II_array_test = Test_NGT_II.to_numpy()\n\n# CVC\nTrain_CVC_Ab = train[\"CVC - Abnormal\"]\nCVC_Ab_array = Train_CVC_Ab.to_numpy()\nTest_CVC_Ab = test[\"CVC - Abnormal\"]\nCVC_Ab_array_test = Test_CVC_Ab.to_numpy()\n\nTrain_CVC_Nm = train[\"CVC - Normal\"]\nCVC_Nm_array = Train_CVC_Nm.to_numpy()\nTest_CVC_Nm = test[\"CVC - Normal\"]\nCVC_Nm_array_test = Test_CVC_Nm.to_numpy()\n\nTrain_CVC_Bl = train[\"CVC - Borderline\"]\nCVC_Bl_array = Train_CVC_Bl.to_numpy()\nTest_CVC_Bl = test[\"CVC - Borderline\"]\nCVC_Bl_array_test = Test_CVC_Bl.to_numpy()\n\n\n# Swan Ganz Catheter Present\nTrain_SGC = train[\"Swan Ganz Catheter Present\"]\nSGC_array = Train_SGC.to_numpy()\nTest_SGC = test[\"Swan Ganz Catheter Present\"]\nSGC_array_test = Test_SGC.to_numpy()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ETT_array = ETT_Ab_array + ETT_Nm_array + ETT_Bl_array\nETT_array = (ETT_array > 0).astype(int)\nETT_array_test = ETT_Ab_array_test + ETT_Nm_array_test + ETT_Bl_array_test\nETT_array_test = (ETT_array_test > 0).astype(int)\nprint(ETT_array)\n\nNGT_array = NGT_Ab_array + NGT_Nm_array + NGT_Bl_array + NGT_II_array\nNGT_array = (NGT_array > 0).astype(int)\nNGT_array_test = NGT_Ab_array_test + NGT_Nm_array_test + NGT_Bl_array_test + NGT_II_array_test\nNGT_array_test = (NGT_array_test > 0).astype(int)\nprint(NGT_array)\n\nCVC_array = CVC_Ab_array + CVC_Nm_array + CVC_Bl_array\nCVC_array = (CVC_array > 0).astype(int)\nCVC_array_test = CVC_Ab_array_test + CVC_Nm_array_test + CVC_Bl_array_test\nCVC_array_test = (CVC_array_test > 0).astype(int)\nprint(CVC_array)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train['ETT'] =  pd.Series(ETT_array)\ntrain['NGT'] =  pd.Series(NGT_array)\ntrain['CVC'] =  pd.Series(CVC_array)\ntrain['SGC'] =  pd.Series(SGC_array)\n\ntest['ETT'] =  pd.Series(ETT_array_test)\ntest['NGT'] =  pd.Series(NGT_array_test)\ntest['CVC'] =  pd.Series(CVC_array_test)\ntest['SGC'] =  pd.Series(SGC_array_test)\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"IMAGE_SIZE = 512\nTARGET_COLS = ['ETT', 'NGT', 'CVC', 'SGC']\nCOLS = ['StudyInstanceUID','ETT', 'NGT', 'CVC', 'SGC']","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train['StudyInstanceUID'] = train['StudyInstanceUID'] + '.jpg'\nprint(train['StudyInstanceUID'][1])\n\ntest['StudyInstanceUID'] = test['StudyInstanceUID'] + '.jpg'\nprint(test['StudyInstanceUID'][1])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.head()\ntest.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### **UTILS**","metadata":{}},{"cell_type":"code","source":"from albumentations import (\n    Compose, OneOf, Normalize, Resize, RandomResizedCrop, RandomCrop, HorizontalFlip, VerticalFlip, \n    RandomBrightness, RandomContrast, RandomBrightnessContrast, Rotate, ShiftScaleRotate, Cutout, \n    IAAAdditiveGaussianNoise, Transpose, HueSaturationValue, CoarseDropout\n    )\nfrom albumentations.pytorch import ToTensorV2\nfrom albumentations import ImageOnlyTransform","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### **DATASET**","metadata":{}},{"cell_type":"code","source":"# Data Preparation: Dataset and DataModule Creation\nfrom torch.utils.data import Dataset, DataLoader\nfrom PIL import Image\nimport cv2\n\nclass Ranzcr_clip_dataset(Dataset):\n    \"\"\" Ranzcr Clip Dataset \"\"\"\n    \n    def __init__(self, root_dir, transform=None, stage=None):\n        if (stage):\n            # We're in test stage then\n            csv_output = test # pd.read_csv(os.path.join(root_dir, \"sample_submission.csv\"))\n            self.images_dir = os.path.join(root_dir, \"test\")\n        else:\n            csv_output = train #pd.read_csv(os.path.join(root_dir, \"train.csv\"))\n            csv_output.head()\n            self.images_dir = os.path.join(root_dir, \"train\")\n        self.image_urls = np.asarray(csv_output[\"StudyInstanceUID\"])\n        self.file_names = csv_output['StudyInstanceUID'].values\n        \n        # First case: Presence/Absence of ETT\n        self.labels = csv_output['ETT'].values\n        self.transform = transform\n        \n    def __len__(self):\n        return len(self.image_urls)\n    \n    def __getitem__(self, idx):\n        # Get and load image\n        file_name = self.file_names[idx]\n        file_path = f'{TRAINDIR}/{file_name}'\n        #image = cv2.imread(file_path)\n        #image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n        image = Image.open(file_path)\n        #image = Image.new(\"RGBA\", img.size)\n        #image.past(img)\n        # Perform transforms if any\n        if self.transform:\n            image = self.transform(image)\n        \n        # Get label\n        label = self.labels[idx]\n        return image, label","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## **DATA MODULE**","metadata":{}},{"cell_type":"code","source":"from torch.utils.data import random_split\nimport math\n\nclass LitRANZ_CLIP(pl.LightningModule):\n    \"\"\" Ranzcr Clip DataModule for Lightning \"\"\"\n    \n    def __init__(self, root_dir, transform=None, batch_size=32):\n        super().__init__()\n        self.batch_size = batch_size\n        self.root_dir = root_dir\n        self.transform = transform\n        \n    def setup(self, stage=None):\n        ranzcr_full = Ranzcr_clip_dataset(self.root_dir, self.transform)\n        train_data_len = math.floor(len(ranzcr_full) * 0.7)\n        val_data_len = len(ranzcr_full) - train_data_len\n        \n        # Create train and validation datasets\n        self.ranzcr_train, self.ranzcr_val = random_split(ranzcr_full, [train_data_len, val_data_len], generator=torch.Generator().manual_seed(42))\n        \n        # Create test dataset\n        self.ranzcr_test = Ranzcr_clip_dataset(self.root_dir, self.transform, stage=\"test\")\n\n    def train_dataloader(self):\n        return DataLoader(self.ranzcr_train, batch_size=self.batch_size)\n    \n    def val_dataloader(self):\n        return DataLoader(self.ranzcr_val, batch_size=self.batch_size)\n    \n    def test_dataloader(self):\n        return DataLoader(self.ranzcr_test, batch_size=self.batch_size)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"transform = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize((0.5,), (0.5,)) # Standard Normalization\n    ])\n\nroot_dir = \"/kaggle/input/ranzcr-clip-catheter-line-classification/\"\nranzcr_data = LitRANZ_CLIP(root_dir, transform, batch_size=64)\nranzcr_data.setup()\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### **MODEL FOR RANZCR CLIP**","metadata":{}},{"cell_type":"code","source":"import torchvision.models as models\n\nclass Ranzcr_clip_Model(pl.LightningModule):\n    def __init__(self, learning_rate=1e-4):\n        super().__init__()\n        \n        # Set our learning rate\n        self.learning_rate = learning_rate\n        \n        num_target_classes = 1\n        self.feature_extractor = models.resnet50(pretrained=False)\n        self.feature_extractor.conv1 = nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3,bias=False)\n        self.feature_extractor.eval()\n        \n        # Use the non-pretrained model to classify ranzcr\n        self.classifier = nn.Linear(1000, num_target_classes)\n        \n        # Create loss function\n        self.loss_fn = torch.nn.BCELoss()\n    \n    def configure_optimizers(self):\n        optimizer = torch.optim.Adam(self.parameters(), lr=self.learning_rate)\n        return optimizer\n    \n    def forward(self, input_data):\n        representations = self.feature_extractor(input_data)\n        preds = self.classifier(representations)\n        preds = F.sigmoid(preds)\n        return preds\n    \n    def training_step(self, train_batch, batch_idx):\n        x, y = train_batch\n        predictions = self.forward(x)\n        y = y.unsqueeze(1)\n        y = y.float()\n        predictions = predictions.float()\n        #y = y.type(torch.FloatTensor)\n        loss = self.loss_fn(predictions, y)\n        return loss\n    \n    def validation_step(self, val_batch, batch_idx):\n        x, y = val_batch\n        predictions = self.forward(x)\n        y = y.unsqueeze(1)\n        y = y.float()\n        predictions = predictions.float()\n        loss = self.loss_fn(predictions, y)\n        self.log('val_loss', loss)\n        #return loss\n        \n    def test_step(self, batch, batch_idx):\n        x, y = batch\n        y = y.unsqueeze(1)\n        y = y.float()\n        #x = x.view(x.size(0), -1)\n        y_hat = self.forward(x)\n        loss = self.loss_fn(y_hat, y)\n        y_hat = torch.argmax(y_hat, dim=1)\n        accuracy = torch.sum(y == y_hat).item() / (len(y) * 1.0)\n        output = dict({\n            'test_loss': loss,\n            'test_acc': torch.tensor(accuracy),\n                       })\n        return output","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### **Initializing our Model & Trainer**","metadata":{}},{"cell_type":"code","source":"model = Ranzcr_clip_Model()\n\ntrainer = pl.Trainer(gpus=1, auto_lr_find=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### **Tune the Learning Rate**","metadata":{}},{"cell_type":"code","source":"trainer.tune(model, ranzcr_data.train_dataloader())","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### **Fitting our Model to Our Data**","metadata":{}},{"cell_type":"code","source":"trainer.fit(model, ranzcr_data.train_dataloader())","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### **Evaluating our Performance**","metadata":{}},{"cell_type":"code","source":"def evaluate_results(loader):\n    model.to(device)\n    model.eval()\n    correct = 0\n    total = 0\n    true_positives = 0\n    false_positives = 0\n    false_negatives = 0\n    true_negatives = 0\n    \n    with torch.no_grad():\n        for x, y in iter(loader):        \n            x = x.to(device)\n            y = y.to(device)\n            preds = model(x)\n            _, predicted = torch.max(preds, 1)\n\n            correct += (predicted == y).sum().item()\n            total += len(y)\n        \n            confusion_vector = preds / y\n            true_positives += torch.sum(confusion_vector == 1).item()\n            false_positives += torch.sum(confusion_vector == float('inf')).item()\n            true_negatives += torch.sum(torch.isnan(confusion_vector)).item()\n            false_negatives += torch.sum(confusion_vector == 0).item()\n            \n    return true_positives, false_positives, true_negatives, false_negatives","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check the Validation Result\nval_dataloader = ranzcr_data.train_dataloader()\n#validation_loader = ranzcr_data.val_dataloader()\nevaluate_results(val_dataloader)\n# Perform evaluation\n#trainer.test(model, ranzcr_data.train_dataloader())","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}}]}