{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Introduction\n\nUsing mixed precision along with efficientnet-b0 and a little bit of pre-processing, a single pass of the entire 670k image dataset should take approx. 45m (at 224x224 resolution)."},{"metadata":{},"cell_type":"markdown","source":"# Sources\n\nWindowing functions for pre-processed data taken from the following:\n\n- https://www.kaggle.com/omission/eda-view-dicom-images-with-correct-windowing "},{"metadata":{},"cell_type":"markdown","source":"# Parameters"},{"metadata":{"trusted":false},"cell_type":"code","source":"# Input\n\ndir_csv = '../input/rsna-intracranial-hemorrhage-detection'\ndir_train_img = '../input/rsna-train-stage-1-images-png-224x/stage_1_train_png_224x'\ndir_test_img = '../input/rsna-test-stage-1-images-png-224x/stage_1_test_png_224x'\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"\n# Parameters\n\nn_classes = 6\nn_epochs = 5\nbatch_size = 128\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Setup\n\nNeed to grab a couple of extra libraries\n\n- Nvidia Apex for mixed precision training (https://github.com/NVIDIA/apex)\n- Pytorch implementation of efficientnet (https://github.com/lukemelas/EfficientNet-PyTorch)"},{"metadata":{"trusted":false,"_kg_hide-output":true},"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\" ./\n!pip install --upgrade efficientnet-pytorch\n    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# Libraries\n\nfrom apex import amp\nimport os\nimport cv2\nimport glob\nimport pydicom\nimport numpy as np\nimport pandas as pd\nfrom efficientnet_pytorch import EfficientNet\nimport torch\nimport torch.optim as optim\nfrom albumentations import Compose, ShiftScaleRotate, Resize\nfrom albumentations.pytorch import ToTensor\nfrom torch.utils.data import Dataset\nfrom tqdm import tqdm_notebook as tqdm\nfrom matplotlib import pyplot as plt","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"\n# Functions\n\nclass IntracranialDataset(Dataset):\n\n    def __init__(self, csv_file, path, labels, transform=None):\n        \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        \n        return len(self.data)\n\n    def __getitem__(self, idx):\n        \n        img_name = os.path.join(self.path, self.data.loc[idx, 'Image'] + '.png')\n        img = cv2.imread(img_name)   \n        \n        if self.transform:       \n            \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}\n    \n    \n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# CSV"},{"metadata":{"trusted":false},"cell_type":"code","source":"# CSVs\n\ntrain = pd.read_csv(os.path.join(dir_csv, 'stage_1_train.csv'))\ntest = pd.read_csv(os.path.join(dir_csv, 'stage_1_sample_submission.csv'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"\n# Split train out into row per image and save a sample\n\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']\ntrain.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# Some files didn't contain legitimate images, so we need to remove them\n\npng = glob.glob(os.path.join(dir_train_img, '*.png'))\npng = [os.path.basename(png)[:-4] for png in png]\npng = np.array(png)\n\ntrain = train[train['Image'].isin(png)]\ntrain.to_csv('train.csv', index=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# Also prepare the test data\n\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('test.csv', index=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# DataLoaders"},{"metadata":{"trusted":false},"cell_type":"code","source":"# Data loaders\n\ntransform_train = Compose([\n    ShiftScaleRotate(),\n    ToTensor()\n])\n\ntransform_test= Compose([\n    ToTensor()\n])\n\ntrain_dataset = IntracranialDataset(\n    csv_file='train.csv', path=dir_train_img, transform=transform_train, labels=True)\n\ntest_dataset = IntracranialDataset(\n    csv_file='test.csv', path=dir_test_img, transform=transform_test, labels=False)\n\ndata_loader_train = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=False, num_workers=4)\ndata_loader_test = torch.utils.data.DataLoader(test_dataset, batch_size=batch_size, shuffle=False, num_workers=4)","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# Plot train example\n\nbatch = next(iter(data_loader_train))\nfig, axs = plt.subplots(1, 5, figsize=(15,5))\n\nfor i in np.arange(5):\n    \n    axs[i].imshow(np.transpose(batch['image'][i].numpy(), (1,2,0))[:,:,0], cmap=plt.cm.bone)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# Plot test example\n\nbatch = next(iter(data_loader_test))\nfig, axs = plt.subplots(1, 5, figsize=(15,5))\n\nfor i in np.arange(5):\n    \n    axs[i].imshow(np.transpose(batch['image'][i].numpy(), (1,2,0))[:,:,0], cmap=plt.cm.bone)\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Model"},{"metadata":{"trusted":false},"cell_type":"code","source":"# Model\n\ndevice = torch.device(\"cuda:0\")\nmodel = EfficientNet.from_pretrained('efficientnet-b0') \nmodel._fc = torch.nn.Linear(1280, n_classes)\n\nmodel.to(device)\n\ncriterion = torch.nn.BCEWithLogitsLoss()\nplist = [{'params': model.parameters(), 'lr': 2e-5}]\noptimizer = optim.Adam(plist, lr=2e-5)\n\nmodel, optimizer = amp.initialize(model, optimizer, opt_level=\"O1\")\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Training"},{"metadata":{"trusted":false},"cell_type":"code","source":"# Train\n\n\nfor epoch in range(n_epochs):\n    \n    print('Epoch {}/{}'.format(epoch, n_epochs - 1))\n    print('-' * 10)\n\n    model.train()    \n    tr_loss = 0\n    \n    tk0 = tqdm(data_loader_train, desc=\"Iteration\")\n\n    for step, batch in enumerate(tk0):\n\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\n        with amp.scale_loss(loss, optimizer) as scaled_loss:\n            scaled_loss.backward()\n\n        tr_loss += loss.item()\n\n        optimizer.step()\n        optimizer.zero_grad()\n\n    epoch_loss = tr_loss / len(data_loader_train)\n    print('Training Loss: {:.4f}'.format(epoch_loss))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Inference"},{"metadata":{"trusted":false},"cell_type":"code","source":"# Inference\n\nfor param in model.parameters():\n    param.requires_grad = False\n\nmodel.eval()\n\ntest_pred = np.zeros((len(test_dataset) * n_classes, 1))\n\nfor i, x_batch in enumerate(tqdm(data_loader_test)):\n    \n    x_batch = x_batch[\"image\"]\n    x_batch = x_batch.to(device, dtype=torch.float)\n    \n    with torch.no_grad():\n        \n        pred = model(x_batch)\n        \n        test_pred[(i * batch_size * n_classes):((i + 1) * batch_size * n_classes)] = torch.sigmoid(\n            pred).detach().cpu().reshape((len(x_batch) * n_classes, 1))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Submission"},{"metadata":{"trusted":false},"cell_type":"code","source":"# Submission\n\nsubmission =  pd.read_csv(os.path.join(dir_csv, 'stage_1_sample_submission.csv'))\nsubmission = pd.concat([submission.drop(columns=['Label']), pd.DataFrame(test_pred)], axis=1)\nsubmission.columns = ['ID', 'Label']\n\nsubmission.to_csv('submission.csv', index=False)\nsubmission.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Clean Up\n\nHave to clean up since Kaggle limits the number of files that can be output from a kernel"},{"metadata":{"trusted":false},"cell_type":"code","source":"!rm -rf /kaggle/working/apex\n!rm test.csv\n!rm train.csv","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.6.6"},"widgets":{"application/vnd.jupyter.widget-state+json":{"state":{"14262d037faf4d3b9551f59e3fff546b":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"HTMLModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"HTMLView","description":"","description_tooltip":null,"layout":"IPY_MODEL_990e3a2d1d0d4399b36f1fcf603a3194","placeholder":"​","style":"IPY_MODEL_2a31c164a41f4c438244ed0d04e09646","value":"100% 614/614 [03:20&lt;00:00,  4.44it/s]"}},"1e3604684f7741fdbf1d7325a52d4343":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"ProgressStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"ProgressStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","bar_color":null,"description_width":""}},"2a31c164a41f4c438244ed0d04e09646":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"DescriptionStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"DescriptionStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","description_width":""}},"308a378af0ca4346bc7df3e5398c8634":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"IntProgressModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"IntProgressModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"ProgressView","bar_style":"","description":"Iteration","description_tooltip":null,"layout":"IPY_MODEL_c65d5ea89eb04ba782bc01f2dbb816f7","max":5249,"min":0,"orientation":"horizontal","style":"IPY_MODEL_be3d6a00817a4cb49646350730235692","value":4931}},"3d62fe3e84df4eb3a61a225ff3bcbcb8":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"HBoxModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"HBoxModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"HBoxView","box_style":"","children":["IPY_MODEL_308a378af0ca4346bc7df3e5398c8634","IPY_MODEL_e4398b0896d740aa82667d15645f2353"],"layout":"IPY_MODEL_6a39f656c9534d2498c417f07c186ed6"}},"50ff61d3047d4b0a9875b5416426818e":{"model_module":"@jupyter-widgets/base","model_module_version":"1.2.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"55c455b87acc4e85bb9f08e4a905ef87":{"model_module":"@jupyter-widgets/base","model_module_version":"1.2.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"608435e40af040c7880e6db9440d5832":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"IntProgressModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"IntProgressModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"ProgressView","bar_style":"success","description":"","description_tooltip":null,"layout":"IPY_MODEL_50ff61d3047d4b0a9875b5416426818e","max":614,"min":0,"orientation":"horizontal","style":"IPY_MODEL_1e3604684f7741fdbf1d7325a52d4343","value":614}},"6a39f656c9534d2498c417f07c186ed6":{"model_module":"@jupyter-widgets/base","model_module_version":"1.2.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"7d355304dad44372a7df9cb7db64331b":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"DescriptionStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"DescriptionStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","description_width":""}},"990e3a2d1d0d4399b36f1fcf603a3194":{"model_module":"@jupyter-widgets/base","model_module_version":"1.2.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"be3d6a00817a4cb49646350730235692":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"ProgressStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"ProgressStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","bar_color":null,"description_width":"initial"}},"c65d5ea89eb04ba782bc01f2dbb816f7":{"model_module":"@jupyter-widgets/base","model_module_version":"1.2.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"ce6a9e9baf2e4e4eb60114cd923524bd":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"HBoxModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"HBoxModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"HBoxView","box_style":"","children":["IPY_MODEL_608435e40af040c7880e6db9440d5832","IPY_MODEL_14262d037faf4d3b9551f59e3fff546b"],"layout":"IPY_MODEL_f267e8bf07da4a08a90eab8562740b19"}},"e4398b0896d740aa82667d15645f2353":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"HTMLModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"HTMLView","description":"","description_tooltip":null,"layout":"IPY_MODEL_55c455b87acc4e85bb9f08e4a905ef87","placeholder":"​","style":"IPY_MODEL_7d355304dad44372a7df9cb7db64331b","value":" 94% 4931/5249 [51:06&lt;03:31,  1.51it/s]"}},"f267e8bf07da4a08a90eab8562740b19":{"model_module":"@jupyter-widgets/base","model_module_version":"1.2.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}}},"version_major":2,"version_minor":0}}},"nbformat":4,"nbformat_minor":1}