{"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":"markdown","source":"# Downloading Libraries","metadata":{}},{"cell_type":"code","source":"!pip install python-gdcm\n!pip install -U pylibjpeg[all]","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"__NOTE:__ Dataset used for training is from https://www.kaggle.com/datasets/anitho2910/rsna-mammography-breast-cancer-detection-png which was created from the given dicom image from my eda notebook https://www.kaggle.com/code/anitho2910/eda-notebook-breast-cancer ","metadata":{}},{"cell_type":"markdown","source":"# Importing Libraries","metadata":{}},{"cell_type":"code","source":"from fastai.vision.all import *\nfrom fastai.data.all import *\nfrom sklearn.model_selection import StratifiedShuffleSplit\nimport gc","metadata":{"execution":{"iopub.status.busy":"2022-12-17T08:07:19.970408Z","iopub.execute_input":"2022-12-17T08:07:19.971163Z","iopub.status.idle":"2022-12-17T08:07:21.808685Z","shell.execute_reply.started":"2022-12-17T08:07:19.971072Z","shell.execute_reply":"2022-12-17T08:07:21.807623Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Hyperparameters","metadata":{}},{"cell_type":"code","source":"seed = 42\nsave_path = '/kaggle/working'\ntrain_size = 0.8\nbatch_size = 32\nimage_resize = 256\nlr_unfreeze = slice(1e-7, 3e-6)\nn_epochs = 15","metadata":{"execution":{"iopub.status.busy":"2022-12-17T10:21:27.548513Z","iopub.execute_input":"2022-12-17T10:21:27.549168Z","iopub.status.idle":"2022-12-17T10:21:27.559512Z","shell.execute_reply.started":"2022-12-17T10:21:27.549116Z","shell.execute_reply":"2022-12-17T10:21:27.558464Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Helper Functions","metadata":{}},{"cell_type":"code","source":"#https://www.kaggle.com/competitions/rsna-breast-cancer-detection/discussion/369267  \ndef pfbeta_torch(preds, labels, beta=1):\n    softmax = torch.nn.Softmax(dim = -1)\n    preds = softmax(preds)\n    preds = preds[:, 1]\n    preds = preds.clip(0, 1)\n    y_true_count = labels.sum()\n    ctp = preds[labels==1].sum()\n    cfp = preds[labels==0].sum()\n    beta_squared = beta * beta\n    c_precision = ctp / (ctp + cfp)\n    c_recall = ctp / y_true_count\n    if (c_precision > 0 and c_recall > 0):\n        result = (1 + beta_squared) * (c_precision * c_recall) / (beta_squared * c_precision + c_recall)\n        return result\n    else:\n        return 0.0","metadata":{"execution":{"iopub.status.busy":"2022-12-17T08:07:21.827418Z","iopub.execute_input":"2022-12-17T08:07:21.830066Z","iopub.status.idle":"2022-12-17T08:07:21.840233Z","shell.execute_reply.started":"2022-12-17T08:07:21.830027Z","shell.execute_reply":"2022-12-17T08:07:21.839314Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data Loading","metadata":{}},{"cell_type":"code","source":"base_path = Path('/kaggle/input')\nbase_images_path = base_path/'rsna-mammography-breast-cancer-detection-png'/'png_images'\nbase_data_path = base_path/'rsna-breast-cancer-detection'\ndf = pd.read_csv(base_data_path/'train.csv')\nprint(df.shape)\nprint(f\"Total Number of patient {len(df['patient_id'].unique())}\")\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2022-12-17T08:07:21.846333Z","iopub.execute_input":"2022-12-17T08:07:21.84881Z","iopub.status.idle":"2022-12-17T08:07:21.963706Z","shell.execute_reply.started":"2022-12-17T08:07:21.848772Z","shell.execute_reply":"2022-12-17T08:07:21.96266Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"only_cc_view_data = df[df['view'] == 'CC'].copy()\nprint(only_cc_view_data.shape)\nprint(f'''Number of patient: {len(only_cc_view_data['patient_id'].unique())} \nand patient with more than 2 scans {(only_cc_view_data['patient_id'].value_counts() > 2).sum()}''')\nonly_cc_view_data.head()","metadata":{"execution":{"iopub.status.busy":"2022-12-17T08:07:21.967912Z","iopub.execute_input":"2022-12-17T08:07:21.970208Z","iopub.status.idle":"2022-12-17T08:07:22.010324Z","shell.execute_reply.started":"2022-12-17T08:07:21.970169Z","shell.execute_reply":"2022-12-17T08:07:22.009381Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"only_cc_view_data['path'] = only_cc_view_data.apply(lambda x: base_images_path/str(x['patient_id'])/(str(x['image_id'])+'.png'), axis = 1)\nfinal_subset = only_cc_view_data.drop_duplicates(subset = ['patient_id', 'laterality'], keep = 'last').copy()\nprint(final_subset.shape)\nprint(f'''Number of patient: {len(final_subset['patient_id'].unique())} \nand patient with more than 2 scans {(final_subset['patient_id'].value_counts() > 2).sum()}''')\nfinal_subset.head()","metadata":{"execution":{"iopub.status.busy":"2022-12-17T08:07:22.014515Z","iopub.execute_input":"2022-12-17T08:07:22.017003Z","iopub.status.idle":"2022-12-17T08:07:23.155347Z","shell.execute_reply.started":"2022-12-17T08:07:22.016963Z","shell.execute_reply":"2022-12-17T08:07:23.154299Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"final_subset['is_valid'] = False\nstrata = StratifiedShuffleSplit(n_splits=2, train_size = train_size, random_state=seed)\nfor (train_idx, valid_idx) in strata.split(final_subset.index, final_subset['cancer']):\n    final_subset.iloc[train_idx, -1] = False\n    final_subset.iloc[valid_idx, -1] = True\n\nprint(final_subset['is_valid'].value_counts(normalize = True))\nfinal_subset.head()","metadata":{"execution":{"iopub.status.busy":"2022-12-17T08:07:23.160066Z","iopub.execute_input":"2022-12-17T08:07:23.162675Z","iopub.status.idle":"2022-12-17T08:07:23.214124Z","shell.execute_reply.started":"2022-12-17T08:07:23.16263Z","shell.execute_reply":"2022-12-17T08:07:23.21316Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"number_class_0 = (final_subset['cancer'] == 0).sum()\nnumber_class_1 = (final_subset['cancer'] == 1).sum()\nweight_class_0 = 1\nweight_class_1 = number_class_0//number_class_1\nprint(f\"Cross Entropy weight for class 1: {weight_class_0}, and for class 0: {weight_class_1}\")\nweights = torch.tensor([weight_class_0, weight_class_1], dtype = torch.float32)\nprint(weights)","metadata":{"execution":{"iopub.status.busy":"2022-12-17T08:07:23.21865Z","iopub.execute_input":"2022-12-17T08:07:23.220912Z","iopub.status.idle":"2022-12-17T08:07:23.23374Z","shell.execute_reply.started":"2022-12-17T08:07:23.220873Z","shell.execute_reply":"2022-12-17T08:07:23.232328Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"datablock = DataBlock(blocks = (ImageBlock(), CategoryBlock),\n                     splitter = ColSplitter(),\n                     get_x = ColReader(-2),\n                     get_y = ColReader(6),\n                     item_tfms = Resize(image_resize, ResizeMethod.Pad, pad_mode = 'zeros'),)","metadata":{"execution":{"iopub.status.busy":"2022-12-17T08:07:23.238559Z","iopub.execute_input":"2022-12-17T08:07:23.240803Z","iopub.status.idle":"2022-12-17T08:07:23.250324Z","shell.execute_reply.started":"2022-12-17T08:07:23.240766Z","shell.execute_reply":"2022-12-17T08:07:23.249303Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dataloaders = datablock.dataloaders(final_subset, bs = 2*batch_size)\ndataloaders.show_batch()","metadata":{"execution":{"iopub.status.busy":"2022-12-17T08:07:23.255391Z","iopub.execute_input":"2022-12-17T08:07:23.257849Z","iopub.status.idle":"2022-12-17T08:07:33.589403Z","shell.execute_reply.started":"2022-12-17T08:07:23.257811Z","shell.execute_reply":"2022-12-17T08:07:33.588359Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training Procedure","metadata":{}},{"cell_type":"code","source":"learn = vision_learner(dataloaders, resnet50, loss_func = CrossEntropyLossFlat(weight = weights),\n                       metrics = [accuracy, pfbeta_torch]).to_fp16()\nlearn.fine_tune(3, cbs=[SaveModelCallback(monitor = 'pfbeta_torch', fname = 'resnet50')])\nlearn.recorder.plot_loss()","metadata":{"execution":{"iopub.status.busy":"2022-12-17T09:12:20.795167Z","iopub.execute_input":"2022-12-17T09:12:20.795707Z","iopub.status.idle":"2022-12-17T10:08:52.384761Z","shell.execute_reply.started":"2022-12-17T09:12:20.795663Z","shell.execute_reply":"2022-12-17T10:08:52.383528Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"interp = ClassificationInterpretation.from_learner(learn)\nlosses,idxs = interp.top_losses()\nlen(dataloaders.valid_ds)==len(losses)==len(idxs)\ninterp.plot_confusion_matrix(figsize=(7,7))","metadata":{"execution":{"iopub.status.busy":"2022-12-17T10:08:52.390139Z","iopub.execute_input":"2022-12-17T10:08:52.392722Z","iopub.status.idle":"2022-12-17T10:14:27.908361Z","shell.execute_reply.started":"2022-12-17T10:08:52.392673Z","shell.execute_reply":"2022-12-17T10:14:27.906906Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"interp.plot_top_losses(9, figsize=(15,10))","metadata":{"execution":{"iopub.status.busy":"2022-12-17T10:14:27.914693Z","iopub.execute_input":"2022-12-17T10:14:27.920599Z","iopub.status.idle":"2022-12-17T10:14:29.86001Z","shell.execute_reply.started":"2022-12-17T10:14:27.920535Z","shell.execute_reply":"2022-12-17T10:14:29.858969Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"del learn\ntorch.cuda.empty_cache()\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2022-12-17T10:16:15.829995Z","iopub.execute_input":"2022-12-17T10:16:15.830539Z","iopub.status.idle":"2022-12-17T10:16:16.142969Z","shell.execute_reply.started":"2022-12-17T10:16:15.830492Z","shell.execute_reply":"2022-12-17T10:16:16.141929Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"learn = vision_learner(dataloaders, resnet50, loss_func = CrossEntropyLossFlat(weight = weights),\n                       metrics = [accuracy, pfbeta_torch]).to_fp16()\nlearn.load('/kaggle/working/models/resnet50')","metadata":{"execution":{"iopub.status.busy":"2022-12-17T10:16:17.560049Z","iopub.execute_input":"2022-12-17T10:16:17.560548Z","iopub.status.idle":"2022-12-17T10:16:18.669288Z","shell.execute_reply.started":"2022-12-17T10:16:17.560503Z","shell.execute_reply":"2022-12-17T10:16:18.668209Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"learn.unfreeze()\nlearn.lr_find()","metadata":{"execution":{"iopub.status.busy":"2022-12-17T10:16:27.354527Z","iopub.execute_input":"2022-12-17T10:16:27.354981Z","iopub.status.idle":"2022-12-17T10:19:46.399475Z","shell.execute_reply.started":"2022-12-17T10:16:27.354941Z","shell.execute_reply":"2022-12-17T10:19:46.39831Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"learn.fit_one_cycle(n_epochs, lr_unfreeze, wd = 0.1,\n                    cbs=[SaveModelCallback(monitor = 'pfbeta_torch', fname = 'resnet50_unfreeze'), \n                        EarlyStoppingCallback(monitor='pfbeta_torch', patience = 4)]) \nlearn.recorder.plot_loss()","metadata":{"execution":{"iopub.status.busy":"2022-12-17T10:21:36.57956Z","iopub.execute_input":"2022-12-17T10:21:36.580017Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"interp = ClassificationInterpretation.from_learner(learn)\nlosses,idxs = interp.top_losses()\nlen(dataloaders.valid_ds)==len(losses)==len(idxs)\ninterp.plot_confusion_matrix(figsize=(7,7))","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"interp.plot_top_losses(9, figsize=(15,10))","metadata":{},"execution_count":null,"outputs":[]}]}