{"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":"!pip install timm -q\n!pip install python-gdcm -q\n!pip install pylibjpeg -q","metadata":{"execution":{"iopub.status.busy":"2022-11-29T11:13:34.79709Z","iopub.execute_input":"2022-11-29T11:13:34.797498Z","iopub.status.idle":"2022-11-29T11:14:08.864149Z","shell.execute_reply.started":"2022-11-29T11:13:34.797416Z","shell.execute_reply":"2022-11-29T11:14:08.863041Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport cv2\nimport glob\n\nimport cv2\nimport numpy as np\nimport pandas as pd\n\nfrom path import Path\nfrom tqdm import tqdm\nimport pydicom as dicom\n\nimport matplotlib.pyplot as plt\nfrom tqdm import tqdm, trange\nfrom sklearn.model_selection import train_test_split\n\nimport torch\nfrom torch import nn\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms, models","metadata":{"execution":{"iopub.status.busy":"2022-11-29T11:14:10.514851Z","iopub.execute_input":"2022-11-29T11:14:10.51521Z","iopub.status.idle":"2022-11-29T11:14:15.534842Z","shell.execute_reply.started":"2022-11-29T11:14:10.515175Z","shell.execute_reply":"2022-11-29T11:14:15.53387Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Reading Dicom Images","metadata":{}},{"cell_type":"code","source":"def load_dicom(path):\n    img=dicom.dcmread(path)\n    data=img.pixel_array       \n    return data\n\ndef listdirs(folder):\n    return [d for d in os.listdir(folder) if os.path.isdir(os.path.join(folder, d))]    \n\ntrain_dir = '/kaggle/input/rsna-breast-cancer-detection/train_images'\ntest_dir = '/kaggle/input/rsna-breast-cancer-detection/test_images'\npatients = sorted(os.listdir(train_dir))","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-11-29T11:14:40.520905Z","iopub.execute_input":"2022-11-29T11:14:40.521267Z","iopub.status.idle":"2022-11-29T11:14:40.87505Z","shell.execute_reply.started":"2022-11-29T11:14:40.521236Z","shell.execute_reply":"2022-11-29T11:14:40.87427Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ds = dicom.dcmread(\"/kaggle/input/rsna-breast-cancer-detection/train_images/10006/1874946579.dcm\")\nplt.imshow(ds.pixel_array, cmap='gray')\n# MetaData\nprint(ds)","metadata":{"execution":{"iopub.status.busy":"2022-11-29T11:14:40.992042Z","iopub.execute_input":"2022-11-29T11:14:40.993758Z","iopub.status.idle":"2022-11-29T11:14:44.145293Z","shell.execute_reply.started":"2022-11-29T11:14:40.993718Z","shell.execute_reply":"2022-11-29T11:14:44.144409Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_file = glob.glob(\"/kaggle/input/rsna-breast-cancer-detection/train_images/10011/*.dcm\")\nfor i in range(4):\n    ax = plt.subplot(2, 2, i + 1)\n    image_path = image_file[i]\n    image = load_dicom(image_path)\n    plt.axis('off')   \n    plt.imshow(image, cmap='gray')","metadata":{"execution":{"iopub.status.busy":"2022-11-29T11:15:39.09796Z","iopub.execute_input":"2022-11-29T11:15:39.098671Z","iopub.status.idle":"2022-11-29T11:15:41.839598Z","shell.execute_reply.started":"2022-11-29T11:15:39.098612Z","shell.execute_reply":"2022-11-29T11:15:41.838569Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Train CSV","metadata":{}},{"cell_type":"code","source":"df = pd.read_csv(\"/kaggle/input/rsna-breast-cancer-detection/train.csv\")\ndf.head().style.background_gradient(cmap=\"Accent\")","metadata":{"execution":{"iopub.status.busy":"2022-11-29T11:16:06.669318Z","iopub.execute_input":"2022-11-29T11:16:06.669876Z","iopub.status.idle":"2022-11-29T11:16:06.867574Z","shell.execute_reply.started":"2022-11-29T11:16:06.669832Z","shell.execute_reply":"2022-11-29T11:16:06.866349Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Missing Values\n","metadata":{}},{"cell_type":"code","source":"missing_columns = [col for col in df.columns if df[col].isnull().any()]\nmissingvalues_count = df.isna().sum()\nmissingValues_df = pd.DataFrame(missingvalues_count.rename('Null Values Count')).loc[missingvalues_count.ne(0)]\nmissingValues_df .style.background_gradient(cmap=\"Pastel1\")","metadata":{"execution":{"iopub.status.busy":"2022-11-29T11:16:27.072592Z","iopub.execute_input":"2022-11-29T11:16:27.073498Z","iopub.status.idle":"2022-11-29T11:16:27.106551Z","shell.execute_reply.started":"2022-11-29T11:16:27.073447Z","shell.execute_reply":"2022-11-29T11:16:27.105489Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df['cancer'].value_counts()","metadata":{"execution":{"iopub.status.busy":"2022-11-29T11:16:55.302002Z","iopub.execute_input":"2022-11-29T11:16:55.302369Z","iopub.status.idle":"2022-11-29T11:16:55.310511Z","shell.execute_reply.started":"2022-11-29T11:16:55.302337Z","shell.execute_reply":"2022-11-29T11:16:55.309548Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cancer = df[df['cancer'] == 1]\nnon_cancer = df[df['cancer'] == 0][:1200] #Taking only 1200 non-cancer images\nframes = [cancer, non_cancer] \ntrain_df = pd.concat(frames)\ntrain_df.head().style.background_gradient(cmap=\"Pastel1\")","metadata":{"execution":{"iopub.status.busy":"2022-11-29T11:17:14.884222Z","iopub.execute_input":"2022-11-29T11:17:14.885024Z","iopub.status.idle":"2022-11-29T11:17:14.937303Z","shell.execute_reply.started":"2022-11-29T11:17:14.884982Z","shell.execute_reply":"2022-11-29T11:17:14.936387Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train, val = train_test_split(train_df, test_size=0.15, stratify=train_df['cancer'])\ntrain = train.reset_index()\nval = val.reset_index()","metadata":{"execution":{"iopub.status.busy":"2022-11-29T11:17:18.437598Z","iopub.execute_input":"2022-11-29T11:17:18.438599Z","iopub.status.idle":"2022-11-29T11:17:18.450935Z","shell.execute_reply.started":"2022-11-29T11:17:18.438562Z","shell.execute_reply":"2022-11-29T11:17:18.449933Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class CancerDataset(Dataset):\n    def __init__(self, df, transform=None):\n        super(CancerDataset, self).__init__()\n        self.df = df.copy()\n        self.transform = transform\n        self.path_to_dcms = \"/kaggle/input/rsna-breast-cancer-detection/train_images\"\n        \n    def __getitem__(self, idx):\n        dcm_path = os.path.join(self.path_to_dcms, str(self.df.loc[idx, \"patient_id\"]), f\"{self.df.loc[idx, 'image_id']}.dcm\")\n        dcm = dicom.dcmread(dcm_path)\n        dcm = dcm.pixel_array.astype(np.float32)\n        dcm = cv2.resize(dcm, (224,224))\n        if self.transform:\n            dcm = self.transform(dcm)\n        label = self.df.loc[idx, \"cancer\"]\n        label = torch.tensor(label, dtype=torch.int32)\n        return dcm, label\n    \n    def __len__(self):\n        return len(self.df)","metadata":{"execution":{"iopub.status.busy":"2022-11-29T11:17:33.630586Z","iopub.execute_input":"2022-11-29T11:17:33.63127Z","iopub.status.idle":"2022-11-29T11:17:33.64592Z","shell.execute_reply.started":"2022-11-29T11:17:33.631224Z","shell.execute_reply":"2022-11-29T11:17:33.644871Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"transform = transforms.Compose([\n    transforms.ToTensor()\n])\n\ntrain_loader = DataLoader(\n    CancerDataset(train,transform=transform), \n    batch_size=16, \n    shuffle=False, \n    num_workers=1\n)\nval_loader = DataLoader(\n    CancerDataset(val,transform=transform), \n    batch_size=16, \n    shuffle=False, \n    num_workers=1\n)\ndataloaders_dict = {\"train\": train_loader, \"val\": val_loader}\ncriterion = nn.CrossEntropyLoss()","metadata":{"execution":{"iopub.status.busy":"2022-11-29T11:17:34.238559Z","iopub.execute_input":"2022-11-29T11:17:34.239506Z","iopub.status.idle":"2022-11-29T11:17:34.247763Z","shell.execute_reply.started":"2022-11-29T11:17:34.239467Z","shell.execute_reply":"2022-11-29T11:17:34.246777Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train_model(model, dataloaders_dict, criterion, optimizer, num_epochs):\n    best_acc = 0.0\n\n    for epoch in range(num_epochs):\n        model.cuda()\n        \n        for phase in ['train', 'val']:\n            if phase == 'train':\n                model.train()\n            else:\n                model.eval()\n                \n            epoch_loss = 0.0\n            epoch_acc = 0\n            \n            dataloader = dataloaders_dict[phase]\n            for item in tqdm(dataloader, leave=False):\n                images = item[0].cuda().float()\n                classes = item[1].cuda().long()\n\n                optimizer.zero_grad()\n                \n                with torch.set_grad_enabled(phase == 'train'):\n                    output = model(images)\n                    loss = criterion(output, classes)\n                    _, preds = torch.max(output, 1)\n\n                    if phase == 'train':\n                        loss.backward()\n                        optimizer.step()\n\n                    epoch_loss += loss.item() * len(output)\n                    epoch_acc += torch.sum(preds == classes.data)\n                    \n\n            data_size = len(dataloader.dataset)\n            epoch_loss = epoch_loss / data_size\n            epoch_acc = epoch_acc.double() / data_size\n\n            print(f'Epoch {epoch + 1}/{num_epochs} | {phase:^5} | Loss: {epoch_loss:.4f} | Acc: {epoch_acc:.4f}')\n        \n        if epoch_acc > best_acc:\n            traced = torch.jit.trace(model.cpu(), torch.rand(1, 1, 224, 224))\n            traced.save('model.pth')\n            best_acc = epoch_acc","metadata":{"execution":{"iopub.status.busy":"2022-11-29T11:17:43.406687Z","iopub.execute_input":"2022-11-29T11:17:43.407053Z","iopub.status.idle":"2022-11-29T11:17:43.417681Z","shell.execute_reply.started":"2022-11-29T11:17:43.40702Z","shell.execute_reply":"2022-11-29T11:17:43.416585Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import timm\nmodel = timm.create_model('efficientnet_b4', pretrained=True, in_chans=1)","metadata":{"execution":{"iopub.status.busy":"2022-11-29T11:17:45.309268Z","iopub.execute_input":"2022-11-29T11:17:45.309612Z","iopub.status.idle":"2022-11-29T11:17:51.277046Z","shell.execute_reply.started":"2022-11-29T11:17:45.309581Z","shell.execute_reply":"2022-11-29T11:17:51.275837Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"optimizer = torch.optim.AdamW(model.parameters(), lr=1e-4)\ntrain_model(model, dataloaders_dict, criterion, optimizer, 3)","metadata":{"execution":{"iopub.status.busy":"2022-11-29T11:18:05.935098Z","iopub.execute_input":"2022-11-29T11:18:05.935462Z"},"trusted":true},"execution_count":null,"outputs":[]}]}