{"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":"\n<h1 style='background-color:#D3D3D3; font-family:newtimeroman; font-size:200%; text-align:center; border-radius: 15px 50px;' > APTOS Blindness Detection with ResNet152V2 </h1>\n\n<img src=\"https://www.researchgate.net/profile/Ankan-Ghosh-Dastider/publication/347866283/figure/fig2/AS:973637188321282@1609144603815/Architecture-of-the-proposed-classification-network-ResCovNet-ResNet152V2-has-been-used.ppm\" width=\"800px\">\n","metadata":{}},{"cell_type":"markdown","source":"### Files\nIn a synchronous Kernels-only competition, the files you can observe and download will be different than the private test set and sample submission. The files may have different ids, may be a different size, and may vary in other ways, depending on the problem. You should structure your code so that it returns predictions for the public test set images in the format specified by the public sample_submission.csv, but does not hard code aspects like the id or number of rows. When Kaggle runs your Kernel privately, it substitutes the private test set and sample submission in place of the public ones. You can plan on the private test set consisting of 20GB of data across 13,000 images (approximately).\n\n\n<img src=\"https://storage.googleapis.com/kaggle-media/competitions/general/public_vs_private.png\" width=\"700px\">\n\n\n\n\n\n* train.csv - the training labels\n* test.csv - the test set (you must predict the diagnosis value for these variables)\n* sample_submission.csv - a sample submission file in the correct format\n* train.zip - the training set images\n* test.zip - the public test set images\n\n#### Dataset Link \n\n##### [Here](https://www.kaggle.com/c/aptos2019-blindness-detection/data)\n\n\n","metadata":{}},{"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 keras.models import Model\nfrom keras import optimizers, applications\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.callbacks import EarlyStopping, ReduceLROnPlateau\nfrom keras.layers import Dense, Dropout, GlobalAveragePooling2D, Input\nimport tensorflow as tf\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.preprocessing import image_dataset_from_directory\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import InputLayer, BatchNormalization, Dropout, Flatten, Dense, Activation, MaxPool2D, Conv2D\nfrom tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint\nfrom tensorflow.keras.applications.resnet50 import ResNet50\nfrom tensorflow.keras.utils import to_categorical\nfrom keras import optimizers\nfrom tensorflow.keras.optimizers import Adam\nfrom keras.callbacks import Callback,ModelCheckpoint,ReduceLROnPlateau\nfrom keras.models import Sequential,load_model\nfrom keras.layers import Dense, Dropout\nfrom keras.wrappers.scikit_learn import KerasClassifier\nimport keras.backend as K\n#import tensorflow_addons as tfa\n#from tensorflow.keras.metrics import Metric\n#from tensorflow_addons.utils.types import AcceptableDTypes, FloatTensorLike\nfrom typeguard import typechecked\nfrom typing import Optional\n%matplotlib inline\nsns.set(style=\"whitegrid\")\nwarnings.filterwarnings(\"ignore\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-05-22T06:02:39.485613Z","iopub.execute_input":"2021-05-22T06:02:39.486081Z","iopub.status.idle":"2021-05-22T06:02:47.170084Z","shell.execute_reply.started":"2021-05-22T06:02:39.485979Z","shell.execute_reply":"2021-05-22T06:02:47.169067Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = pd.read_csv('../input/aptos2019-blindness-detection/train.csv')\ntest = pd.read_csv('../input/aptos2019-blindness-detection/test.csv')\nsubmission= pd.read_csv('../input/aptos2019-blindness-detection/sample_submission.csv')","metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_kg_hide-input":false,"execution":{"iopub.status.busy":"2021-05-22T06:02:47.171637Z","iopub.execute_input":"2021-05-22T06:02:47.171976Z","iopub.status.idle":"2021-05-22T06:02:47.378299Z","shell.execute_reply.started":"2021-05-22T06:02:47.171942Z","shell.execute_reply":"2021-05-22T06:02:47.376909Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('Number of train samples: ', train.shape[0])\nprint('Number of test samples: ', test.shape[0])\ndisplay(train.head())","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-05-22T06:02:47.380672Z","iopub.execute_input":"2021-05-22T06:02:47.381148Z","iopub.status.idle":"2021-05-22T06:02:47.411354Z","shell.execute_reply.started":"2021-05-22T06:02:47.381106Z","shell.execute_reply":"2021-05-22T06:02:47.410338Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas_profiling as pp\npp.ProfileReport(train)","metadata":{"execution":{"iopub.status.busy":"2021-05-22T06:02:47.412931Z","iopub.execute_input":"2021-05-22T06:02:47.413244Z","iopub.status.idle":"2021-05-22T06:02:51.208736Z","shell.execute_reply.started":"2021-05-22T06:02:47.413211Z","shell.execute_reply":"2021-05-22T06:02:51.207211Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"f, ax = plt.subplots(figsize=(14, 5))\nax = sns.countplot(x=\"diagnosis\", data=train, palette=\"Set2\")\nsns.despine()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-05-22T06:02:51.210661Z","iopub.execute_input":"2021-05-22T06:02:51.211081Z","iopub.status.idle":"2021-05-22T06:02:51.414932Z","shell.execute_reply.started":"2021-05-22T06:02:51.211041Z","shell.execute_reply":"2021-05-22T06:02:51.413220Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sns.set_style(\"white\")\ncount = 1\nplt.figure(figsize=[15, 15])\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()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-05-22T06:02:51.416771Z","iopub.execute_input":"2021-05-22T06:02:51.417138Z","iopub.status.idle":"2021-05-22T06:03:00.774433Z","shell.execute_reply.started":"2021-05-22T06:02:51.417103Z","shell.execute_reply":"2021-05-22T06:03:00.773012Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"N_CLASSES = train['diagnosis'].nunique()\nN_CLASSES","metadata":{"execution":{"iopub.status.busy":"2021-05-22T06:03:00.776246Z","iopub.execute_input":"2021-05-22T06:03:00.776757Z","iopub.status.idle":"2021-05-22T06:03:00.789595Z","shell.execute_reply.started":"2021-05-22T06:03:00.776704Z","shell.execute_reply":"2021-05-22T06:03:00.788229Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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()","metadata":{"execution":{"iopub.status.busy":"2021-05-22T06:03:00.793592Z","iopub.execute_input":"2021-05-22T06:03:00.794089Z","iopub.status.idle":"2021-05-22T06:03:00.821421Z","shell.execute_reply.started":"2021-05-22T06:03:00.794040Z","shell.execute_reply":"2021-05-22T06:03:00.819228Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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=16,\n    class_mode=\"categorical\",\n    target_size=(224, 224),\n    subset='training')\n","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-05-22T06:03:00.823894Z","iopub.execute_input":"2021-05-22T06:03:00.824260Z","iopub.status.idle":"2021-05-22T06:03:08.354564Z","shell.execute_reply.started":"2021-05-22T06:03:00.824228Z","shell.execute_reply":"2021-05-22T06:03:08.352912Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"valid_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=16,\n    class_mode=\"categorical\",    \n    target_size=(224, 224),\n    subset='validation')\n","metadata":{"execution":{"iopub.status.busy":"2021-05-22T06:03:08.355973Z","iopub.execute_input":"2021-05-22T06:03:08.356330Z","iopub.status.idle":"2021-05-22T06:03:09.490634Z","shell.execute_reply.started":"2021-05-22T06:03:08.356296Z","shell.execute_reply":"2021-05-22T06:03:09.489140Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_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=(224, 224),\n        batch_size=16,\n        shuffle=False,\n        class_mode=None)","metadata":{"execution":{"iopub.status.busy":"2021-05-22T06:03:09.491778Z","iopub.execute_input":"2021-05-22T06:03:09.492073Z","iopub.status.idle":"2021-05-22T06:03:11.628924Z","shell.execute_reply.started":"2021-05-22T06:03:09.492043Z","shell.execute_reply":"2021-05-22T06:03:11.628025Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"base_model = tf.keras.applications.ResNet152V2(input_shape=(224,224,3),include_top=False,weights=\"imagenet\")","metadata":{"execution":{"iopub.status.busy":"2021-05-22T06:03:11.630118Z","iopub.execute_input":"2021-05-22T06:03:11.630622Z","iopub.status.idle":"2021-05-22T06:03:25.399513Z","shell.execute_reply.started":"2021-05-22T06:03:11.630590Z","shell.execute_reply":"2021-05-22T06:03:25.398237Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Freezing Layers\n\nfor layer in base_model.layers[:-10]:\n    layer.trainable=False","metadata":{"execution":{"iopub.status.busy":"2021-05-22T06:03:25.402947Z","iopub.execute_input":"2021-05-22T06:03:25.403845Z","iopub.status.idle":"2021-05-22T06:03:25.431665Z","shell.execute_reply.started":"2021-05-22T06:03:25.403787Z","shell.execute_reply":"2021-05-22T06:03:25.430489Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Building Model\n\nmodel=Sequential()\nmodel.add(base_model)\nmodel.add(Dropout(0.5))\nmodel.add(Flatten())\nmodel.add(BatchNormalization())\nmodel.add(Dense(256,kernel_initializer='he_uniform'))\nmodel.add(BatchNormalization())\nmodel.add(Activation('relu'))\nmodel.add(Dropout(0.5))\nmodel.add(Dense(128,kernel_initializer='he_uniform'))\nmodel.add(BatchNormalization())\nmodel.add(Activation('relu'))\nmodel.add(Dropout(0.5))\nmodel.add(Dense(32,kernel_initializer='he_uniform'))\nmodel.add(BatchNormalization())\nmodel.add(Activation('relu'))\nmodel.add(Dense(5,activation='softmax'))","metadata":{"execution":{"iopub.status.busy":"2021-05-22T06:03:25.433097Z","iopub.execute_input":"2021-05-22T06:03:25.433470Z","iopub.status.idle":"2021-05-22T06:03:26.958936Z","shell.execute_reply.started":"2021-05-22T06:03:25.433430Z","shell.execute_reply":"2021-05-22T06:03:26.957309Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Model Summary\n\nmodel.summary()\n","metadata":{"execution":{"iopub.status.busy":"2021-05-22T06:03:26.960894Z","iopub.execute_input":"2021-05-22T06:03:26.961404Z","iopub.status.idle":"2021-05-22T06:03:27.013996Z","shell.execute_reply.started":"2021-05-22T06:03:26.961343Z","shell.execute_reply":"2021-05-22T06:03:27.012799Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.utils import plot_model\nfrom IPython.display import Image\nplot_model(model, to_file='convnet.png', show_shapes=True,show_layer_names=True)\nImage(filename='convnet.png')","metadata":{"execution":{"iopub.status.busy":"2021-05-22T06:03:27.015570Z","iopub.execute_input":"2021-05-22T06:03:27.015921Z","iopub.status.idle":"2021-05-22T06:03:27.883603Z","shell.execute_reply.started":"2021-05-22T06:03:27.015876Z","shell.execute_reply":"2021-05-22T06:03:27.882472Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def f1_score(y_true, y_pred): #taken from old keras source code\n    true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))\n    possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))\n    predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))\n    precision = true_positives / (predicted_positives + K.epsilon())\n    recall = true_positives / (possible_positives + K.epsilon())\n    f1_val = 2*(precision*recall)/(precision+recall+K.epsilon())\n    return f1_val\n","metadata":{"execution":{"iopub.status.busy":"2021-05-22T06:03:27.885346Z","iopub.execute_input":"2021-05-22T06:03:27.885710Z","iopub.status.idle":"2021-05-22T06:03:27.893624Z","shell.execute_reply.started":"2021-05-22T06:03:27.885675Z","shell.execute_reply":"2021-05-22T06:03:27.892367Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"METRICS = [\n      tf.keras.metrics.BinaryAccuracy(name='accuracy'),\n      tf.keras.metrics.Precision(name='precision'),\n      tf.keras.metrics.Recall(name='recall'),  \n      tf.keras.metrics.AUC(name='auc'),\n        f1_score,\n]","metadata":{"execution":{"iopub.status.busy":"2021-05-22T06:03:27.894937Z","iopub.execute_input":"2021-05-22T06:03:27.895261Z","iopub.status.idle":"2021-05-22T06:03:28.095976Z","shell.execute_reply.started":"2021-05-22T06:03:27.895230Z","shell.execute_reply":"2021-05-22T06:03:28.094843Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"lrd = ReduceLROnPlateau(monitor = 'val_loss',patience = 2,verbose = 1,factor = 0.8, min_lr = 1e-6)\n\nmcp = ModelCheckpoint('ResNet152V2.h5')\n\nes = EarlyStopping(verbose=1, patience=2)","metadata":{"execution":{"iopub.status.busy":"2021-05-22T06:03:28.097905Z","iopub.execute_input":"2021-05-22T06:03:28.098425Z","iopub.status.idle":"2021-05-22T06:03:28.103838Z","shell.execute_reply.started":"2021-05-22T06:03:28.098374Z","shell.execute_reply":"2021-05-22T06:03:28.102700Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.compile(optimizer='Adam', loss=\"binary_crossentropy\", metrics=METRICS)","metadata":{"execution":{"iopub.status.busy":"2021-05-22T06:03:28.105789Z","iopub.execute_input":"2021-05-22T06:03:28.106384Z","iopub.status.idle":"2021-05-22T06:03:28.143473Z","shell.execute_reply.started":"2021-05-22T06:03:28.106344Z","shell.execute_reply":"2021-05-22T06:03:28.142444Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"STEP_SIZE_TRAIN = train_generator.n//train_generator.batch_size\nSTEP_SIZE_VALID = valid_generator.n//valid_generator.batch_size","metadata":{"execution":{"iopub.status.busy":"2021-05-22T06:03:28.144778Z","iopub.execute_input":"2021-05-22T06:03:28.145088Z","iopub.status.idle":"2021-05-22T06:03:28.149526Z","shell.execute_reply.started":"2021-05-22T06:03:28.145057Z","shell.execute_reply":"2021-05-22T06:03:28.148375Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(STEP_SIZE_TRAIN)\nprint(STEP_SIZE_VALID)","metadata":{"execution":{"iopub.status.busy":"2021-05-22T06:03:28.151025Z","iopub.execute_input":"2021-05-22T06:03:28.151528Z","iopub.status.idle":"2021-05-22T06:03:28.164934Z","shell.execute_reply.started":"2021-05-22T06:03:28.151490Z","shell.execute_reply":"2021-05-22T06:03:28.163443Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%time\nhistory = model.fit_generator(generator=train_generator,steps_per_epoch=STEP_SIZE_TRAIN,validation_data=valid_generator,validation_steps=STEP_SIZE_VALID,epochs=10,callbacks=[lrd,mcp,es])","metadata":{"execution":{"iopub.status.busy":"2021-05-22T06:03:28.169686Z","iopub.execute_input":"2021-05-22T06:03:28.170042Z","iopub.status.idle":"2021-05-22T07:51:52.535363Z","shell.execute_reply.started":"2021-05-22T06:03:28.170014Z","shell.execute_reply":"2021-05-22T07:51:52.529220Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"complete_datagen = ImageDataGenerator(rescale=1./255)\ncomplete_generator = complete_datagen.flow_from_dataframe(  \n        dataframe=train,\n        directory = \"../input/aptos2019-blindness-detection/train_images/\",\n        x_col=\"id_code\",\n        target_size=(224, 224),\n        batch_size=1,\n        shuffle=False,\n        class_mode=None)","metadata":{"execution":{"iopub.status.busy":"2021-05-22T07:51:52.547565Z","iopub.execute_input":"2021-05-22T07:51:52.548748Z","iopub.status.idle":"2021-05-22T07:51:54.831522Z","shell.execute_reply.started":"2021-05-22T07:51:52.548680Z","shell.execute_reply":"2021-05-22T07:51:54.830161Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"STEP_SIZE_COMPLETE = complete_generator.n//complete_generator.batch_size\ntrain_preds = model.predict_generator(complete_generator, steps=STEP_SIZE_COMPLETE)\ntrain_preds = [np.argmax(pred) for pred in train_preds]","metadata":{"execution":{"iopub.status.busy":"2021-05-22T07:51:54.833143Z","iopub.execute_input":"2021-05-22T07:51:54.833831Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels = ['0 - No DR', '1 - Mild', '2 - Moderate', '3 - Severe', '4 - Proliferative DR']\ncnf_matrix = confusion_matrix(train['diagnosis'].astype('int'), train_preds)\ncnf_matrix_norm = cnf_matrix.astype('float') / cnf_matrix.sum(axis=1)[:, np.newaxis]\ndf_cm = pd.DataFrame(cnf_matrix_norm, index=labels, columns=labels)\nprint(df_cm.describe().T)\nplt.figure(figsize=(15, 8))\nsns.heatmap(df_cm, annot=True, fmt='.2f')\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_cm.head(5)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Train Cohen Kappa score: %.3f\" % cohen_kappa_score(train_preds, train['diagnosis'].astype('int'), weights='quadratic'))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_generator.reset()\nSTEP_SIZE_TEST = test_generator.n//test_generator.batch_size\npreds = model.predict_generator(test_generator, steps=STEP_SIZE_TEST)\npredictions = [np.argmax(pred) for pred in preds]\npredictions[:10]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"filenames = test_generator.filenames\nresults = pd.DataFrame(['id_code',filenames, 'diagnosis',predictions])\nresults.to_csv('submission.csv',index=False)\nresults.head(5).T","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}