{"cells":[{"metadata":{},"cell_type":"markdown","source":"# RSNA Intracranial Hemorrhage Detection\n- Identify acute intracranial hemorrhage and its subtypes"},{"metadata":{},"cell_type":"markdown","source":"- Intracranial hemorrhage, bleeding that occurs inside the cranium, is a serious health problem requiring rapid and often intensive medical treatment. For example, intracranial hemorrhages account for approximately 10% of strokes in the U.S., where stroke is the fifth-leading cause of death. Identifying the location and type of any hemorrhage present is a critical step in treating the patient.\n\n- Diagnosis requires an urgent procedure. When a patient shows acute neurological symptoms such as severe headache or loss of consciousness, highly trained specialists review medical images of the patient’s cranium to look for the presence, location and type of hemorrhage. The process is complicated and often time consuming.\n\n- In this competition, we will build an algorithm to detect acute intracranial hemorrhage and its subtypes."},{"metadata":{},"cell_type":"markdown","source":"![Types of Hemorrahages](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F603584%2F56162e47358efd77010336a373beb0d2%2Fsubtypes-of-hemorrhage.png?generation=1568657910458946&alt=media)"},{"metadata":{},"cell_type":"markdown","source":"- **This kernel is based on the starter pack created by Radek. check out his** [github page](https://github.com/radekosmulski/rsna-intracranial) **and** [kaggle kernel](https://www.kaggle.com/radek1/fastai-starter-pack-train-basic-model-and-submit).\n\n- The code to generate images to 224x224 is from [here](https://www.kaggle.com/taindow/generate-images-train)"},{"metadata":{},"cell_type":"markdown","source":"# Import Libraries\n- For this challenge we will use the latest version of [fastai v2 library](https://github.com/fastai/fastai_dev). The library is under active development so we will install it from source using 'pip'."},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"_kg_hide-output":true},"cell_type":"code","source":"#install fastai v2\n\n!pip install git+https://github.com/fastai/fastai_dev","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true,"_kg_hide-output":true},"cell_type":"code","source":"%matplotlib inline\n\nimport PIL\nimport pydicom\nimport numpy as np\nfrom pathlib import Path\nfrom matplotlib import pyplot as plt\nimport os\nimport torch\nimport seaborn as sns\nplt.style.use(\"seaborn\")\n\n#checking the input files\nprint(os.listdir(\"../input/rsna-intracranial-hemorrhage-detection/\"))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#set input data path\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'\ndir_train_csv = \"../input/rsnsa-intracranial-hemorrahage-detection/stage_1_train.csv\"\ndir_sample_submission_csv = \"../input/rsnsa-intracranial-hemorrahage-detection/stage_1_sample_submission.csv\"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#fastai libs\n\nfrom fastai2.torch_basics import *\nfrom fastai2.test import *\nfrom fastai2.layers import *\nfrom fastai2.data.all import *\nfrom fastai2.optimizer import *\nfrom fastai2.learner import *\nfrom fastai2.metrics import *\nfrom fastai2.vision.all import *\nfrom fastai2.vision.learner import *\nfrom fastai2.vision.models import *\nfrom fastai2.callback.all import *","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#get items\n\nitems = get_image_files(dir_train_img)\nitems = [i for i in items if '(copy)' not in i.name]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Processing the `stage_1_train.csv` into something more parsable."},{"metadata":{"trusted":true},"cell_type":"code","source":"!mkdir -p data\n\n#read the train csv\ndf_train = pd.read_csv(f'{dir_csv}/stage_1_train.csv')\ndf_train.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#check for any missing values in label\ndf_train.Label.isna().sum()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#refactor the csv file\n\ndf_train['fn'] = df_train.ID.apply(lambda x: '_'.join(x.split('_')[:2]) + '.png')\ndf_train.columns = ['ID', 'probability', 'fn']\ndf_train['label'] = df_train.ID.apply(lambda x: x.split('_')[-1])\ndf_train.drop_duplicates('ID', inplace=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"pivot = df_train.pivot(index='fn', columns='label', values='probability')\npivot.reset_index(inplace=True)\npivot.to_csv('data/train_pivot.csv', index=False)\npivot.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"> We need to refactor the pivot data since are using Data blocks API from fastai lib"},{"metadata":{"trusted":true},"cell_type":"code","source":"from collections import defaultdict\n\nd = defaultdict(list)\n\nfor fn in df_train.fn.unique(): \n    d[fn]\n    \nfor tup in df_train.itertuples():\n    if tup.probability:\n        d[tup.fn].append(tup.label)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#iterate through the items in 'd'\n\nks, vs = [], []\n\nfor k, v in d.items():\n    ks.append(k), vs.append(' '.join(v))\n    \n#save the dataframe\npd.DataFrame(data = {'fn': ks, \"labels\": vs}).to_csv('data/train_labels_as_string.csv', index = False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#define a class labeller\n\nclass Labeller():\n    \"\"\"path to label\"\"\"\n    def __init__(self):\n        self.df = pd.read_csv(\"data/train_labels_as_string.csv\")\n        self.df.set_index(\"fn\", inplace = True)\n        \n    def __call__(self, path):\n        fn = path.name\n        labels_txt = self.df.loc[fn].labels\n        if isinstance(labels_txt, float) or labels_txt == ' ': return []\n        return labels_txt.split(' ')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#create an object of the class\n\nlabeler = Labeller()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"classes = L(pd.read_csv(\"data/train_pivot.csv\").columns.tolist()[1:])\nclasses","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"mcat = MultiCategorize(vocab = classes)\nmcat.o2i = classes.val2idx()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"mcat.o2i #mapping dictionary","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"tfms = [PILImage.create, [Labeller(), mcat, OneHotEncode()]]\nds_img_tfms = [ToTensor()]\ndsrc = DataSource(items, tfms, splits = RandomSplitter()(items))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_paths = get_image_files(dir_test_img)\ntest_tfms = [PILImage.create, [lambda x: np.array([0,0,0,0,0,0])]]\ndsrc_test = DataSource([test_paths[0]] + test_paths, test_tfms, splits=[[0], L(range(len(test_paths))).map(lambda x: x + 1)])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dsrc_test[0]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"means = [0.1627, 0.1348, 0.1373]\nst_devs = [0.2961, 0.2605, 0.1889]\n\ndataset_stats = (means, st_devs)\ndataset_stats = broadcast_vec(1, 4, *dataset_stats)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#create train and test data bunch\n\nds_img_tfms = [ToTensor()]\ndl_tfms = [Cuda(), IntToFloatTensor(), Normalize(*dataset_stats)]\n\n#train data bunch\ndbch = dsrc.databunch(after_item = ds_img_tfms, after_batch = dl_tfms, bs = 128, num_workers = 4)\n\n#test data bunch\ndbch_test = dsrc_test.databunch(after_item = ds_img_tfms, after_batch = dl_tfms, bs = 128, num_workers = 4)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Create Model"},{"metadata":{"trusted":true},"cell_type":"code","source":"model = create_cnn_model(resnet18, 6, -2, True)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"- define how I want to split the model for applying differential learing rates"},{"metadata":{"trusted":true},"cell_type":"code","source":"model_segments = model[0][:6], model[0][6:], model[1]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def trainable_params_mod(model): return L(trainable_params(segment) for segment in model_segments)\n\n#define optimization function.\nopt_func = partial(Adam, wd=0.01, eps=1e-3)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#create a learner\n\nlearn = Learner(\n    dbch,\n    model,\n    loss_func=BCEWithLogitsLossFlat(),\n    metrics=[accuracy_multi],\n    opt_func=opt_func,\n    splitter=trainable_params_mod\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#freeze\n\nlearn.freeze_to(-1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#find learning rate\n\nlearn.lr_find()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#fit one cycle\n\nlearn.fit_one_cycle(2, 2e-2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#save the model\nlearn.save('phase-1')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#load the model again\nlearn.load('phase-1');","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#freeze\nlearn.freeze_to(-2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"learn.lr_find(start_lr=1e-8, end_lr=1e-1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"learn.fit_one_cycle(2, [1e-3, 1e-4, 1e-5]) #fit another cycle","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"learn.recorder.plot_loss() #plot the loss","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"learn.save('phase-2')\n\nlearn.load('phase-2');","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"learn.unfreeze()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"learn.fit_one_cycle(5, [1e-4, 5e-4, 1e-3])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"learn.save('phase-3')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"learn.load('phase-3')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"learn.metrics = [PrecisionMulti(), RecallMulti()]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"learn.validate()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"learn.dbunch = dbch_test","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"preds, targs = learn.get_preds()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#create a pred labels and probability\nids = []\nlabels = []\n\nfor path, pred in zip(test_paths, preds):\n    for i, label in enumerate(classes):\n        ids.append(f\"{path.name.split('.')[0]}_{label}\")\n        predicted_probability = '{0:1.10f}'.format(pred[i].item())\n        labels.append(predicted_probability)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#make submission file\npd.DataFrame({'ID': ids, 'Label': labels}).to_csv(f'submission.csv', index=False)","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":1}