{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":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 matplotlib.pyplot as plt\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport cv2\nimport tensorflow as tf\n!pip install seaborn\nimport seaborn as sns\n\nfrom sklearn.model_selection import  train_test_split\nfrom sklearn.utils import shuffle\nfrom sklearn.metrics import cohen_kappa_score, accuracy_score\nfrom keras.applications import DenseNet121\nfrom keras import layers\nfrom keras.models import Sequential\nfrom keras.optimizers import Adam\nfrom keras.callbacks import Callback, ModelCheckpoint\nfrom keras.preprocessing.image import ImageDataGenerator\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 the files in the input directory\n\nimport os\nprint(os.listdir(\"../input\"))\n\n\nimg_size = 512   # setting our image size to a standard value \n\n%matplotlib inline\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# **LOADING DATA**"},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"train_df = pd.read_csv('../input/train.csv')\ntest_df = pd.read_csv('../input/test.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# ** EXPLORATORY DATA ANALYSIS **"},{"metadata":{},"cell_type":"markdown","source":"From the information given the 'disagnois' column gives us a rating for 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"},{"metadata":{},"cell_type":"markdown","source":"Lets establish our x and y variable for this dataset"},{"metadata":{"trusted":true},"cell_type":"code","source":"x = train_df['id_code']\ny = train_df['diagnosis']","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"To avoid any bias, we need to reset the data structure each time we run the cell above. We can do this using the shuffle object in the pandas dataframe"},{"metadata":{"trusted":true},"cell_type":"code","source":"seed = 50  # defining the number of seeds in our shuffling \nx, y = shuffle(x, y, random_state=seed)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Splitting Our Training & Testing Datasets"},{"metadata":{"trusted":true},"cell_type":"code","source":"x_train,x_test,y_train,y_test=train_test_split(x, y, test_size=0.2, random_state =seed)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Now we need to do a count to see how many of each type of severity of diabetic retinopothy we have in our training dataset"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df['diagnosis'].value_counts()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"It seems that the majority of the training set is made up of patients that have no DR. Overall, we can see a decrease in counts as we goes up in the the severity of DR\n\nTo better visualize this lets do a simple bar graph visualization "},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df['diagnosis'].value_counts().plot.bar()\n\nplt.title('Visualization of DR Trainig Dataset')\nplt.xlabel('DR Diagnosis Type')\nplt.ylabel('Patient Count')\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# **DISPLAYING SOME CORRECTED SAMPLE IMAGES**"},{"metadata":{},"cell_type":"markdown","source":"The purpose of this function is to display a set of grayscale converted and cropped samples images from the given dataset "},{"metadata":{"trusted":true},"cell_type":"code","source":"def display_train_images(df, col=3, row=3):\n    \n    tol = 30  # initializing our tolerence level for cropping \n\n    matrix = col*row\n    fig = plt.figure(figsize=(10, 10)) #definingthe size of our inline plot from matplotlib \n    \n    for i in range(matrix):\n        \n        image_path = df.loc[i,'id_code']     # assigning the id_code of each eye image to a certain path\n        image_id = df.loc[i,'diagnosis']\n        \n        image = cv2.imread(f'../input/train_images/{image_path}.png')\n        \n        img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # converting images from a RGB format to a grayscale format \n        \n        mask = img>tol\n        img = img[np.ix_(mask.any(1),mask.any(0))]       # converting the images into an adjusted or cropped image\n        \n        img = cv2.resize(img, (img_size, img_size))   # resizing our images all to a single size \n        \n        img=cv2.addWeighted(img, 4, cv2.GaussianBlur(img, (0,0), img_size/10),-4, 128) # creating a guassian blur from the grayscale image \n        \n        fig.add_subplot(row, col, i+1)\n        \n        plt.title(image_id)\n        plt.axis('off')\n        plt.imshow(img,cmap='gray')\n        \n    plt.tight_layout()\n\n    return df","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Displaying Our Training Images"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df = display_train_images(train_df)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Displaying Our Testing Images "},{"metadata":{"trusted":true},"cell_type":"code","source":"def display_test_images(df, col=3, row=3):\n    \n    tol = 30  # initializing our tolerence level for cropping \n\n    matrix = col*row\n    fig = plt.figure(figsize=(10, 10)) #definingthe size of our inline plot from matplotlib \n    \n    for i in range(matrix):\n        \n        image_path = df.loc[i,'id_code']     # assigning the id_code of each eye image to a certain path\n        image = cv2.imread(f'../input/test_images/{image_path}.png')\n        \n        img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # converting images from a RGB format to a grayscale format \n        \n        mask = img>tol\n        img = img[np.ix_(mask.any(1),mask.any(0))]       # converting the images into an adjusted or cropped image\n        \n        img = cv2.resize(img, (img_size, img_size))   # resizing our images all to a single size \n        \n        \n        fig.add_subplot(row, col, i+1)\n        \n        plt.axis('off')\n        plt.imshow(img,cmap='gray')\n        \n    plt.tight_layout()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"display_test_images(test_df)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"As we can see fromthe figure above, the top of each image in the subset shows the type of diagnosis for each patient (from the 0-4 scale) and each image in now converted into a grayscale image, cropped to 512x512 pixel image\n\nSince our tesing images do not have a diagnosis, the numbers are missing from the top of each figure in the subplot "},{"metadata":{},"cell_type":"markdown","source":"## Creating An Image Info Generator "},{"metadata":{"trusted":true},"cell_type":"code","source":"BATCH_SIZE = 32\n\ndef create_datagen():\n    return ImageDataGenerator(\n        zoom_range=0.15,  # set range for random zoom\n        # set mode for filling points outside the input boundaries\n        fill_mode='constant',\n        cval=0.,  # value used for fill_mode = \"constant\"\n        horizontal_flip=True,  # randomly flip images\n        vertical_flip=True,  # randomly flip images\n    )","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# **MODEL TRAINING - DENSENET 121**"},{"metadata":{},"cell_type":"markdown","source":"### Creating A Call back for QWK"},{"metadata":{"trusted":true},"cell_type":"code","source":"class Metrics(Callback):\n    def on_train_begin(self, logs={}):\n        self.val_kappas = []\n\n    def on_epoch_end(self, epoch, logs={}):\n        X_val, y_val = self.validation_data[:2]\n        y_val = y_val.sum(axis=1) - 1\n        \n        y_pred = self.model.predict(X_val) > 0.5\n        y_pred = y_pred.astype(int).sum(axis=1) - 1\n\n        _val_kappa = cohen_kappa_score(\n            y_val,\n            y_pred, \n            weights='quadratic'\n        )\n\n        self.val_kappas.append(_val_kappa)\n\n        print(f\"val_kappa: {_val_kappa:.4f}\")\n        \n        if _val_kappa == max(self.val_kappas):\n            print(\"Validation Kappa has improved. Saving model.\")\n            self.model.save('model.h5')\n\n        return","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"densenet = DenseNet121(\n    weights='imagenet',\n    include_top=False,\n    input_shape=(224,224,3)\n)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Model Architecture Design "},{"metadata":{"trusted":true},"cell_type":"code","source":"def build_model():\n    model = Sequential()\n    model.add(densenet)\n    model.add(layers.GlobalAveragePooling2D())\n    model.add(layers.Dropout(0.5))\n    model.add(layers.Dense(10, activation='sigmoid'))\n    \n    # Compiling the model\n    model.compile(\n        loss='binary_crossentropy',\n        optimizer=Adam(lr=0.00005),\n        metrics=['accuracy']\n    )\n    \n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = build_model()\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"kappa_metrics = Metrics()\n\nhistory = model.fit_generator(\n    data_generator,\n    steps_per_epoch=x_train.shape[0] / BATCH_SIZE,\n    epochs=15,\n    validation_data=(x_val, y_val),\n    callbacks=[kappa_metrics]\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"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.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}