{"cells":[{"metadata":{"_uuid":"13d2ca12cd093ec89adcac5871a928b5fb59fc3c"},"cell_type":"markdown","source":"# Histopathologic Cancer Detection\n\nThis challenge will focus on the detection and classification of breast cancer metastases in lymph nodes. Lymph nodes are small glands that filter lymph, the fluid that circulates through the lymphatic system. \n![bcancer](https://camelyon17.grand-challenge.org/media/CAMELYON17/public_html/breast_lymph_node.png)\nThe lymph nodes in the axilla are the first place breast cancer is likely to spread. Metastatic involvement of lymph nodes is one of the most important prognostic factors in breast cancer. Prognosis is poorer when cancer has spread to the lymph nodes. This is why lymph nodes are surgically removed and examined microscopically. However, the diagnostic procedure for pathologists is tedious and time-consuming. But most importantly, small metastases are very difficult to detect and sometimes they are missed."},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"from fastai import *\nfrom fastai.vision import *\nfrom fastai.callbacks.hooks import *\n\nimport numpy as np \nimport pandas as pd \nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom sklearn.metrics import auc,roc_curve\n\nimport os\nprint(os.listdir(\"../input\"))\n% matplotlib inline","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"261782ee933a03367fc036779eea852f2907c663"},"cell_type":"markdown","source":"## Exploratory Data Analysis\nIn this dataset, you are provided with a large number of small pathology images to classify. Files are named with an image id. The train_labels.csv file provides the ground truth for the images in the train folder. You are predicting the labels for the images in the test folder. A positive label indicates that the center 32x32px region of a patch contains at least one pixel of tumor tissue. Tumor tissue in the outer region of the patch does not influence the label. This outer region is provided to enable fully-convolutional models that do not use zero-padding, to ensure consistent behavior when applied to a whole-slide image."},{"metadata":{"trusted":true,"_uuid":"af5296ff9a5b946ce3b2b6e6db3ab24ecc5cdc44"},"cell_type":"code","source":"labels_path='../input/train_labels.csv'\nlabels = pd.read_csv(labels_path)\nlabels.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"1b2a678aa8e1574d8b275af398f4cc270a9ea1d5"},"cell_type":"code","source":"print(f'Number of labels {len(labels)}')\nsns.countplot(x='label',data=labels)","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"path=Path('../input/')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f45c62f381bbd320f9f20f965ccfa6fbfdd2edb5"},"cell_type":"code","source":"tfms=get_transforms(flip_vert=True, max_warp=0, max_rotate=0, max_lighting=0.05)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d1be83a4242be52aae5edaaaae9663be3dc1de76"},"cell_type":"code","source":"data=ImageDataBunch.from_csv(path, \n                             csv_labels='train_labels.csv', \n                             folder='train', \n                             suffix='.tif',\n                             num_workers=2,\n                             ds_tfms=tfms,\n                             bs=64,\n                             size=72,\n                             test=path/'test').normalize()\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"84b0ceea71158393131f4e25c6070d07c357d612"},"cell_type":"code","source":"data.show_batch(rows=3,figsize=(8,10))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"1e832e748aa6ec54f8cf8be05053069e54c97696"},"cell_type":"code","source":"learner= create_cnn(data, models.resnet50, metrics=[accuracy], model_dir=\"/tmp/models/\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"61b506b0f54011367bcf4c2a4d9bcb9caaca6e77"},"cell_type":"code","source":"learner.lr_find()\nlearner.recorder.plot()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"7042d7de49e75e15c91373aba6a33eb25ab60aa4"},"cell_type":"code","source":"learner.fit_one_cycle(6, max_lr=(1e-4, 1e-3, 1e-2), wd=(1e-4, 1e-4, 1e-1))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3a20953db525d6348081329944b3a43a2e7295a7"},"cell_type":"code","source":"learner.unfreeze()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"054f1dd3fcfb6c5e9547be41617e511fbc6da56e"},"cell_type":"code","source":"learner.lr_find()\nlearner.recorder.plot()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"fddd3a3fed456e3399ba49690e780934bf4b00a0"},"cell_type":"code","source":"learner.fit_one_cycle(14, slice(1e-5,1e-4,1e-3))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"5c07718260c0c512acb44a8ee9aaecfe5a3ef21b"},"cell_type":"code","source":"learner.save('stage-1') ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"182bc15258ccf0263639e2046356de1b3e67d140"},"cell_type":"code","source":"learner.recorder.plot_losses()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"361b751829b4d2cb55a5059292b4cb7df0dbc812"},"cell_type":"code","source":"learner.recorder.plot_metrics()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"47fca2ab90884b4e9bd761d2cd34d6c0466dfcf2"},"cell_type":"markdown","source":"##  Confusion Matrix"},{"metadata":{"trusted":true,"_uuid":"d0974852788c43b18f69cf92f2b2884ad2c77d11"},"cell_type":"code","source":"conf= ClassificationInterpretation.from_learner(learner)\nconf.plot_confusion_matrix(figsize=(10,8))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e3c7d99e91a58c2eaf455ce5a431d6aef6615851"},"cell_type":"markdown","source":"## Production "},{"metadata":{"trusted":true,"_uuid":"3fdfb086f4ccf55d4a9e5b190ea7964f340aa33c"},"cell_type":"code","source":"pred_data= ImageDataBunch.from_csv(path, \n                             csv_labels='train_labels.csv', \n                             folder='train', \n                             suffix='.tif',\n                             num_workers=2,\n                             ds_tfms=get_transforms(flip_vert=True, max_warp=0),\n                             bs=64,\n                             test=path/'test').normalize(imagenet_stats)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a6804bcc21d7f3e8c0dbe3b7c3b33c2568ec341a"},"cell_type":"code","source":"classes=[0,1]\npred_data.single_from_classes(path, classes)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6b15ccbd9eaccfb7f3747fde50a3f9915a7eec6d"},"cell_type":"code","source":"predictor=create_cnn(pred_data, models.resnet50, metrics=[accuracy], model_dir=\"/tmp/models/\").load('stage-1')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"816a6e52344e1f4c7c06fe56ea236b12c9016bad"},"cell_type":"code","source":"x,y=pred_data.valid_ds[1]\nx.show()\npred_data.valid_ds.y[1]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"33ec401edc9aa86fe0a938ecad760cdd8d4772e2"},"cell_type":"code","source":"pred_class,pred_idx,outputs = predictor.predict(x)\npred_class","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"44744f0f8a9f3a8e28b20ea7f253dc5a9fca4aeb"},"cell_type":"markdown","source":"# Heatmap"},{"metadata":{"trusted":true,"_uuid":"8c3843960e53d81b528f81115bbffbc180c45fb6"},"cell_type":"code","source":"def heatMap(x,y,data, learner, size=(0,96,96,0)):\n    \"\"\"HeatMap\"\"\"\n    \n    # Evaluation mode\n    m=learner.model.eval()\n    \n    # Denormalize the image\n    xb,_ = data.one_item(x)\n    xb_im = Image(data.denorm(xb)[0])\n    xb = xb.cuda()\n    \n    # hook the activations\n    with hook_output(m[0]) as hook_a: \n        with hook_output(m[0], grad=True) as hook_g:\n            preds = m(xb)\n            preds[0,int(y)].backward()\n\n    # Activations    \n    acts=hook_a.stored[0].cpu()\n    \n    # Avg of the activations\n    avg_acts=acts.mean(0)\n    \n    # Show HeatMap\n    _,ax = plt.subplots()\n    xb_im.show(ax)\n    ax.imshow(avg_acts, alpha=0.6, extent=size,\n              interpolation='bilinear', cmap='magma')\n    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b67e5c4422dc03f1d979bea0fbdd29c0ff044879"},"cell_type":"code","source":"heatMap(x,y,pred_data,learner)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"e965b7ab6543075a39e5e5518f05da4700e90bc5"},"cell_type":"markdown","source":"## Test Prediction"},{"metadata":{"trusted":true,"_uuid":"1f3d56cfbc8f0c2ce178fe603597394d10566de7"},"cell_type":"code","source":"# Predictions of the validation data\npreds_val, y_val=learner.get_preds()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"c30b76e5bed31c75af84c774f833d4f42abdcb4a"},"cell_type":"markdown","source":"### Roc Curve\nWith the ROC curve we will mesuare how good it's our model"},{"metadata":{"trusted":true,"_uuid":"85d1cd1ae0e2fbf58fed78ac9ba59380e418ca1b"},"cell_type":"code","source":"#  ROC curve\nfpr, tpr, thresholds = roc_curve(y_val.numpy(), preds_val.numpy()[:,1], pos_label=1)\n\n#  ROC area\npred_score = auc(fpr, tpr)\nprint(f'ROC area is {pred_score}')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"9df62b19ef617d8380b43f927fff71db63dd771d"},"cell_type":"code","source":"plt.figure()\nplt.plot(fpr, tpr, color='orange', label='ROC curve (area = %0.2f)' % pred_score)\nplt.plot([0, 1], [0, 1], color='navy', linestyle='--')\nplt.xlim([-0.01, 1.0])\nplt.ylim([0.0, 1.01])\nplt.xlabel('False Positive Rate')\nplt.ylabel('True Positive Rate')\nplt.title('Receiver Operating Characteristic')\nplt.legend(loc=\"lower right\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"2e014fdf22769277bcee5c08b8a9c6b448be53a2"},"cell_type":"code","source":"# Predictions on the Test data\npreds_test,y_test = learner.TTA(ds_type=DatasetType.Test)\n# preds_test, y_test=learner.get_preds(ds_type=DatasetType.Test)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d9a01f7bfc5d59cf289bfcccc0c4b79e743cb370"},"cell_type":"markdown","source":"## Submision"},{"metadata":{"trusted":true,"scrolled":true,"_uuid":"72dbd346b5f029e6a6de9a818506206b4f40c764"},"cell_type":"code","source":"sub=pd.read_csv(f'{path}/sample_submission.csv').set_index('id')\nsub.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"0e694ab0e6935b253a17d47f8128e59f077d7ba0"},"cell_type":"code","source":"names=np.vectorize(lambda img_name: str(img_name).split('/')[-1][:-4]) \nfile_names= names(data.test_ds.items).astype(str)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"8b22ea40509bada73364b213e174c1116b8e3f68"},"cell_type":"code","source":"sub.loc[file_names,'label']=preds_test.numpy()[:,1]\nsub.to_csv(f'submission_{pred_score}.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"abd0fd5a8097651c9fc763f0881910df9440abfa","scrolled":true},"cell_type":"code","source":"sub.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d936c28ef74db81301bf4537f75a1ac8ae4aee01"},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}