{"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":"# Histopathologic Cancer Detection\n## Identify metastatic tissue in histopathologic scans of lymph node sections","metadata":{"editable":false}},{"cell_type":"markdown","source":"# About the images","metadata":{"editable":false}},{"cell_type":"markdown","source":"#### There are 220,025 training images and 57,456 test images.\n#### The images are 96x96 pixels and are full color.","metadata":{"editable":false}},{"cell_type":"markdown","source":"","metadata":{"editable":false}},{"cell_type":"markdown","source":"# Import Packages","metadata":{"editable":false}},{"cell_type":"code","source":"import os\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport matplotlib.image as mpimg\nimport pandas as pd\nfrom sklearn.model_selection import train_test_split\nimport pickle\nfrom IPython.lib.display import Audio\n\nimport tensorflow as tf\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.models import Sequential, load_model\nfrom tensorflow.keras.layers import *\nfrom tensorflow.keras import backend as K\n\nimport zipfile ","metadata":{"execution":{"iopub.status.busy":"2021-12-11T11:48:43.844629Z","iopub.execute_input":"2021-12-11T11:48:43.854985Z","iopub.status.idle":"2021-12-11T11:48:45.737466Z","shell.execute_reply.started":"2021-12-11T11:48:43.854788Z","shell.execute_reply":"2021-12-11T11:48:45.736663Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Helper Functions","metadata":{"editable":false}},{"cell_type":"code","source":"def merge_history(hlist):\n    history = {}\n    for k in hlist[0].history.keys():\n        history[k] = sum([h.history[k] for h in hlist], [])\n    return history","metadata":{"execution":{"iopub.status.busy":"2021-12-11T11:48:45.738824Z","iopub.execute_input":"2021-12-11T11:48:45.739110Z","iopub.status.idle":"2021-12-11T11:48:45.744864Z","shell.execute_reply.started":"2021-12-11T11:48:45.739073Z","shell.execute_reply":"2021-12-11T11:48:45.744173Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def vis_training(h, start=1):\n    epoch_range = range(start, len(h['loss'])+1)\n    s = slice(start-1, None)\n\n    plt.figure(figsize=[14,4])\n\n    n = int(len(h.keys()) / 2)\n\n    for i in range(n):\n        k = list(h.keys())[i]\n        plt.subplot(1,n,i+1)\n        plt.plot(epoch_range, h[k][s], label='Training')\n        plt.plot(epoch_range, h['val_' + k][s], label='Validation')\n        plt.xlabel('Epoch'); plt.ylabel(k); plt.title(k)\n        plt.grid()\n        plt.legend()\n\n    plt.tight_layout()\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-11T11:48:45.746808Z","iopub.execute_input":"2021-12-11T11:48:45.747378Z","iopub.status.idle":"2021-12-11T11:48:45.757577Z","shell.execute_reply.started":"2021-12-11T11:48:45.747273Z","shell.execute_reply":"2021-12-11T11:48:45.756777Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def play_alarm():\n    framerate = 4410\n    play_time_seconds = 6\n\n    t = np.linspace(0, play_time_seconds, framerate*play_time_seconds)\n    audio_data = (np.sin(2*np.pi*300*t) + np.sin(2*np.pi*240*t)) * np.sin(2*np.pi*t)\n    return Audio(audio_data, rate=framerate, autoplay=True)","metadata":{"execution":{"iopub.status.busy":"2021-12-11T11:48:45.760423Z","iopub.execute_input":"2021-12-11T11:48:45.760706Z","iopub.status.idle":"2021-12-11T11:48:45.768556Z","shell.execute_reply.started":"2021-12-11T11:48:45.760669Z","shell.execute_reply":"2021-12-11T11:48:45.767765Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load and Prepare Data","metadata":{"editable":false}},{"cell_type":"markdown","source":"# Dataframes","metadata":{"editable":false}},{"cell_type":"code","source":"test = pd.read_csv('../input/histopathologic-cancer-detection/sample_submission.csv', dtype=str)\ntrain_full = pd.read_csv('../input/histopathologic-cancer-detection/train_labels.csv', dtype=str)\n\nprint(train_full.shape)\nprint(test.shape)","metadata":{"execution":{"iopub.status.busy":"2021-12-11T11:48:45.779495Z","iopub.execute_input":"2021-12-11T11:48:45.779928Z","iopub.status.idle":"2021-12-11T11:48:46.055683Z","shell.execute_reply.started":"2021-12-11T11:48:45.779868Z","shell.execute_reply":"2021-12-11T11:48:46.054817Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_full.head()","metadata":{"execution":{"iopub.status.busy":"2021-12-11T11:48:46.057079Z","iopub.execute_input":"2021-12-11T11:48:46.057955Z","iopub.status.idle":"2021-12-11T11:48:46.072490Z","shell.execute_reply.started":"2021-12-11T11:48:46.057910Z","shell.execute_reply":"2021-12-11T11:48:46.071506Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test.head()","metadata":{"execution":{"iopub.status.busy":"2021-12-11T11:48:46.073948Z","iopub.execute_input":"2021-12-11T11:48:46.074335Z","iopub.status.idle":"2021-12-11T11:48:46.083285Z","shell.execute_reply.started":"2021-12-11T11:48:46.074293Z","shell.execute_reply":"2021-12-11T11:48:46.082525Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_id = test.id\n\ntrain_full.id = train_full.id + '.tif'\ntest.id = test.id + '.tif'\n\nprint(train_full.head())\nprint(test.head())","metadata":{"execution":{"iopub.status.busy":"2021-12-11T11:48:46.084749Z","iopub.execute_input":"2021-12-11T11:48:46.085285Z","iopub.status.idle":"2021-12-11T11:48:46.150704Z","shell.execute_reply.started":"2021-12-11T11:48:46.085243Z","shell.execute_reply":"2021-12-11T11:48:46.149849Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Label Distribution","metadata":{"editable":false}},{"cell_type":"code","source":"y_train = train_full.label\n\n(train_full.label.value_counts() / len(train_full)).to_frame()","metadata":{"execution":{"iopub.status.busy":"2021-12-11T11:48:46.152948Z","iopub.execute_input":"2021-12-11T11:48:46.153508Z","iopub.status.idle":"2021-12-11T11:48:46.186767Z","shell.execute_reply.started":"2021-12-11T11:48:46.153465Z","shell.execute_reply":"2021-12-11T11:48:46.185819Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('Training Images:', len(os.listdir('../input/histopathologic-cancer-detection/train/')))\n\nfor i in range(10):\n  img = plt.imread('../input/histopathologic-cancer-detection/train/' + train_full.id[i])\n  print('Images shape', img.shape)","metadata":{"execution":{"iopub.status.busy":"2021-12-11T11:48:46.188241Z","iopub.execute_input":"2021-12-11T11:48:46.188523Z","iopub.status.idle":"2021-12-11T11:48:46.407180Z","shell.execute_reply.started":"2021-12-11T11:48:46.188482Z","shell.execute_reply":"2021-12-11T11:48:46.406292Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Number of images in the train and test folder","metadata":{"editable":false}},{"cell_type":"code","source":"print('Number of images in train set',len(os.listdir('../input/histopathologic-cancer-detection/train')))\nprint('Number of images in test set',len(os.listdir('../input/histopathologic-cancer-detection/test')))","metadata":{"execution":{"iopub.status.busy":"2021-12-11T11:48:46.408553Z","iopub.execute_input":"2021-12-11T11:48:46.408929Z","iopub.status.idle":"2021-12-11T11:48:46.615641Z","shell.execute_reply.started":"2021-12-11T11:48:46.408878Z","shell.execute_reply":"2021-12-11T11:48:46.614741Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{"editable":false}},{"cell_type":"markdown","source":"# View Sample of Images","metadata":{"editable":false}},{"cell_type":"code","source":"sample = train_full.sample(n=16).reset_index()\n\nplt.figure(figsize=(8,8))\n\nfor i, row in sample.iterrows():\n\n    img = mpimg.imread(f'../input/histopathologic-cancer-detection/train/{row.id}')    \n    label = row.label\n\n    plt.subplot(4,4,i+1)\n    plt.imshow(img)\n    plt.text(0, -5, f'Class {label}', color='k')\n        \n    plt.axis('off')\n\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-11T11:48:46.619445Z","iopub.execute_input":"2021-12-11T11:48:46.619650Z","iopub.status.idle":"2021-12-11T11:48:47.909797Z","shell.execute_reply.started":"2021-12-11T11:48:46.619623Z","shell.execute_reply":"2021-12-11T11:48:47.908950Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training and Validation Sets","metadata":{"editable":false}},{"cell_type":"code","source":"train, valid = train_test_split(train_full, test_size=0.2, random_state=1, stratify=train_full.label)\n\nprint(train.shape)\nprint(valid.shape)","metadata":{"execution":{"iopub.status.busy":"2021-12-11T11:48:47.916253Z","iopub.execute_input":"2021-12-11T11:48:47.916860Z","iopub.status.idle":"2021-12-11T11:48:48.342410Z","shell.execute_reply.started":"2021-12-11T11:48:47.916818Z","shell.execute_reply":"2021-12-11T11:48:48.341548Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data generators","metadata":{"editable":false}},{"cell_type":"code","source":"train_datagen = ImageDataGenerator(rescale=1/255)\nvalid_datagen = ImageDataGenerator(rescale=1/255)","metadata":{"execution":{"iopub.status.busy":"2021-12-11T11:48:48.343938Z","iopub.execute_input":"2021-12-11T11:48:48.344253Z","iopub.status.idle":"2021-12-11T11:48:48.349553Z","shell.execute_reply.started":"2021-12-11T11:48:48.344210Z","shell.execute_reply":"2021-12-11T11:48:48.348395Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{"editable":false}},{"cell_type":"code","source":"BATCH_SIZE = 64\n\ntrain_loader = train_datagen.flow_from_dataframe(\n    dataframe = train,\n    directory = '../input/histopathologic-cancer-detection/train/',\n    x_col = \"id\",\n    y_col = \"label\",\n    batch_size = BATCH_SIZE,\n    seed = 1,\n    shuffle = True,\n    class_mode = \"categorical\",\n    target_size = (96,96),\n)\n\n\nvalid_loader = valid_datagen.flow_from_dataframe(\n    dataframe = valid,\n    directory = '../input/histopathologic-cancer-detection/train/',\n    x_col = \"id\",\n    y_col = \"label\",\n    batch_size = BATCH_SIZE,\n    seed = 1,\n    shuffle = True,\n    class_mode = \"categorical\",\n    target_size = (96,96))","metadata":{"execution":{"iopub.status.busy":"2021-12-11T11:48:48.351037Z","iopub.execute_input":"2021-12-11T11:48:48.351531Z","iopub.status.idle":"2021-12-11T11:56:50.287528Z","shell.execute_reply.started":"2021-12-11T11:48:48.351489Z","shell.execute_reply":"2021-12-11T11:56:50.285838Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TR_STEPS = len(train_loader)\nVA_STEPS = len(valid_loader)\n\nprint(TR_STEPS)\nprint(VA_STEPS)","metadata":{"execution":{"iopub.status.busy":"2021-12-11T11:56:50.288984Z","iopub.execute_input":"2021-12-11T11:56:50.289242Z","iopub.status.idle":"2021-12-11T11:56:50.294725Z","shell.execute_reply.started":"2021-12-11T11:56:50.289207Z","shell.execute_reply":"2021-12-11T11:56:50.293936Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Build network","metadata":{"editable":false}},{"cell_type":"code","source":"np.random.seed(1)\ntf.random.set_seed(1)\n\ncnn = Sequential([\n    Conv2D(32, (3,3), activation = 'relu', padding = 'same', input_shape=(96,96,3)),\n    BatchNormalization(),\n    Conv2D(32, (3,3), activation = 'relu', padding = 'same'),\n    BatchNormalization(),\n    MaxPooling2D(2,2),\n    Dropout(0.3),\n\n    Conv2D(64, (3,3), activation = 'relu', padding = 'same'),\n    BatchNormalization(),\n    Conv2D(64, (3,3), activation = 'relu', padding = 'same'),\n    BatchNormalization(),\n    MaxPooling2D(2,2),\n    Dropout(0.3),\n    \n    Conv2D(128, (3,3), activation = 'relu', padding = 'same'),\n    BatchNormalization(),\n    Conv2D(128, (3,3), activation = 'relu', padding = 'same'),\n    BatchNormalization(),\n    MaxPooling2D(2,2),\n    Dropout(0.3),\n\n    Flatten(),\n\n    Dense(256, activation='relu'),\n    BatchNormalization(),\n    Dropout(0.5),\n    Dense(2, activation='softmax')\n])\n\ncnn.summary()","metadata":{"execution":{"iopub.status.busy":"2021-12-11T11:56:50.296104Z","iopub.execute_input":"2021-12-11T11:56:50.296350Z","iopub.status.idle":"2021-12-11T11:56:52.884350Z","shell.execute_reply.started":"2021-12-11T11:56:50.296318Z","shell.execute_reply":"2021-12-11T11:56:52.883574Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Train network","metadata":{"editable":false}},{"cell_type":"code","source":"opt = tf.keras.optimizers.Adam(0.001)\ncnn.compile(loss='categorical_crossentropy', optimizer=opt, metrics=['accuracy', tf.keras.metrics.AUC()])","metadata":{"execution":{"iopub.status.busy":"2021-12-11T11:56:52.885515Z","iopub.execute_input":"2021-12-11T11:56:52.886061Z","iopub.status.idle":"2021-12-11T11:56:52.908636Z","shell.execute_reply.started":"2021-12-11T11:56:52.886018Z","shell.execute_reply":"2021-12-11T11:56:52.907918Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time \n\nh1 = cnn.fit(\n    train_loader, \n    steps_per_epoch=TR_STEPS, \n    validation_data=valid_loader, \n    validation_steps=VA_STEPS, \n    epochs = 20,\n    verbose=1, \n    use_multiprocessing=True, \n    workers=8\n)","metadata":{"execution":{"iopub.status.busy":"2021-12-11T11:56:52.909921Z","iopub.execute_input":"2021-12-11T11:56:52.910676Z","iopub.status.idle":"2021-12-11T13:20:13.296202Z","shell.execute_reply.started":"2021-12-11T11:56:52.910632Z","shell.execute_reply":"2021-12-11T13:20:13.295108Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = merge_history([h1])\nvis_training(history)","metadata":{"execution":{"iopub.status.busy":"2021-12-11T13:20:13.302407Z","iopub.execute_input":"2021-12-11T13:20:13.320240Z","iopub.status.idle":"2021-12-11T13:20:14.365527Z","shell.execute_reply.started":"2021-12-11T13:20:13.320179Z","shell.execute_reply":"2021-12-11T13:20:14.364841Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"play_alarm()","metadata":{"execution":{"iopub.status.busy":"2021-12-11T13:20:14.366576Z","iopub.execute_input":"2021-12-11T13:20:14.366925Z","iopub.status.idle":"2021-12-11T13:20:14.384607Z","shell.execute_reply.started":"2021-12-11T13:20:14.366892Z","shell.execute_reply":"2021-12-11T13:20:14.383823Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"K.set_value(cnn.optimizer.learning_rate, 0.0001)","metadata":{"execution":{"iopub.status.busy":"2021-12-11T13:20:14.391776Z","iopub.execute_input":"2021-12-11T13:20:14.392242Z","iopub.status.idle":"2021-12-11T13:20:14.401187Z","shell.execute_reply.started":"2021-12-11T13:20:14.392207Z","shell.execute_reply":"2021-12-11T13:20:14.400414Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time \n\nh2 = cnn.fit(\n    train_loader, \n    steps_per_epoch=TR_STEPS, \n    validation_data=valid_loader, \n    validation_steps=VA_STEPS, \n    epochs = 20,\n    verbose=1, \n    use_multiprocessing=True, \n    workers=8\n)","metadata":{"execution":{"iopub.status.busy":"2021-12-11T13:20:14.402561Z","iopub.execute_input":"2021-12-11T13:20:14.403038Z","iopub.status.idle":"2021-12-11T14:43:33.669765Z","shell.execute_reply.started":"2021-12-11T13:20:14.403003Z","shell.execute_reply":"2021-12-11T14:43:33.668624Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = merge_history([h1, h2])\nvis_training(history)","metadata":{"execution":{"iopub.status.busy":"2021-12-11T14:43:33.672687Z","iopub.execute_input":"2021-12-11T14:43:33.673441Z","iopub.status.idle":"2021-12-11T14:43:34.613502Z","shell.execute_reply.started":"2021-12-11T14:43:33.673383Z","shell.execute_reply":"2021-12-11T14:43:34.612786Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"play_alarm()","metadata":{"execution":{"iopub.status.busy":"2021-12-11T14:43:34.614808Z","iopub.execute_input":"2021-12-11T14:43:34.615213Z","iopub.status.idle":"2021-12-11T14:43:34.627276Z","shell.execute_reply.started":"2021-12-11T14:43:34.615172Z","shell.execute_reply":"2021-12-11T14:43:34.626521Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"K.set_value(cnn.optimizer.learning_rate, 0.00001)","metadata":{"execution":{"iopub.status.busy":"2021-12-11T14:43:34.628477Z","iopub.execute_input":"2021-12-11T14:43:34.629285Z","iopub.status.idle":"2021-12-11T14:43:34.635812Z","shell.execute_reply.started":"2021-12-11T14:43:34.629244Z","shell.execute_reply":"2021-12-11T14:43:34.635076Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time \n\nh3 = cnn.fit(\n    train_loader, \n    steps_per_epoch=TR_STEPS, \n    validation_data=valid_loader, \n    validation_steps=VA_STEPS, \n    epochs = 20,\n    verbose=1, \n    use_multiprocessing=True, \n    workers=8\n)","metadata":{"execution":{"iopub.status.busy":"2021-12-11T14:43:34.637595Z","iopub.execute_input":"2021-12-11T14:43:34.637882Z","iopub.status.idle":"2021-12-11T16:06:07.184583Z","shell.execute_reply.started":"2021-12-11T14:43:34.637846Z","shell.execute_reply":"2021-12-11T16:06:07.183732Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = merge_history([h1, h2, h3])\nvis_training(history)","metadata":{"execution":{"iopub.status.busy":"2021-12-11T16:06:07.186600Z","iopub.execute_input":"2021-12-11T16:06:07.186889Z","iopub.status.idle":"2021-12-11T16:06:07.795173Z","shell.execute_reply.started":"2021-12-11T16:06:07.186847Z","shell.execute_reply":"2021-12-11T16:06:07.794392Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"play_alarm()","metadata":{"execution":{"iopub.status.busy":"2021-12-11T16:06:07.796345Z","iopub.execute_input":"2021-12-11T16:06:07.797202Z","iopub.status.idle":"2021-12-11T16:06:07.809594Z","shell.execute_reply.started":"2021-12-11T16:06:07.797157Z","shell.execute_reply":"2021-12-11T16:06:07.808767Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cnn.save('cancer_model_v01.h5')\npickle.dump(history, open(f'cancer_history_v01.pkl', 'wb'))","metadata":{"execution":{"iopub.status.busy":"2021-12-11T16:18:38.393464Z","iopub.execute_input":"2021-12-11T16:18:38.394317Z","iopub.status.idle":"2021-12-11T16:18:38.559608Z","shell.execute_reply.started":"2021-12-11T16:18:38.394266Z","shell.execute_reply":"2021-12-11T16:18:38.558864Z"},"editable":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{"editable":false}}]}