{"cells":[{"metadata":{},"cell_type":"markdown","source":"# APTOS 2019 Blindness Detection\n\n### Dataset Description\nYou are provided with a large set of retina images taken using fundus photography under a variety of imaging conditions.\n\nA clinician has rated each image for the severity of diabetic retinopathy on a scale of 0 to 4:\n\n0 - No DR\n\n1 - Mild\n\n2 - Moderate\n\n3 - Severe\n\n4 - Proliferative DR\n\nLike any real-world data set, you will encounter noise in both the images and labels. Images may contain artifacts, be out of focus, underexposed, or overexposed. The images were gathered from multiple clinics using a variety of cameras over an extended period of time, which will introduce further variation."},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"_kg_hide-output":true,"_kg_hide-input":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load in \n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"import os\nimport cv2\nimport random\nimport warnings\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom sklearn.metrics import confusion_matrix, cohen_kappa_score\nfrom sklearn.metrics import confusion_matrix\n\n\nimport keras.backend as K\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.preprocessing import image\nfrom keras.models import Model\nfrom keras.layers import Input, Dense, Dropout\nfrom keras.applications.inception_v3 import InceptionV3\nfrom keras.applications.inception_v3 import preprocess_input, decode_predictions","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"train = pd.read_csv('../input/aptos2019-blindness-detection/train.csv')\ntest = pd.read_csv('../input/aptos2019-blindness-detection/test.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Number of train samples: ', train.shape[0])\nprint('Number of test samples: ', test.shape[0])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sns.set_style(\"white\")\ncount = 1\nplt.figure(figsize=[20, 20])\nfor img_name in train['id_code'][:15]:\n    img = cv2.imread(\"../input/aptos2019-blindness-detection/train_images/%s.png\" % img_name)[...,[2, 1, 0]]\n    plt.subplot(5, 5, count)\n    plt.imshow(img)\n    plt.title(\"Image %s\" % count)\n    count += 1\n    \nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train['diagnosis'].value_counts().sort_index().plot(kind=\"bar\", \n                                                       figsize=(12,5), \n                                                       rot=0)\nplt.title(\"Label Distribution (Training Set)\", \n          weight='bold', \n          fontsize=18)\nplt.xticks(fontsize=15)\nplt.yticks(fontsize=15)\nplt.xlabel(\"Label\", fontsize=17)\nplt.ylabel(\"Frequency\", fontsize=17);","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Preprocecss data\ntrain[\"id_code\"] = train[\"id_code\"].apply(lambda x: x + \".png\")\ntest[\"id_code\"] = test[\"id_code\"].apply(lambda x: x + \".png\")\ntrain['diagnosis'] = train['diagnosis'].astype('str')\ntrain.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Model parameters\nBATCH_SIZE = 8\nEPOCHS = 20\nWARMUP_EPOCHS = 2\nLEARNING_RATE = 1e-4\nWARMUP_LEARNING_RATE = 1e-3\nHEIGHT = 512\nWIDTH = 512\nCANAL = 3\nN_CLASSES = train['diagnosis'].nunique()\nES_PATIENCE = 5\nRLROP_PATIENCE = 3\nDECAY_DROP = 0.5","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_datagen=ImageDataGenerator(rescale=1./255, \n                                 validation_split=0.2,\n                                 horizontal_flip=True)\n\ntrain_generator=train_datagen.flow_from_dataframe(\n    dataframe=train,\n    directory=\"../input/aptos2019-blindness-detection/train_images/\",\n    x_col=\"id_code\",\n    y_col=\"diagnosis\",\n    batch_size=BATCH_SIZE,\n    class_mode=\"categorical\",\n    target_size=(HEIGHT, WIDTH),\n    subset='training')\n\nvalid_generator=train_datagen.flow_from_dataframe(\n    dataframe=train,\n    directory=\"../input/aptos2019-blindness-detection/train_images/\",\n    x_col=\"id_code\",\n    y_col=\"diagnosis\",\n    batch_size=BATCH_SIZE,\n    class_mode=\"categorical\",    \n    target_size=(HEIGHT, WIDTH),\n    subset='validation')\n\ntest_datagen = ImageDataGenerator(rescale=1./255)\n\ntest_generator = test_datagen.flow_from_dataframe(  \n        dataframe=test,\n        directory = \"../input/aptos2019-blindness-detection/test_images/\",\n        x_col=\"id_code\",\n        target_size=(HEIGHT, WIDTH),\n        batch_size=1,\n        shuffle=False,\n        class_mode=None)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-output":true},"cell_type":"code","source":"inp = Input((HEIGHT, WIDTH, CANAL))\ninception = InceptionV3(include_top=False, weights='imagenet', input_tensor=inp, input_shape=(HEIGHT, WIDTH, CANAL), pooling='avg')\nx = inception.output\nx = Dense(256, activation='relu')(x)\nx = Dropout(0.1)(x)\nout = Dense(5, activation='softmax')(x)\n\ncomplete_model = Model(inp, out)\n\ncomplete_model.compile(optimizer='adam', loss='categorical_crossentropy')\ncomplete_model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Running the model using the fit_generater method for 10 epochs\nhistory = complete_model.fit_generator(train_generator, steps_per_epoch=115, epochs=10, validation_data=valid_generator, validation_steps=20, verbose=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Taking the outputs of first 100 layers from trained model, leaving the first Input layer, in a list\nlayer_outputs = [layer.output for layer in complete_model.layers[1:100]]\n\n# This is image of a Rose flower from our dataset. All of the visualizations in this cell are of this image.\ntest_image = \"../input/aptos2019-blindness-detection/test_images/021c207614d6.png\"\n\n# Loading the image and converting it to a numpy array for feeding it to the model. Its important to use expand_dims since our original model takes batches of images\n# as input, and here we are feeding a single image to it, so the number of dimensions should match for model input.\nimg = image.load_img(test_image, target_size=(512, 512))\nimg_arr = image.img_to_array(img)\nimg_arr = np.expand_dims(img_arr, axis=0)\nimg_arr /= 255.\n\n# Defining a new model using original model's input and all the 100 layers outputs and then predicting the values for all those 100 layers for our test image.\nactivation_model = Model(inputs=complete_model.input, outputs=layer_outputs)\nactivations = activation_model.predict(img_arr)\n\n# These are names of layers, the outputs of which we are going to visualize.\nlayer_names = ['conv2d_1', 'activation_1', 'conv2d_4', 'activation_4', 'conv2d_9', 'activation_9']\nactiv_list = [activations[0], activations[2], activations[10], activations[12], activations[17], activations[19]]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Visualization of the activation maps from first convolution layer. Different filters activate different parts of the image, like some are detecting edges, some are\n# detecting background, while others are detecting just the outer boundary of the flower and so on.\nfig = plt.figure(figsize=(22, 3))\nfor img in range(30):\n    ax = fig.add_subplot(2, 15, img+1)\n    ax = plt.imshow(activations[0][0, :, :, img], cmap='gray')\n    plt.xticks([])\n    plt.yticks([])\n    fig.subplots_adjust(wspace=0.05, hspace=0.05)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# This is the visualization of activation maps from third convolution layer. In this layer the abstraction has increased. Filters are now able to regognise the edges\n# of the flower more closely. Some filters are activating the surface texture of the image as well\nfig = plt.figure(figsize=(22, 6))\nfor img in range(60):\n    ax = fig.add_subplot(4, 15, img+1)\n    ax = plt.imshow(activations[6][0, :, :, img], cmap='gray')\n    plt.xticks([])\n    plt.yticks([])\n    fig.subplots_adjust(wspace=0.05, hspace=0.05)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# These are activation maps from fourth convolution layer. The images have become a little blurry, because of the MaxPooling operation done just before this layer. As\n# more Pooling layers are introduced the knowledge reaching the convolution layer becomes more and more abstract, which helps the complete network to finally classify\n# the image properly, but visually they don't provide us with much information.\nfig = plt.figure(figsize=(22, 6))\nfor img in range(60):\n    ax = fig.add_subplot(4, 15, img+1)\n    ax = plt.imshow(activations[10][0, :, :, img], cmap='gray')\n    plt.xticks([])\n    plt.yticks([])\n    fig.subplots_adjust(wspace=0.05, hspace=0.05)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# These are the activation maps from next convolution layer after next MaPooling layer. The images have become more blurry\nfig = plt.figure(figsize=(22, 6))\nfor img in range(60):\n    ax = fig.add_subplot(4, 15, img+1)\n    ax = plt.imshow(activations[17][0, :, :, img], cmap='gray')\n    plt.xticks([])\n    plt.yticks([])\n    fig.subplots_adjust(wspace=0.05, hspace=0.05)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Activation maps from first Concatenate layer Mixed0, which concatenates the ReLU activated outputs from four convolution layers.\nfig = plt.figure(figsize=(22, 6))\nfor img in range(60):\n    ax = fig.add_subplot(4, 15, img+1)\n    ax = plt.imshow(activations[39][0, :, :, img], cmap='plasma')\n    plt.xticks([])\n    plt.yticks([])\n    fig.subplots_adjust(wspace=0.05, hspace=0.05)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Visualizing Filter Patterns of Convolution layers\n> The basic idea of the code is to apply Gradient Ascent in input space i.e., applying Gradient Descent to the value of the input image of a convnet so as to maximize the response of a specific filter, starting with a blank input image. The resulting input image will be the pattern to which the chosen filter is maximally responsive to. I do this by calling the function generate_pattern and a helper function deprocess_image, working of each is explained in their respective cells.\n\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"def deprocess_image(x):\n    \n    x -= x.mean()\n    x /= (x.std() + 1e-5)\n    x *= 0.1\n    x += 0.5\n    x = np.clip(x, 0, 1)\n    x *= 255\n    x = np.clip(x, 0, 255).astype('uint8')\n\n    return x","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def generate_pattern(layer_name, filter_index, size=150):\n    \n    layer_output = complete_model.get_layer(layer_name).output\n    loss = K.mean(layer_output[:, :, :, filter_index])\n    grads = K.gradients(loss, complete_model.input)[0]\n    grads /= (K.sqrt(K.mean(K.square(grads))) + 1e-5)\n    iterate = K.function([complete_model.input], [loss, grads])\n    input_img_data = np.random.random((1, size, size, 3)) * 20 + 128.\n    step = 1.\n    for i in range(80):\n        loss_value, grads_value = iterate([input_img_data])\n        input_img_data += grads_value * step\n        \n    img = input_img_data[0]\n    return deprocess_image(img)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Below are the patterns to which the filters from first convolution layer get activated. As we can see these are very basic cross-sectional patterns formed by\n# horizontal and vertical lines, which is what the these filters look in the input image and get activated if they find one\nfig = plt.figure(figsize=(15, 12))\nfor img in range(30):\n    ax = fig.add_subplot(5, 6, img+1)\n    ax = plt.imshow(generate_pattern('conv2d_1', img))\n    plt.xticks([])\n    plt.yticks([])\n    fig.subplots_adjust(wspace=0.05, hspace=0.05)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"markdown","source":"> Here are patterns to which filters from third convolution layer respond to. These patterns are liitle more abstract than the simple cross-sectional patterns we saw for first layer. This tells us that this layer is looking for more deeper and complex patterns than the earlier convolutional layer.\n"},{"metadata":{},"cell_type":"markdown","source":""},{"metadata":{"trusted":true},"cell_type":"code","source":"img_path = \"../input/aptos2019-blindness-detection/test_images/021c207614d6.png\"\n\nimg = image.load_img(img_path, target_size=(512, 512))\nx = image.img_to_array(img)\nx = np.expand_dims(x, axis=0)\nx = preprocess_input(x)\n\npreds = complete_model.predict(x)\npreds","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"flower_output = complete_model.output[:, 0]\nlast_conv_layer = complete_model.get_layer('mixed10')\n\ngrads = K.gradients(flower_output, last_conv_layer.output)[0]                               # Gradient of output with respect to 'mixed10' layer\npooled_grads = K.mean(grads, axis=(0, 1, 2))                                                # Vector of size (2048,), where each entry is mean intensity of\n                                                                                            # gradient over a specific feature-map channel\niterate = K.function([complete_model.input], [pooled_grads, last_conv_layer.output[0]])\npooled_grads_value, conv_layer_output_value = iterate([x])\n\n#2048 is the number of filters/channels in 'mixed10' layer\nfor i in range(2048):                                                                       # Multiplies each channel in feature-map array by \"how important this\n        conv_layer_output_value[:, :, i] *= pooled_grads_value[i]                           # channel is\" with regard to the class\n        \nheatmap = np.mean(conv_layer_output_value, axis=-1)\nheatmap = np.maximum(heatmap, 0)                                                            # Following two lines just normalize heatmap between 0 and 1\nheatmap /= np.max(heatmap)\n\nplt.imshow(heatmap)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"img = plt.imread(img_path)\nextent = 0, 300, 0, 300\nfig = plt.Figure(frameon=False)\n\nimg1 = plt.imshow(img, extent=extent)\nimg2 = plt.imshow(heatmap, cmap='viridis', alpha=0.4, extent=extent)\n\nplt.xticks([])\nplt.yticks([])\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"##### To be Continued Folks....................."}],"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":4}