{"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 os\nimport random\nimport glob\nimport pandas as pd\nimport numpy as np\nimport pydicom \n\n\nimport torch\nimport torch.optim as optim\nfrom albumentations import Compose, ShiftScaleRotate, Resize, Normalize, HorizontalFlip, RandomBrightnessContrast\nfrom albumentations.pytorch import ToTensorV2\nfrom torch.utils.data import Dataset,Subset\n\nfrom sklearn.metrics import roc_auc_score, f1_score, accuracy_score, jaccard_score, confusion_matrix\nfrom tqdm import notebook as tqdm","metadata":{"execution":{"iopub.status.busy":"2022-05-08T05:35:00.740469Z","iopub.execute_input":"2022-05-08T05:35:00.740937Z","iopub.status.idle":"2022-05-08T05:35:04.504508Z","shell.execute_reply.started":"2022-05-08T05:35:00.740797Z","shell.execute_reply":"2022-05-08T05:35:04.503701Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"INPUT_PATH = '../input/rsna-intracranial-hemorrhage-detection/rsna-intracranial-hemorrhage-detection/'","metadata":{"execution":{"iopub.status.busy":"2022-05-08T05:35:07.604541Z","iopub.execute_input":"2022-05-08T05:35:07.604811Z","iopub.status.idle":"2022-05-08T05:35:07.610518Z","shell.execute_reply.started":"2022-05-08T05:35:07.604779Z","shell.execute_reply":"2022-05-08T05:35:07.609744Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.listdir(INPUT_PATH)","metadata":{"execution":{"iopub.status.busy":"2022-05-03T10:32:19.273053Z","iopub.execute_input":"2022-05-03T10:32:19.27335Z","iopub.status.idle":"2022-05-03T10:32:19.291284Z","shell.execute_reply.started":"2022-05-03T10:32:19.273312Z","shell.execute_reply":"2022-05-03T10:32:19.290561Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Parameters\nn_classes = 6\nn_epochs = 1\nbatch_size = 32","metadata":{"execution":{"iopub.status.busy":"2022-05-08T05:35:10.900808Z","iopub.execute_input":"2022-05-08T05:35:10.901434Z","iopub.status.idle":"2022-05-08T05:35:10.906582Z","shell.execute_reply.started":"2022-05-08T05:35:10.901392Z","shell.execute_reply":"2022-05-08T05:35:10.9059Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"COLS = ['epidural', 'intraparenchymal', 'intraventricular', 'subarachnoid', 'subdural', 'any']","metadata":{"execution":{"iopub.status.busy":"2022-05-08T05:35:14.171902Z","iopub.execute_input":"2022-05-08T05:35:14.17243Z","iopub.status.idle":"2022-05-08T05:35:14.176157Z","shell.execute_reply.started":"2022-05-08T05:35:14.172392Z","shell.execute_reply":"2022-05-08T05:35:14.175446Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_images_dir = os.path.join(INPUT_PATH, 'stage_2_train/')\ntest_images_dir = os.path.join(INPUT_PATH, 'stage_2_test/')","metadata":{"execution":{"iopub.status.busy":"2022-05-08T05:35:17.64713Z","iopub.execute_input":"2022-05-08T05:35:17.648083Z","iopub.status.idle":"2022-05-08T05:35:17.65308Z","shell.execute_reply.started":"2022-05-08T05:35:17.64803Z","shell.execute_reply":"2022-05-08T05:35:17.651759Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# train_metadata_csv = '../input/rsna-stage-2-metadata-ihd-2019/stage_2_train_with_metadata.csv'\n# test_metadata_csv = '../input/rsna-stage-2-metadata-ihd-2019/stage_2_test_with_metadata.csv'\ntrain_metadata_csv = '../input/rsna-intracranial-sequence-metadata/train_metadata_noidx.csv'\ntest_metadata_csv = '../input/rsna-intracranial-sequence-metadata/test_metadata_noidx.csv'","metadata":{"execution":{"iopub.status.busy":"2022-05-08T05:35:22.162199Z","iopub.execute_input":"2022-05-08T05:35:22.162463Z","iopub.status.idle":"2022-05-08T05:35:22.166757Z","shell.execute_reply.started":"2022-05-08T05:35:22.162434Z","shell.execute_reply":"2022-05-08T05:35:22.16575Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_metadata = pd.read_csv(train_metadata_csv)\ntrain_metadata.columns","metadata":{"execution":{"iopub.status.busy":"2022-05-06T13:44:12.949294Z","iopub.execute_input":"2022-05-06T13:44:12.94964Z","iopub.status.idle":"2022-05-06T13:44:15.506317Z","shell.execute_reply.started":"2022-05-06T13:44:12.949608Z","shell.execute_reply":"2022-05-06T13:44:15.505311Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = pd.read_csv(os.path.join(INPUT_PATH, 'stage_2_train.csv'))\ntest = pd.read_csv(os.path.join(INPUT_PATH, 'stage_2_sample_submission.csv'))","metadata":{"execution":{"iopub.status.busy":"2022-05-08T05:35:37.167357Z","iopub.execute_input":"2022-05-08T05:35:37.167613Z","iopub.status.idle":"2022-05-08T05:35:41.511807Z","shell.execute_reply.started":"2022-05-08T05:35:37.167583Z","shell.execute_reply":"2022-05-08T05:35:41.508282Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Preprocessing : Windowing","metadata":{}},{"cell_type":"code","source":"## A function to correct pixel data and rescale intercercepts ob 12 bit images\ndef dcm_correction(dcm_img):\n        x = dcm_img.pixel_array + 1000\n        px_mode = 4096\n        x[x >= px_mode] = x[x >= px_mode] - px_mode #if there are extra bits in 12-bit grayscale(<=4096)\n        dcm_img.PixelData = x.tobytes()\n        dcm_img.RescaleIntercept = -1000 #setting a common value across all 12-bit US images\n        \n#Systemic/linear windowing\ndef window_image(dcm, window_center, window_width):\n    if (dcm.BitsStored == 12) and (dcm.PixelRepresentation == 0) and (int(dcm.RescaleIntercept) > -100):\n        dcm_correction(dcm)\n\n    img = dcm.pixel_array * dcm.RescaleSlope + dcm.RescaleIntercept #reconstructing the image from pixels\n    img_min = window_center - window_width // 2 #lowest visible value\n    img_max = window_center + window_width // 2 #highest visible value\n    img = np.clip(img, img_min, img_max)\n\n    return img\n\n#Combining all\ndef bsb_window(dcm):\n    brain_img = window_image(dcm, 40, 80)\n    subdural_img = window_image(dcm, 80, 200)\n    soft_img = window_image(dcm, 40, 380)\n\n    brain_img = (brain_img - 0) / 80\n    subdural_img = (subdural_img - (-20)) / 200\n    soft_img = (soft_img - (-150)) / 380\n    bsb_img = np.array([brain_img, subdural_img, soft_img]).transpose(1, 2, 0)\n\n    return bsb_img","metadata":{"execution":{"iopub.status.busy":"2022-05-08T05:35:42.648166Z","iopub.execute_input":"2022-05-08T05:35:42.648416Z","iopub.status.idle":"2022-05-08T05:35:42.658692Z","shell.execute_reply.started":"2022-05-08T05:35:42.648387Z","shell.execute_reply":"2022-05-08T05:35:42.657902Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class IntracranialDataset(Dataset):\n\n    def __init__(self, csv_file, path, labels, transform=None):\n        self.path = path\n        self.data = pd.read_csv(csv_file)\n        self.transform = transform\n        self.labels = labels\n\n    def __len__(self):\n        return len(self.data)\n\n    def __getitem__(self, idx):\n#         img_name = os.path.join(self.path, self.data.loc[idx, 'Image'] + '.png')\n#         img = cv2.imread(img_name)   \n        try:\n            dicom = pydicom.dcmread(self.path, self.data.loc[idx, 'Image'] + '.dcm')\n            img = bsb_window(dicom)\n        except:\n            img = np.zeros((512, 512, 3))\n        \n        if self.transform:       \n            augmented = self.transform(image=img)\n            img = augmented['image']   \n            \n        if self.labels:\n            \n            labels = torch.tensor(\n                self.data.loc[idx, ['epidural', 'intraparenchymal', 'intraventricular', 'subarachnoid', 'subdural', 'any']])\n            return {'image': img, 'labels': labels}    \n        \n        else:      \n            \n            return {'image': img}","metadata":{"execution":{"iopub.status.busy":"2022-05-08T05:35:50.392699Z","iopub.execute_input":"2022-05-08T05:35:50.393425Z","iopub.status.idle":"2022-05-08T05:35:50.403349Z","shell.execute_reply.started":"2022-05-08T05:35:50.393386Z","shell.execute_reply":"2022-05-08T05:35:50.401702Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.value_counts()","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2022-05-03T10:32:24.050437Z","iopub.execute_input":"2022-05-03T10:32:24.050758Z","iopub.status.idle":"2022-05-03T10:32:39.056598Z","shell.execute_reply.started":"2022-05-03T10:32:24.05072Z","shell.execute_reply":"2022-05-03T10:32:39.055914Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_metadata = pd.read_csv(train_metadata_csv)\ntest_metadata = pd.read_csv(test_metadata_csv)","metadata":{"execution":{"iopub.status.busy":"2022-05-08T05:35:54.648626Z","iopub.execute_input":"2022-05-08T05:35:54.649421Z","iopub.status.idle":"2022-05-08T05:35:57.435604Z","shell.execute_reply.started":"2022-05-08T05:35:54.64937Z","shell.execute_reply":"2022-05-08T05:35:57.434884Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_metadata[['ID', 'Image', 'Diagnosis']] = train_metadata['ID'].str.split('_', expand=True)\ntrain_metadata['ImageID'] = 'ID_' + train_metadata['Image']\ntrain_metadata.head()","metadata":{"execution":{"iopub.status.busy":"2022-05-03T12:18:03.660382Z","iopub.execute_input":"2022-05-03T12:18:03.660843Z","iopub.status.idle":"2022-05-03T12:18:06.41878Z","shell.execute_reply.started":"2022-05-03T12:18:03.660807Z","shell.execute_reply":"2022-05-03T12:18:06.41804Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_metadata.drop(['ID', 'Diagnosis'], axis=1)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-05-03T12:34:40.87572Z","iopub.execute_input":"2022-05-03T12:34:40.876266Z","iopub.status.idle":"2022-05-03T12:34:41.536792Z","shell.execute_reply.started":"2022-05-03T12:34:40.876227Z","shell.execute_reply":"2022-05-03T12:34:41.535993Z"},"_kg_hide-output":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_metadata[:15]","metadata":{"execution":{"iopub.status.busy":"2022-05-03T12:34:56.084895Z","iopub.execute_input":"2022-05-03T12:34:56.085176Z","iopub.status.idle":"2022-05-03T12:34:56.124763Z","shell.execute_reply.started":"2022-05-03T12:34:56.085142Z","shell.execute_reply":"2022-05-03T12:34:56.124083Z"},"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Data Preparation","metadata":{}},{"cell_type":"code","source":"# Prepare train table\ntrain[['ID', 'Image', 'Diagnosis']] = train['ID'].str.split('_', expand=True)\ntrain = train[['Image', 'Diagnosis', 'Label']]\ntrain.drop_duplicates(inplace=True)\ntrain = train.pivot(index='Image', columns='Diagnosis', values='Label').reset_index()\ntrain['Image'] = 'ID_' + train['Image']","metadata":{"execution":{"iopub.status.busy":"2022-05-08T05:36:01.212687Z","iopub.execute_input":"2022-05-08T05:36:01.213389Z","iopub.status.idle":"2022-05-08T05:36:23.875281Z","shell.execute_reply.started":"2022-05-08T05:36:01.213348Z","shell.execute_reply":"2022-05-08T05:36:23.87449Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Remove invalid instances of images(dcm, PNG)\npng = glob.glob(os.path.join(train_images_dir, '*.dcm'))\npng = [os.path.basename(png)[:-4] for png in png]\npng = np.array(png)","metadata":{"execution":{"iopub.status.busy":"2022-05-08T05:36:23.876958Z","iopub.execute_input":"2022-05-08T05:36:23.87736Z","iopub.status.idle":"2022-05-08T05:36:54.565596Z","shell.execute_reply.started":"2022-05-08T05:36:23.877322Z","shell.execute_reply":"2022-05-08T05:36:54.564861Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = train[train['Image'].isin(png)]\n# train.to_csv('train.csv', index=False)\ntrain.value_counts()","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2022-05-08T05:36:54.566914Z","iopub.execute_input":"2022-05-08T05:36:54.567172Z","iopub.status.idle":"2022-05-08T05:36:56.376802Z","shell.execute_reply.started":"2022-05-08T05:36:54.567138Z","shell.execute_reply":"2022-05-08T05:36:56.376132Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"merged_train = pd.merge(left=train, right=train_metadata, how='left', left_on='Image', right_on='ImageId')","metadata":{"execution":{"iopub.status.busy":"2022-05-08T05:36:56.378655Z","iopub.execute_input":"2022-05-08T05:36:56.37927Z","iopub.status.idle":"2022-05-08T05:36:57.476644Z","shell.execute_reply.started":"2022-05-08T05:36:56.379225Z","shell.execute_reply":"2022-05-08T05:36:57.475888Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"merged_train","metadata":{"execution":{"iopub.status.busy":"2022-05-05T12:01:43.373191Z","iopub.execute_input":"2022-05-05T12:01:43.373939Z","iopub.status.idle":"2022-05-05T12:01:43.400696Z","shell.execute_reply.started":"2022-05-05T12:01:43.3739Z","shell.execute_reply":"2022-05-05T12:01:43.399924Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Train/valid split \ntrain_series = train_metadata['SeriesInstanceUID'].unique() #Identifying unique scans by SeriesID: there are totally \n\nvalid_series = train_series[21000:]\ntrain_series = train_series[:21000]","metadata":{"execution":{"iopub.status.busy":"2022-05-08T05:36:57.478084Z","iopub.execute_input":"2022-05-08T05:36:57.478353Z","iopub.status.idle":"2022-05-08T05:36:57.565439Z","shell.execute_reply.started":"2022-05-08T05:36:57.478319Z","shell.execute_reply":"2022-05-08T05:36:57.564807Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(len(train_series))\nprint(len(valid_series))","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-05-08T05:36:57.56672Z","iopub.execute_input":"2022-05-08T05:36:57.567251Z","iopub.status.idle":"2022-05-08T05:36:57.572384Z","shell.execute_reply.started":"2022-05-08T05:36:57.567213Z","shell.execute_reply":"2022-05-08T05:36:57.571599Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_series","metadata":{"execution":{"iopub.status.busy":"2022-05-03T11:40:20.992963Z","iopub.execute_input":"2022-05-03T11:40:20.993509Z","iopub.status.idle":"2022-05-03T11:40:20.999129Z","shell.execute_reply.started":"2022-05-03T11:40:20.993465Z","shell.execute_reply":"2022-05-03T11:40:20.99841Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = merged_train[merged_train['SeriesInstanceUID'].isin(train_series)]\ntrain_df","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2022-05-08T05:36:57.573703Z","iopub.execute_input":"2022-05-08T05:36:57.574102Z","iopub.status.idle":"2022-05-08T05:36:58.146943Z","shell.execute_reply.started":"2022-05-08T05:36:57.574068Z","shell.execute_reply":"2022-05-08T05:36:58.146106Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"valid_df = merged_train[merged_train['SeriesInstanceUID'].isin(valid_series)]\nvalid_df","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2022-05-08T05:36:58.14835Z","iopub.execute_input":"2022-05-08T05:36:58.1486Z","iopub.status.idle":"2022-05-08T05:36:58.284253Z","shell.execute_reply.started":"2022-05-08T05:36:58.148564Z","shell.execute_reply":"2022-05-08T05:36:58.283421Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(len(train_df))\nprint(len(valid_df))","metadata":{"execution":{"iopub.status.busy":"2022-05-08T05:36:58.28577Z","iopub.execute_input":"2022-05-08T05:36:58.286045Z","iopub.status.idle":"2022-05-08T05:36:58.290798Z","shell.execute_reply.started":"2022-05-08T05:36:58.286009Z","shell.execute_reply":"2022-05-08T05:36:58.290065Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"So the training set has 728,513 slices and a validation set 24,290 slices","metadata":{}},{"cell_type":"code","source":"os.mkdir('./data')","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-05-08T05:42:59.936589Z","iopub.execute_input":"2022-05-08T05:42:59.936942Z","iopub.status.idle":"2022-05-08T05:42:59.94152Z","shell.execute_reply.started":"2022-05-08T05:42:59.936909Z","shell.execute_reply":"2022-05-08T05:42:59.940862Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.to_csv('data/train.csv', index=False)\nprint(train_df['any'].value_counts())\nvalid_df.to_csv('data/valid.csv', index=False)\nprint(valid_df['any'].value_counts())","metadata":{"execution":{"iopub.status.busy":"2022-05-08T05:43:02.799507Z","iopub.execute_input":"2022-05-08T05:43:02.799787Z","iopub.status.idle":"2022-05-08T05:43:08.393075Z","shell.execute_reply.started":"2022-05-08T05:43:02.799755Z","shell.execute_reply":"2022-05-08T05:43:08.392283Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Prepare test table\ntest[['ID', 'Image', 'Diagnosis']] = test['ID'].str.split('_', expand=True)\ntest['Image'] = 'ID_' + test['Image']\ntest = test[['Image', 'Label']]\ntest.drop_duplicates(inplace=True)\n\ntest.to_csv('data/test.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2022-05-08T05:43:46.586101Z","iopub.execute_input":"2022-05-08T05:43:46.586584Z","iopub.status.idle":"2022-05-08T05:43:48.664681Z","shell.execute_reply.started":"2022-05-08T05:43:46.586547Z","shell.execute_reply":"2022-05-08T05:43:48.663946Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Data loaders\ntransform_train = Compose([Resize(256, 256),\n                           Normalize(mean=[0.1738, 0.1433, 0.1970], std=[0.3161, 0.2850, 0.3111], max_pixel_value=1.),\n                           HorizontalFlip(),\n                           ShiftScaleRotate(),\n                           RandomBrightnessContrast(),\n                           ToTensorV2()])\n\ntransform_test = Compose([Resize(256, 256),\n                          Normalize(mean=[0.1738, 0.1433, 0.1970], std=[0.3161, 0.2850, 0.3111], max_pixel_value=1.),\n                          ToTensorV2()])\n","metadata":{"execution":{"iopub.status.busy":"2022-05-08T05:43:12.178631Z","iopub.execute_input":"2022-05-08T05:43:12.181368Z","iopub.status.idle":"2022-05-08T05:43:12.18758Z","shell.execute_reply.started":"2022-05-08T05:43:12.181318Z","shell.execute_reply":"2022-05-08T05:43:12.186569Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset = IntracranialDataset(\n    csv_file='data/train.csv', path=train_images_dir, transform=transform_train, labels=True)\n# print(len(train_dataset))\n\nvalid_dataset = IntracranialDataset(\n    csv_file='data/valid.csv', path=train_images_dir, transform=transform_train, labels=True)\n# print(len(valid_dataset))\n\n","metadata":{"execution":{"iopub.status.busy":"2022-05-08T05:43:22.965354Z","iopub.execute_input":"2022-05-08T05:43:22.965608Z","iopub.status.idle":"2022-05-08T05:43:25.169283Z","shell.execute_reply.started":"2022-05-08T05:43:22.965579Z","shell.execute_reply":"2022-05-08T05:43:25.168592Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dataset = IntracranialDataset(\n    csv_file='data/test.csv', path=test_images_dir, transform=transform_test, labels=False)\n# print(len(test_dataset))","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_loader_train = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=4)\nprint(len(data_loader_train))\ndata_loader_valid = torch.utils.data.DataLoader(valid_dataset, batch_size=batch_size, shuffle=False, num_workers=2)\nprint(len(data_loader_valid))","metadata":{"execution":{"iopub.status.busy":"2022-05-08T06:22:10.678518Z","iopub.execute_input":"2022-05-08T06:22:10.678792Z","iopub.status.idle":"2022-05-08T06:22:10.688483Z","shell.execute_reply.started":"2022-05-08T06:22:10.67876Z","shell.execute_reply":"2022-05-08T06:22:10.687757Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_loader_test = torch.utils.data.DataLoader(test_dataset, batch_size=batch_size, shuffle=False, num_workers=2)\nprint(len(data_loader_test))","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Model","metadata":{}},{"cell_type":"code","source":"from torch.hub import load_state_dict_from_url\nfrom torchvision.models.resnet import ResNet, Bottleneck","metadata":{"execution":{"iopub.status.busy":"2022-05-08T05:47:23.05282Z","iopub.execute_input":"2022-05-08T05:47:23.053393Z","iopub.status.idle":"2022-05-08T05:47:23.057137Z","shell.execute_reply.started":"2022-05-08T05:47:23.053355Z","shell.execute_reply":"2022-05-08T05:47:23.056355Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_urls = {\n    'resnext101_32x8d': 'https://download.pytorch.org/models/ig_resnext101_32x8-c38310e5.pth',\n    'resnext101_32x16d': 'https://download.pytorch.org/models/ig_resnext101_32x16-c6f796b0.pth',\n    'resnext101_32x32d': 'https://download.pytorch.org/models/ig_resnext101_32x32-e4b90b00.pth',\n    'resnext101_32x48d': 'https://download.pytorch.org/models/ig_resnext101_32x48-3e41cc8a.pth',\n}","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-05-08T05:47:26.188714Z","iopub.execute_input":"2022-05-08T05:47:26.189203Z","iopub.status.idle":"2022-05-08T05:47:26.19308Z","shell.execute_reply.started":"2022-05-08T05:47:26.189163Z","shell.execute_reply":"2022-05-08T05:47:26.192386Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def _resnext(arch, block, layers, pretrained, progress, **kwargs):\n    model = ResNet(block, layers, **kwargs)\n    state_dict = load_state_dict_from_url(model_urls[arch], progress=progress)\n    model.load_state_dict(state_dict)\n    return model\n\ndef resnext101_32x8d_wsl(progress=True, **kwargs):\n    \"\"\"Constructs a ResNeXt-101 32x8 model pre-trained on weakly-supervised data\n    and finetuned on ImageNet from Figure 5 in\n    `\"Exploring the Limits of Weakly Supervised Pretraining\" <https://arxiv.org/abs/1805.00932>`_\n    Args:\n        progress (bool): If True, displays a progress bar of the download to stderr.\n    \"\"\"\n    kwargs['groups'] = 32\n    kwargs['width_per_group'] = 8\n    return _resnext('resnext101_32x8d', Bottleneck, [3, 4, 23, 3], True, progress, **kwargs)","metadata":{"execution":{"iopub.status.busy":"2022-05-08T05:47:33.416178Z","iopub.execute_input":"2022-05-08T05:47:33.41677Z","iopub.status.idle":"2022-05-08T05:47:33.428199Z","shell.execute_reply.started":"2022-05-08T05:47:33.41673Z","shell.execute_reply":"2022-05-08T05:47:33.4273Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = resnext101_32x8d_wsl()\nprint(model)","metadata":{"_kg_hide-output":true,"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-05-07T10:50:19.286351Z","iopub.execute_input":"2022-05-07T10:50:19.287229Z","iopub.status.idle":"2022-05-07T10:50:35.300236Z","shell.execute_reply.started":"2022-05-07T10:50:19.287157Z","shell.execute_reply":"2022-05-07T10:50:35.299477Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"list(model.children())","metadata":{"execution":{"iopub.status.busy":"2022-05-03T15:00:10.664902Z","iopub.execute_input":"2022-05-03T15:00:10.665178Z","iopub.status.idle":"2022-05-03T15:00:10.6751Z","shell.execute_reply.started":"2022-05-03T15:00:10.665149Z","shell.execute_reply":"2022-05-03T15:00:10.674343Z"},"_kg_hide-input":true,"_kg_hide-output":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class ResNeXtModel(torch.nn.Module):\n    def __init__(self):\n        super(ResNeXtModel, self).__init__()\n        resnext = resnext101_32x8d_wsl()\n        self.base = torch.nn.Sequential(*list(resnext.children())[:-1])\n        self.fc = torch.nn.Sequential(torch.nn.Linear(2048,6))\n    \n    def forward(self, input):\n        features = self.base(input).reshape(-1, 2048)\n        out = self.fc(features)\n        return out, features","metadata":{"execution":{"iopub.status.busy":"2022-05-08T05:52:57.700222Z","iopub.execute_input":"2022-05-08T05:52:57.70048Z","iopub.status.idle":"2022-05-08T05:52:57.707368Z","shell.execute_reply.started":"2022-05-08T05:52:57.700452Z","shell.execute_reply":"2022-05-08T05:52:57.7067Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Training & Validation","metadata":{}},{"cell_type":"code","source":"# Installing useful libraries\n\n!git clone https://github.com/NVIDIA/apex && cd apex && pip install -v --no-cache-dir --global-option=\"--cpp_ext\" --global-option=\"--cuda_ext\" ./","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2022-05-08T05:56:53.815455Z","iopub.execute_input":"2022-05-08T05:56:53.815919Z","iopub.status.idle":"2022-05-08T06:08:37.737273Z","shell.execute_reply.started":"2022-05-08T05:56:53.815882Z","shell.execute_reply":"2022-05-08T06:08:37.73641Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#For Mixed precision training\nfrom apex import amp","metadata":{"execution":{"iopub.status.busy":"2022-05-08T06:08:37.741083Z","iopub.execute_input":"2022-05-08T06:08:37.741324Z","iopub.status.idle":"2022-05-08T06:08:37.781599Z","shell.execute_reply.started":"2022-05-08T06:08:37.741297Z","shell.execute_reply":"2022-05-08T06:08:37.780899Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')","metadata":{"execution":{"iopub.status.busy":"2022-05-08T05:53:08.169821Z","iopub.execute_input":"2022-05-08T05:53:08.170145Z","iopub.status.idle":"2022-05-08T05:53:08.247978Z","shell.execute_reply.started":"2022-05-08T05:53:08.17011Z","shell.execute_reply":"2022-05-08T05:53:08.24705Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = ResNeXtModel()\nmodel.to(device)\n\ncriterion = torch.nn.BCEWithLogitsLoss()\noptimizer = optim.Adam(model.parameters(), lr=1e-5)","metadata":{"execution":{"iopub.status.busy":"2022-05-08T05:53:11.28376Z","iopub.execute_input":"2022-05-08T05:53:11.284317Z","iopub.status.idle":"2022-05-08T05:53:32.489274Z","shell.execute_reply.started":"2022-05-08T05:53:11.284278Z","shell.execute_reply":"2022-05-08T05:53:32.488537Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model, optimizer = amp.initialize(model, optimizer, opt_level=\"O1\")","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2022-05-08T06:08:37.782524Z","iopub.execute_input":"2022-05-08T06:08:37.783033Z","iopub.status.idle":"2022-05-08T06:08:37.807049Z","shell.execute_reply.started":"2022-05-08T06:08:37.783004Z","shell.execute_reply":"2022-05-08T06:08:37.806369Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install GPUtil","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2022-05-07T11:33:45.055028Z","iopub.execute_input":"2022-05-07T11:33:45.055315Z","iopub.status.idle":"2022-05-07T11:33:56.360356Z","shell.execute_reply.started":"2022-05-07T11:33:45.055284Z","shell.execute_reply":"2022-05-07T11:33:56.359434Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from GPUtil import showUtilization as gpu_usage\nfrom numba import cuda","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-05-07T12:21:30.521943Z","iopub.execute_input":"2022-05-07T12:21:30.522854Z","iopub.status.idle":"2022-05-07T12:21:31.030378Z","shell.execute_reply.started":"2022-05-07T12:21:30.522814Z","shell.execute_reply":"2022-05-07T12:21:31.02959Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def free_gpu_cache():\n    print(\"Initial GPU Usage\")\n    gpu_usage()                             \n\n    torch.cuda.empty_cache()\n\n    cuda.select_device(0)\n    cuda.close()\n    cuda.select_device(0)\n\n    print(\"GPU Usage after emptying the cache\")\n    gpu_usage()\n\nfree_gpu_cache()   ","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-05-07T12:21:45.813673Z","iopub.execute_input":"2022-05-07T12:21:45.814495Z","iopub.status.idle":"2022-05-07T12:21:47.530673Z","shell.execute_reply.started":"2022-05-07T12:21:45.814453Z","shell.execute_reply":"2022-05-07T12:21:47.529478Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"torch.cuda.empty_cache()","metadata":{"execution":{"iopub.status.busy":"2022-05-07T12:21:04.621226Z","iopub.execute_input":"2022-05-07T12:21:04.622007Z","iopub.status.idle":"2022-05-07T12:21:04.62671Z","shell.execute_reply.started":"2022-05-07T12:21:04.621949Z","shell.execute_reply":"2022-05-07T12:21:04.625451Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gpu_usage()  ","metadata":{"execution":{"iopub.status.busy":"2022-05-07T12:21:36.321576Z","iopub.execute_input":"2022-05-07T12:21:36.321888Z","iopub.status.idle":"2022-05-07T12:21:36.473773Z","shell.execute_reply.started":"2022-05-07T12:21:36.321857Z","shell.execute_reply":"2022-05-07T12:21:36.47292Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torch.utils.tensorboard import SummaryWriter","metadata":{"execution":{"iopub.status.busy":"2022-05-08T06:09:06.554813Z","iopub.execute_input":"2022-05-08T06:09:06.555334Z","iopub.status.idle":"2022-05-08T06:09:06.827927Z","shell.execute_reply.started":"2022-05-08T06:09:06.555293Z","shell.execute_reply":"2022-05-08T06:09:06.827188Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tb  = SummaryWriter('runs/ich_detection_experiment_1')\n# tb  = SummaryWriter()","metadata":{"execution":{"iopub.status.busy":"2022-05-08T06:09:09.410153Z","iopub.execute_input":"2022-05-08T06:09:09.410415Z","iopub.status.idle":"2022-05-08T06:09:12.740913Z","shell.execute_reply.started":"2022-05-08T06:09:09.410384Z","shell.execute_reply":"2022-05-08T06:09:12.740151Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for epoch in range(n_epochs):\n\n    print('Epoch {}/{}'.format(epoch + 1, n_epochs))\n    print('-' * 10)\n\n    model.train()\n    tr_loss = 0\n    tr_correct = 0\n    \n    tk0 = tqdm.tqdm(data_loader_train, desc=\"Iteration\")\n\n    for step, batch in enumerate(tk0):\n        inputs = batch[\"image\"]\n#         print(inputs.shape)\n        labels = batch[\"labels\"]\n#         print(labels.shape)\n\n        inputs = inputs.to(device, dtype=torch.float)\n        labels = labels.to(device, dtype=torch.float)\n\n        outputs, _ = model(inputs)\n#         print(outputs.shape)\n#         print(outputs)\n        loss = criterion(outputs, labels)\n        preds = (torch.sigmoid(outputs) >=0.5).float()*1\n#         print(preds.shape)\n\n\n        with amp.scale_loss(loss, optimizer) as scaled_loss:\n            scaled_loss.backward()\n            \n        tr_loss += loss.item()\n        tr_correct += torch.sum(preds == labels)\n#         print(tr_correct)\n\n        optimizer.step()\n        optimizer.zero_grad()\n\n        if step % 512 == 0:\n            epoch_loss = tr_loss / (step + 1)\n            print('Training Loss at {}: {:.4f}'.format(step, epoch_loss))\n\n    epoch_loss = tr_loss / len(data_loader_train)\n    print('Training Loss: {:.4f}'.format(epoch_loss))\n    print('-----------------------')\n    #Tensorboard code for visualisations\n    tb.add_scalar(\"Training Loss\", tr_loss, epoch)\n    tb.add_scalar(\"Training Correct preds\", tr_correct, epoch)\n    tb.add_scalar(\"Training Accuracy\", tr_correct/ len(train_dataset), epoch)\n    print('Finished Training!')\n    \n    model.eval()\n    tr_loss = 0\n    tr_correct = 0\n\n    auc_preds = []\n    auc_truths = []\n    \n    print('Validation starts...')\n    for step, batch in enumerate(data_loader_valid):\n        inputs = batch[\"image\"]\n        labels = batch[\"labels\"]\n\n        inputs = inputs.to(device, dtype=torch.float)\n        labels = labels.to(device, dtype=torch.float)\n\n        outputs, _ = model(inputs)\n        loss = criterion(outputs, labels)\n        preds = (torch.sigmoid(outputs) >=0.5).float()*1\n\n        tr_loss += loss.item()\n        tr_correct += torch.sum(preds == labels)\n\n        auc_preds.append(preds.view(-1, 6).detach().cpu().numpy())\n        auc_truths.append(labels.view(-1, 6).detach().cpu().numpy())\n\n    epoch_loss = tr_loss / len(data_loader_valid)\n    print('Validation Loss: {:.4f}'.format(epoch_loss))\n    \n    #Tensorboard code for visualisations\n    tb.add_scalar(\"Validation Loss\", tr_loss, epoch)\n    tb.add_scalar(\"Training Correct preds\", tr_correct, epoch)\n    tb.add_scalar(\"Training Accuracy\", tr_correct/ len(train_dataset), epoch)\n    print('Finished Validation!')\n    \n    roc_preds = np.concatenate(auc_preds)\n\n    roc_truths = np.concatenate(auc_truths)\n\n    for tp in range(0, 6):\n        print('ROC_AUC')\n        print(COLS[tp], roc_auc_score(roc_truths[:, tp], roc_preds[:, tp]), )\n        print('F1 SCORE')\n        print(COLS[tp], f1_score(roc_truths[:, tp], roc_preds[:, tp]), )\n        print('ACCURACY')\n        print(COLS[tp], accuracy_score(roc_truths[:, tp], roc_preds[:, tp]), )\n        tn, fp, fn, tp = confusion_matrix(roc_truths[:, tp], roc_preds[:, tp]).ravel()\n        print('SENSITIVITY')\n        print(COLS[tp], tp/(tp+fn), )\n        print('SPECIFICITY')\n        print(COLS[tp], tn/(tn+fp), )    \n        print('JACCARD SCORE')\n        print(COLS[tp], jaccard_score(roc_truths[:, tp], roc_preds[:, tp]), )\n        \n    print('-----------------------')\n\n# Save checkpoint\ncheckpoint = {\n    'model': model.state_dict(),\n    'optimizer': optimizer.state_dict(),\n    # 'amp': amp.state_dict()\n}\ntorch.save(checkpoint, 'model.pt')\ntb.close()","metadata":{"execution":{"iopub.status.busy":"2022-05-08T06:35:03.913988Z","iopub.execute_input":"2022-05-08T06:35:03.914442Z","iopub.status.idle":"2022-05-08T13:18:54.053788Z","shell.execute_reply.started":"2022-05-08T06:35:03.914402Z","shell.execute_reply":"2022-05-08T13:18:54.05264Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Points to note -**\n- It is **NOT** multi-class but a **multi-label** classification problem(Refer to the paper)\n- Try using Sigmoid function to get 0or1 across each class, NOT Softmax\n- While finding accuracy, to fin correct predictions use threshold for outputs as 0.5\n\n**Observations and points to noye** -\n- On just 1 epoch, the results are **very poor**\n- Accuracy is high for obvious reasons. It **should not be used** to judge, since it is an **imbalaced problem**\n- F1 should be used when **we care about positive classes**. We should look at improving this\n- ROC-AUC should be used when you care **equally about positive and negative classes**. **Not advised on highly imbalanced** dataset(but let's check what we get and comapre with paper. Look into *average_precision_score* metric instead(when you care more about positive than negative class)\n- What did we get?\n    - Accuracy high - DO NOT go by this\n    - F1 of 0 - very bad, hope it improves when trained on more epochs\n    - ROC-AUC of 0.5 - which means not discriminating between the two claases(0/1); again hope to improve\n    \n**NOTE**\nError fixed. Should work tommorrow(::finger crossed::)\n- Tensorboard visualisation codes are right! But the site to display them doesn't seem to work through kaggle. It should work locally","metadata":{}},{"cell_type":"code","source":"tb.close()","metadata":{"execution":{"iopub.status.busy":"2022-05-08T14:11:58.659808Z","iopub.execute_input":"2022-05-08T14:11:58.660505Z","iopub.status.idle":"2022-05-08T14:11:58.665372Z","shell.execute_reply.started":"2022-05-08T14:11:58.660461Z","shell.execute_reply":"2022-05-08T14:11:58.664398Z"},"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!tensorboard --logdir=runs","metadata":{"execution":{"iopub.status.busy":"2022-05-08T14:12:01.889045Z","iopub.execute_input":"2022-05-08T14:12:01.889637Z","iopub.status.idle":"2022-05-08T14:14:06.565762Z","shell.execute_reply.started":"2022-05-08T14:12:01.889586Z","shell.execute_reply":"2022-05-08T14:14:06.564899Z"},"_kg_hide-output":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Testing","metadata":{}},{"cell_type":"code","source":"# Nothing yet","metadata":{},"execution_count":null,"outputs":[]}]}