{"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 numpy as np\nimport matplotlib.pyplot as plt\nimport matplotlib.image as mpimg\nimport pandas as pd\nimport pickle\nimport cv2\nfrom tqdm import tqdm \nimport matplotlib as mpl\n\nfrom sklearn.model_selection import train_test_split\n\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras.models import Sequential, load_model\nfrom tensorflow.keras.layers import *\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-12-09T19:23:07.680210Z","iopub.execute_input":"2021-12-09T19:23:07.680800Z","iopub.status.idle":"2021-12-09T19:23:07.687341Z","shell.execute_reply.started":"2021-12-09T19:23:07.680760Z","shell.execute_reply":"2021-12-09T19:23:07.686448Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = pd.read_csv(f'../input/histopathologic-cancer-detection/train_labels.csv', dtype=str)\nprint('Training Set Size:', train.shape)\ntrain.head()","metadata":{"execution":{"iopub.status.busy":"2021-12-09T19:23:07.689248Z","iopub.execute_input":"2021-12-09T19:23:07.689846Z","iopub.status.idle":"2021-12-09T19:23:07.955946Z","shell.execute_reply.started":"2021-12-09T19:23:07.689800Z","shell.execute_reply":"2021-12-09T19:23:07.955101Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train['id'] = train['id'].apply(lambda x: f'{x}.tif')\ntrain.head()","metadata":{"execution":{"iopub.status.busy":"2021-12-09T19:23:39.000456Z","iopub.execute_input":"2021-12-09T19:23:39.001386Z","iopub.status.idle":"2021-12-09T19:23:39.102473Z","shell.execute_reply.started":"2021-12-09T19:23:39.001348Z","shell.execute_reply":"2021-12-09T19:23:39.101828Z"},"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.id[i])\n  print('Images shape', img.shape)","metadata":{"execution":{"iopub.status.busy":"2021-12-09T19:23:42.293980Z","iopub.execute_input":"2021-12-09T19:23:42.294706Z","iopub.status.idle":"2021-12-09T19:23:42.513860Z","shell.execute_reply.started":"2021-12-09T19:23:42.294664Z","shell.execute_reply":"2021-12-09T19:23:42.512881Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_path = \"../input/histopathologic-cancer-detection/train\"\nprint('Training Images:', len(os.listdir(train_path)))\n\nsample = train.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-09T19:24:33.693495Z","iopub.execute_input":"2021-12-09T19:24:33.694268Z","iopub.status.idle":"2021-12-09T19:24:34.972029Z","shell.execute_reply.started":"2021-12-09T19:24:33.694215Z","shell.execute_reply":"2021-12-09T19:24:34.971136Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cnn = keras.models.load_model('../input/cancer-detection-models/cancer_detection_model_v22.h5')\n\ncnn.summary()","metadata":{"execution":{"iopub.status.busy":"2021-12-09T19:23:08.212031Z","iopub.status.idle":"2021-12-09T19:23:08.212520Z","shell.execute_reply.started":"2021-12-09T19:23:08.212252Z","shell.execute_reply":"2021-12-09T19:23:08.212278Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#cnn2 = keras.models.load_model('../input/cancer-models/cancer_model_v02_ResNet50V2.h5')\n#cnn2.summary()","metadata":{"execution":{"iopub.status.busy":"2021-12-09T19:23:08.213906Z","iopub.status.idle":"2021-12-09T19:23:08.214361Z","shell.execute_reply.started":"2021-12-09T19:23:08.214109Z","shell.execute_reply":"2021-12-09T19:23:08.214133Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Heatmap Functions\n","metadata":{}},{"cell_type":"markdown","source":"In the cell below we create the two functions that will be used to generate the heatmaps.\n\nThe function create_grad_model() is used to create a \"gradient model\" from our CNN. It needs to be called only once.\nThe function compute_heatmap() returns a numpy array representing the heatmap for a single image.","metadata":{}},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"def create_grad_model(model):\n    for layer in reversed(model.layers):\n        if len(layer.output_shape) == 4:\n            last_conv_layer = layer.name\n            break\n\n    grad_model = tf.keras.models.Model(\n        inputs=[model.inputs],\n        outputs=[model.get_layer(last_conv_layer).output, model.output])\n    \n    return grad_model \n\ndef compute_heatmap(image, class_ix, grad_model):\n\n    with tf.GradientTape() as tape:\n        inputs = tf.cast(image, tf.float32)\n        (conv_outputs, predictions) = grad_model(inputs)\n        loss = predictions[:, class_ix]\n    grads = tape.gradient(loss, conv_outputs)\n\n    cast_conv_outputs = tf.cast(conv_outputs > 0, \"float32\")\n    cast_grads = tf.cast(grads > 0, \"float32\")\n    guided_grads = cast_conv_outputs * cast_grads * grads\n\n    conv_outputs = conv_outputs[0]\n    guided_grads = guided_grads[0]\n\n    weights = tf.reduce_mean(guided_grads, axis=(0, 1))\n\n    cam = tf.reduce_sum(tf.multiply(weights, conv_outputs), axis=-1)\n\n    (w, h) = (image.shape[2], image.shape[1])\n    heatmap = cv2.resize(cam.numpy(), (w, h))\n        \n    return heatmap","metadata":{"execution":{"iopub.status.busy":"2021-12-09T19:23:08.216209Z","iopub.status.idle":"2021-12-09T19:23:08.216690Z","shell.execute_reply.started":"2021-12-09T19:23:08.216443Z","shell.execute_reply":"2021-12-09T19:23:08.216468Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Example: First Heatmap","metadata":{}},{"cell_type":"code","source":"gm = create_grad_model(cnn)\n# g2m = create_grad_model(cnn2)\n\n# Select Image and Create Heatmap\nfilename = train.id[0]\nimg = mpimg.imread(f'../input/histopathologic-cancer-detection/train/{filename}')       \ntensor = img.reshape(-1,32,32,3) / 255\nheatmap = compute_heatmap(tensor, 1, gm)\n\nplt.figure(figsize=[9,3])\n\n# Display Image\nplt.subplot(1,3,1)\nplt.imshow(img)\nplt.axis('off')\n\n# Display Heatmap\nplt.subplot(1,3,2)\nplt.imshow(heatmap, cmap='coolwarm')\nplt.axis('off')\n\n# Display Image and Heatmap Together\nplt.subplot(1,3,3)\nplt.imshow(img, alpha=0.8, cmap='binary_r')\nplt.imshow(heatmap, alpha=0.6, cmap='coolwarm')\nplt.axis('off')\n    \nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-09T19:23:08.217777Z","iopub.status.idle":"2021-12-09T19:23:08.218238Z","shell.execute_reply.started":"2021-12-09T19:23:08.217977Z","shell.execute_reply":"2021-12-09T19:23:08.218001Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_heatmap_dist(df, class_ix, gm):\n\n    values = None\n    for i, row in tqdm(df.iterrows()):\n        img = mpimg.imread(f'../input/histopathologic-cancer-detection/train/{row.id}')    \n        tensor = img.reshape(-1,32,32,3) / 255\n        hm = compute_heatmap(tensor, class_ix, gm)\n\n        if values is None:\n            values = hm.flatten()\n        else:\n            values = np.hstack([values, hm.flatten()])\n\n    return values","metadata":{"execution":{"iopub.status.busy":"2021-12-09T19:23:08.219713Z","iopub.status.idle":"2021-12-09T19:23:08.220147Z","shell.execute_reply.started":"2021-12-09T19:23:08.219904Z","shell.execute_reply":"2021-12-09T19:23:08.219928Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"values = get_heatmap_dist(train.sample(1000, random_state=1), 1, gm)","metadata":{"execution":{"iopub.status.busy":"2021-12-09T19:23:08.221550Z","iopub.status.idle":"2021-12-09T19:23:08.222016Z","shell.execute_reply.started":"2021-12-09T19:23:08.221767Z","shell.execute_reply":"2021-12-09T19:23:08.221792Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"low = np.quantile(values, 0.10)\nhigh = np.quantile(values, 0.96)\n\nnorm = mpl.colors.Normalize(vmin=low, vmax=high)\n\nprint(low)\nprint(high)","metadata":{"execution":{"iopub.status.busy":"2021-12-09T19:23:08.223037Z","iopub.status.idle":"2021-12-09T19:23:08.223547Z","shell.execute_reply.started":"2021-12-09T19:23:08.223258Z","shell.execute_reply":"2021-12-09T19:23:08.223281Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Select which images to display\nindices = range(12)\n\nfor i in indices:  \n    row = train.iloc[i,:]\n    img = mpimg.imread(f'../input/histopathologic-cancer-detection/train/{row.id}')    \n    label = row.label\n    \n    tensor = img.reshape(-1,32,32,3) / 255\n    heatmap = compute_heatmap(tensor, 1, gm)\n\n    if(label == '1'):\n        print('Malignant (Has Cancer)')\n    else:\n        print('Benign (No Cancer)')\n    \n    plt.figure(figsize=[9,3])\n\n    plt.subplot(1,3,1)\n    plt.imshow(img)\n    plt.axis('off')\n\n    plt.subplot(1,3,2)\n    plt.imshow(heatmap, cmap='coolwarm', norm=norm)\n    plt.axis('off')\n\n    plt.subplot(1,3,3)\n    plt.imshow(img, alpha=0.6, cmap='binary_r')\n    plt.imshow(heatmap, alpha=0.6, cmap='coolwarm', norm=norm)\n    plt.axis('off')\n    \n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-09T19:23:08.226117Z","iopub.status.idle":"2021-12-09T19:23:08.226644Z","shell.execute_reply.started":"2021-12-09T19:23:08.226338Z","shell.execute_reply":"2021-12-09T19:23:08.226365Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}