{"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":"# Import stuff\nimport random\nimport numpy as np\nimport torch\nimport torch.backends.cudnn as cudnn\nimport torch.optim\nimport pandas as pd\nfrom torch.utils.data import Dataset\nfrom glob import glob\nimport random\nimport torch.distributed as dist\nimport torch.nn as nn\nimport matplotlib.pyplot as plt\nfrom torch.utils.data import DataLoader\nfrom torchvision import transforms\nfrom PIL import Image\nfrom torchvision.transforms import ToTensor\nimport torchvision\nimport cv2\nfrom sklearn.metrics import roc_curve, auc\nimport os","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-05-18T19:21:06.468991Z","iopub.execute_input":"2022-05-18T19:21:06.469350Z","iopub.status.idle":"2022-05-18T19:21:09.510100Z","shell.execute_reply.started":"2022-05-18T19:21:06.469245Z","shell.execute_reply":"2022-05-18T19:21:09.509365Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Dataset():\n\n    def __init__(self, file_list, mode):\n        self.file_list = file_list\n        self.mode = mode\n\n    def __getitem__(self,idx):\n        image_filepath = self.file_list[idx]\n        image, code = self.loadimage(image_filepath)\n        \n        sample = {'Image': image,\n              'Code': code,\n              }\n\n        return sample\n\n    def __len__(self):\n        return len(self.file_list)\n\n    def loadimage(self, image_filepath):\n        img = cv2.imread(image_filepath, 0)\n        img = np.pad(img, [(262,262),(0,0)])\n        img = cv2.resize(img, dsize=(382, 382))\n        \n        image = ToTensor()(img) \n        image = 2*(image/torch.max(image))-1\n        code = image_filepath.split('/')[4][:-4] \n        return image, code","metadata":{"execution":{"iopub.status.busy":"2022-05-18T19:21:09.511659Z","iopub.execute_input":"2022-05-18T19:21:09.512098Z","iopub.status.idle":"2022-05-18T19:21:09.519657Z","shell.execute_reply.started":"2022-05-18T19:21:09.512067Z","shell.execute_reply":"2022-05-18T19:21:09.518973Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gt_df = pd.read_csv(\"../input/ranzcr-clip-catheter-line-classification/train.csv\")\ntrain_dir = '../input/ranzcr-clip-catheter-line-classification/train'\ntest_dir = '../input/ranzcr-clip-catheter-line-classification/test'\ntotal_files = []\ntotal_files.extend(sorted(glob(train_dir + '/*.jpg')))\nval_length = int(len(total_files) * 0.2)\ntrain_files = total_files[val_length:]\nval_files = total_files[:val_length]\ntest_files = []\ntest_files.extend(sorted(glob(test_dir + '/*.jpg')))\n\nTrain_Dataset = Dataset(train_files, \"Train\")\nTrain_dataloader = DataLoader(Train_Dataset, shuffle=True, num_workers=2, batch_size=200, pin_memory=True)\n\nVal_Dataset = Dataset(val_files, \"Val\")\nVal_dataloader = DataLoader(Val_Dataset, shuffle=False, num_workers=2, batch_size=200, pin_memory=True)\n\nTest_Dataset = Dataset(test_files, \"Test\")\nTest_dataloader = DataLoader(Train_Dataset, shuffle=True, num_workers=2, batch_size=1, pin_memory=True)","metadata":{"execution":{"iopub.status.busy":"2022-05-18T19:21:09.520845Z","iopub.execute_input":"2022-05-18T19:21:09.521353Z","iopub.status.idle":"2022-05-18T19:21:10.487522Z","shell.execute_reply.started":"2022-05-18T19:21:09.521297Z","shell.execute_reply":"2022-05-18T19:21:10.486737Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class resconv_block_2D(nn.Module):\n    def __init__(self, ch_in, ch_out):\n        super(resconv_block_2D, self).__init__()\n        self.conv = nn.Sequential(\n            nn.Conv2d(ch_in, ch_out, kernel_size = 3, stride = 1, padding = 1, bias = True),\n            nn.BatchNorm2d(ch_out),\n            nn.ReLU(inplace = True),\n            nn.Conv2d(ch_out, ch_out, kernel_size = 3, stride = 1, padding = 1, bias = True),\n            nn.BatchNorm2d(ch_out),\n            nn.ReLU(inplace = True)\n        )\n        self.Conv_1x1 = nn.Conv2d(ch_in, ch_out, kernel_size = 1, stride = 1, padding = 0)\n\n    def forward(self,x):\n\n        residual = self.Conv_1x1(x)\n        x = self.conv(x)\n        return residual + x\n\nclass ResNet(nn.Module):\n    def __init__(\n        self,\n        img_ch = 1,\n        output_ch = 11,\n        ):\n        super(ResNet,self).__init__()\n\n        self.Maxpool = nn.MaxPool2d(kernel_size=2,stride=2)\n        self.Softmax = nn.Softmax(dim=1)\n        self.Sigmoid = nn.Sigmoid()\n\n        self.Conv1 = resconv_block_2D(ch_in=img_ch,ch_out=8)\n        self.Conv2 = resconv_block_2D(ch_in=8,ch_out=16)\n        self.Conv3 = resconv_block_2D(ch_in=16,ch_out=32)\n        self.Conv4 = resconv_block_2D(ch_in=32,ch_out=64)\n        self.Conv5 = resconv_block_2D(ch_in=64,ch_out=128)\n\n        feature_dimension = 67712\n        self.classifier = nn.Sequential(\n            nn.Dropout(),\n            nn.Linear(feature_dimension, 1024),\n            nn.ReLU(True),\n\n            nn.Dropout(),\n            nn.Linear(1024, 128),\n            nn.Sigmoid(),\n\n            nn.Linear(128, output_ch),\n         )\n\n    def forward(self,x):\n        x1 = self.Conv1(x)\n        x2 = self.Maxpool(x1)\n        x2 = self.Conv2(x2)\n        x3 = self.Maxpool(x2)\n        x3 = self.Conv3(x3)\n        x4 = self.Maxpool(x3)\n        x4 = self.Conv4(x4)\n        x5 = self.Maxpool(x4)\n        x = self.Conv5(x5) \n        x = x.view(x.size(0), -1)\n        x = self.classifier(x)\n        x = self.Sigmoid(x)\n        return x","metadata":{"execution":{"iopub.status.busy":"2022-05-18T19:21:10.489671Z","iopub.execute_input":"2022-05-18T19:21:10.490071Z","iopub.status.idle":"2022-05-18T19:21:10.505472Z","shell.execute_reply.started":"2022-05-18T19:21:10.490036Z","shell.execute_reply":"2022-05-18T19:21:10.504816Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = ResNet()\nmodel = model.cuda()","metadata":{"execution":{"iopub.status.busy":"2022-05-18T19:21:10.506526Z","iopub.execute_input":"2022-05-18T19:21:10.506708Z","iopub.status.idle":"2022-05-18T19:21:13.994237Z","shell.execute_reply.started":"2022-05-18T19:21:10.506686Z","shell.execute_reply":"2022-05-18T19:21:13.993481Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"criterion=nn.BCELoss()\ncriterion = criterion.cuda()\n\noptimizer = torch.optim.Adam(model.parameters(), lr=0.0001)","metadata":{"execution":{"iopub.status.busy":"2022-05-18T19:21:13.995568Z","iopub.execute_input":"2022-05-18T19:21:13.995798Z","iopub.status.idle":"2022-05-18T19:21:14.000997Z","shell.execute_reply.started":"2022-05-18T19:21:13.995766Z","shell.execute_reply":"2022-05-18T19:21:14.000162Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def find_gt(code, df):\n    index = df.index[df['StudyInstanceUID'] == code].tolist()\n    g = df.iloc[index]\n    g = g.to_numpy()[0]\n    GT = (g[1:-1])\n    return GT\n\ntrain_global_losses = []\nval_global_losses = []\nval_global_auc = []\n\nfor epoch in range(0, 20):\n    \n        # Declare lists to keep track of losses and metrics within the epoch\n        train_epoch_losses = []\n        val_epoch_losses = []\n        \n        val_auc = []\n        val_gt = {i:[] for i in range(0,11)}\n        val_predictions = {i:[] for i in range(0,11)}\n\n        model.train()\n        \n        count = 0\n    \n        for i, data in enumerate(Train_dataloader):\n\n            input_img = data['Image']\n            codes = data['Code']\n            codes_formatted = np.zeros([len(codes),11])\n            \n            for k in range(0,len(codes)):\n                g = find_gt(codes[k], gt_df)\n                codes_formatted[k,:] += np.array(g, dtype='float')\n                        \n            input_img = input_img.cuda(non_blocking=True)\n            codes_formatted = torch.tensor(codes_formatted)\n            codes_formatted = codes_formatted.to(torch.float)\n            codes_formatted = codes_formatted.cuda(non_blocking=True)\n            \n            output = model(input_img)\n            \n            loss = []\n            for j in range(0,11):\n                cur_output = output[:,j].unsqueeze(1)\n                cur_gt = codes_formatted[:,j].unsqueeze(1)\n                loss.append(criterion(cur_output, cur_gt))\n            \n            total_loss = sum(loss)\n            train_epoch_losses.append(total_loss.item())\n\n            optimizer.zero_grad()\n            total_loss.backward()\n            optimizer.step()\n\n        # Transition to val mode\n        model.eval()\n\n        # Avoid computing gradients during validation to save memory\n        with torch.no_grad():\n            count = 0\n\n            for i, data in enumerate(Val_dataloader):\n                \n                input_img = data['Image']\n                codes = data['Code']\n                codes_formatted = np.zeros([len(codes),11])\n\n                for k in range(0,len(codes)):\n                    g = find_gt(codes[k], gt_df)\n                    codes_formatted[k,:] += np.array(g, dtype='float')\n\n                input_img = input_img.cuda(non_blocking=True)\n                codes_formatted = torch.tensor(codes_formatted)\n                codes_formatted = codes_formatted.to(torch.float)\n                codes_formatted = codes_formatted.cuda(non_blocking=True)\n\n                output = model(input_img)\n\n                loss = []\n                for j in range(0,11):\n                    cur_output = output[:,j].unsqueeze(1)\n                    cur_gt = codes_formatted[:,j].unsqueeze(1)\n                    loss.append(criterion(cur_output, cur_gt))\n                    val_gt[j].extend(list(codes_formatted[:,j].cpu().detach().numpy()))\n                    val_predictions[j].extend(list(output[:,j].cpu().detach().numpy()))\n\n                total_loss = sum(loss)\n                val_epoch_losses.append(total_loss.item())\n\n        train_net_loss = sum(train_epoch_losses) / len(train_epoch_losses)\n        val_net_loss = sum(val_epoch_losses) / len(val_epoch_losses)\n        train_global_losses.append(train_net_loss)\n        val_global_losses.append(val_net_loss)\n\n        for j in range(0,11):\n            gt = np.array(val_gt[j]).flatten()\n            pred = np.array(val_predictions[j]).flatten()\n            fpr, tpr, _ = roc_curve(gt, pred)\n            AUC = auc(fpr, tpr)\n            val_auc.append(AUC)\n                        \n        average_epoch_auc = sum(val_auc)/len(val_auc)\n\n        print('Epoch: {} | Train Loss: {} | Val Loss: {} | Avg Val AUC: {} |'.format(epoch, train_net_loss, val_net_loss, average_epoch_auc))\n\n        checkpoint_dir = './'\n        # Save the model if it reaches a new min validation loss\n        if val_global_losses[-1] == min(val_global_losses):\n            print('saving model at the end of epoch ' + str(epoch))\n            if epoch > 5:\n                best_epoch = epoch\n                file_name = os.path.join(checkpoint_dir, 'model_epoch_{}.pth'.format(epoch))\n                torch.save({\n                    'epoch': epoch,\n                    'state_dict': model.state_dict(),\n                    'optim_dict': optimizer.state_dict(),\n                    },\n                    file_name)","metadata":{"execution":{"iopub.status.busy":"2022-05-18T19:21:14.002393Z","iopub.execute_input":"2022-05-18T19:21:14.002811Z","iopub.status.idle":"2022-05-18T23:25:23.089598Z","shell.execute_reply.started":"2022-05-18T19:21:14.002776Z","shell.execute_reply":"2022-05-18T23:25:23.087962Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"best_epoch = np.argmin(np.array(val_global_losses))\n\nmodel = ResNet()\nmodel = model.cuda()\n\nload_dir = './model_epoch_' + str(best_epoch) + '.pth'\ncheckpoint = torch.load(load_dir)\nmodel.load_state_dict(checkpoint['state_dict'])\nmodel.cuda()\n\noutput_df = pd.DataFrame(columns=['StudyInstanceUID', 'ETT - Abnormal', 'ETT - Borderline',\n       'ETT - Normal', 'NGT - Abnormal', 'NGT - Borderline',\n       'NGT - Incompletely Imaged', 'NGT - Normal', 'CVC - Abnormal',\n       'CVC - Borderline', 'CVC - Normal', 'Swan Ganz Catheter Present'])\n\nwith torch.no_grad():\n    count = 0\n    \n    for i, data in enumerate(Test_dataloader):\n        final = []\n        input_img = data['Image']\n        codes = data['Code']\n        \n        final.append(codes[0])\n\n        input_img = input_img.cuda(non_blocking=True)\n        output = model(input_img)\n        output = output.squeeze(0)\n        final.extend(list(output.cpu().detach().numpy()))\n        \n        output_df.loc[i] = final","metadata":{"execution":{"iopub.status.busy":"2022-05-18T23:25:23.091491Z","iopub.execute_input":"2022-05-18T23:25:23.091776Z","iopub.status.idle":"2022-05-18T23:36:18.979732Z","shell.execute_reply.started":"2022-05-18T23:25:23.091732Z","shell.execute_reply":"2022-05-18T23:36:18.978786Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"output_df.to_csv('output.csv')","metadata":{"execution":{"iopub.status.busy":"2022-05-18T23:36:18.981307Z","iopub.execute_input":"2022-05-18T23:36:18.982702Z","iopub.status.idle":"2022-05-18T23:36:19.387956Z","shell.execute_reply.started":"2022-05-18T23:36:18.982657Z","shell.execute_reply":"2022-05-18T23:36:19.387157Z"},"trusted":true},"execution_count":null,"outputs":[]}]}