{"cells":[{"metadata":{},"cell_type":"markdown","source":"**Importing Liberaries**\nImporting al the required liberaries for the project"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import json\nimport math\nimport os\nimport scipy\nimport numpy as np\nimport pandas as pd\nimport tensorflow as tf\nfrom tqdm import tqdm\nfrom PIL import Image\nfrom keras import layers\nfrom keras.applications import DenseNet121\nfrom keras.callbacks import Callback, ModelCheckpoint\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.models import Sequential\nfrom keras.optimizers import Adam\nimport matplotlib.pyplot as plt\nimport cv2\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import cohen_kappa_score, accuracy_score\nfrom imblearn.over_sampling import SMOTE\nimport keras.backend as K\nfrom keras.applications.densenet import DenseNet121\nfrom keras.callbacks import Callback, EarlyStopping, ReduceLROnPlateau\nimport seaborn as sns\nsns.set()\nimport warnings\n%matplotlib inline\nwarnings.filterwarnings('ignore')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"epochs = 100\nbatch_size = 6\nimg_size=224\nseed = 999\nlearning_rate = 0.00001","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"np.random.seed(seed)\ntf.set_random_seed(seed)\n\ntrain_df = pd.read_csv('../input/aptos2019-blindness-detection/train.csv')\ntest_df = pd.read_csv('../input/aptos2019-blindness-detection/test.csv')\n\nprint ('Training data shape', train_df.shape)\nprint ('Testing data shape', test_df.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df['diagnosis'].value_counts().sort_index().plot(kind=\"bar\",figsize=(12,5))\nplt.title(\"Distribution\", weight='bold',fontsize=12)\nplt.xticks(fontsize=12)\nplt.yticks(fontsize=12)\nplt.xlabel(\"Label\", fontsize=17)\nplt.ylabel(\"Frequency\", fontsize=17);","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fig, ax = plt.subplots(1, 5, figsize=(30, 12))\nfor i in range(5):\n    sample = train_df[train_df['diagnosis'] == i].sample(1) #.sample(frac=1) will extract single element\n    image_name = sample['id_code'].item()\n    X = cv2.imread(f'../input/aptos2019-blindness-detection/train_images/{image_name}.png')\n    X = cv2.cvtColor(X, cv2.COLOR_BGR2RGB)\n    ax[i].set_title(f\"Image: {image_name}\\n Label = {sample['diagnosis'].item()}\",fontsize=25)\n    ax[i].axis('off')\n    ax[i].imshow(X)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\ndef crop_image(img,tol=7):\n    if img.ndim ==2:\n        print('nadim =2')\n        mask = img>tol\n        print('nadim =2 mask =',mask)\n        return img[np.ix_(mask.any(1),mask.any(0))]\n    elif img.ndim==3:\n        print('nadim =3')\n        gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)\n        mask = gray_img>tol\n        print('nadim =3 mask =',mask)\n        check_shape = img[:,:,0][np.ix_(mask.any(1),mask.any(0))].shape[0]\n        print('check shape =',check_shape)\n        if (check_shape == 0): \n            print('check shape 0 returned ')\n            return img \n        else:\n            img1=img[:,:,0][np.ix_(mask.any(1),mask.any(0))]\n            print('img1')\n            img2=img[:,:,1][np.ix_(mask.any(1),mask.any(0))]\n            print('img2')\n            img3=img[:,:,2][np.ix_(mask.any(1),mask.any(0))]\n            print('img3')\n            img = np.stack([img1,img2,img3],axis=-1)\n            print('img shape=',img.shape)\n        return img\n    \ndef load_ben_color(path, sigmaX=10):\n    image = cv2.imread(path)\n    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n    image = cv2.resize(image, (224, 224))\n    image=cv2.addWeighted ( image,4, cv2.GaussianBlur( image , (0,0) , sigmaX) ,-4 ,128)\n    return image\n\ndef preprocess_image(image_path, desired_size=224):\n    # Add Lighting, to improve quality\n    im = load_ben_color(image_path)\n    return im\n\ndef under_sample_make_all_same(df, categories, max_per_category):\n    df = pd.concat([df[df['diagnosis'] == c][:max_per_category] for c in categories])\n    df = df.sample(n=(max_per_category)*len(categories), replace=False, random_state=20031976)\n    df.index = np.arange(len(df))\n    return df\n\ndef circle_crop(img):   \n    height, width, depth = img.shape    \n    x = int(width/2)\n    y = int(height/2)\n    r = np.amin((x,y))\n    cropped_img = np.zeros((height, width), np.uint8)\n    cv2.circle(cropped_img, (x,y), int(r), 1, thickness=-1)\n    img = cv2.bitwise_and(img, img, mask=cropped_img)\n    img = crop_image(img)\n    return img \n\nprint('Training dataset shape now:',train_df.shape)\n\ntrain_df = train_df.drop(train_df[train_df['diagnosis'] == 0].sample(n=805, replace=False).index)\n\nN = train_df.shape[0]\nx_train = np.empty((N, 224, 224, 3), dtype=np.uint8)\n\nfor i, image_id in enumerate((train_df['id_code'])):\n    x_train[i, :, :, :] = preprocess_image(f'../input/aptos2019-blindness-detection/train_images/{image_id}.png')\n\nN = test_df.shape[0]\nx_test = np.empty((N, 224, 224, 3), dtype=np.uint8)\n\nfor i, image_id in enumerate((test_df['id_code'])):\n    x_test[i, :, :, :] = preprocess_image(f'../input/aptos2019-blindness-detection/test_images/{image_id}.png')\n    \ny_train = pd.get_dummies(train_df['diagnosis']).values","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# View the sample pre-processed images here\nfig=plt.figure(figsize=(20, 10))\nplt.title('Sample Img')\nplt.imshow(x_train[0])\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"circle_crop_img = circle_crop(x_train[1])\nfig=plt.figure(figsize=(20, 10))\nplt.title('Sample Img')\nplt.imshow(circle_crop_img)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(\"x_train.shape=\",x_train.shape)\nprint(\"y_train.shape=\",y_train.shape)\nprint(\"x_test.shape=\",x_test.shape)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"x_samples, y_samples = SMOTE(random_state=seed).fit_sample(x_train.reshape(x_train.shape[0], -1), train_df['diagnosis'].ravel())\n\nprint(\"x_samples shape=\",x_samples.shape)\nprint(\"x_samples shape=\",y_samples.shape)\n\nx_train = x_samples.reshape(x_samples.shape[0], 224, 224, 3)\ny_train = pd.get_dummies(y_samples).values\n\nprint(\"x_train shape=\",x_train.shape)\nprint(\"y_train shape=\",y_train.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"y_train_multilabel = np.empty(y_train.shape, dtype=y_train.dtype)\ny_train_multilabel[:, 4] = y_train[:, 4]\n\nfor i in range(3, -1, -1):\n    y_train_multilabel[:, i] = np.logical_or(y_train[:, i], y_train_multilabel[:, i+1])\n\nprint(\"Original y_train:\", y_train.sum(axis=0))\nprint(\"Multilabel version:\", y_train_multilabel.sum(axis=0))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"x_sptrain, x_spval, y_sptrain, y_spval = train_test_split(x_train, y_train_multilabel,test_size=0.25,random_state=seed )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"datagen= ImageDataGenerator(\n                zoom_range=0.10,        # set range for random zoom\n                fill_mode='constant',   # set mode for filling points outside the input boundaries\n                cval=0.,                # value used for fill_mode = \"constant\"\n                horizontal_flip=True,   # randomly flip images\n                vertical_flip=True,     # randomly flip images\n            )\n\n# Using original generator\ndata_generator = datagen.flow(x_sptrain, y_sptrain, batch_size=batch_size, seed=seed)\nprint(\"Image data augmentated ...\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Precision** quantifies the number of positive class predictions that actually belong to the positive class.<br>\n**Recall** quantifies the number of positive class predictions made out of all positive examples in the dataset.<br>\n**F-Measure** provides a single score that balances both the concerns of precision and recall in one number."},{"metadata":{"trusted":true},"cell_type":"code","source":"def precision(y_true, y_pred):\n    true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))\n    predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))\n    precision = true_positives / (predicted_positives + K.epsilon())\n    return precision\n\ndef recall(y_true, y_pred):\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    recall = true_positives / (possible_positives + K.epsilon())\n    return recall\n\ndef fbeta_score(y_true, y_pred, beta=1):\n    if beta < 0:\n        raise ValueError('The lowest choosable beta is zero (only precision).')\n\n    # If there are no true positives, fix the F score at 0 like sklearn.\n    if K.sum(K.round(K.clip(y_true, 0, 1))) == 0:\n        return 0\n\n    p = precision(y_true, y_pred)\n    r = recall(y_true, y_pred)\n    bb = beta ** 2\n    fbeta_score = (1 + bb) * (p * r) / (bb * p + r + K.epsilon())\n    return fbeta_score\n\ndef fmeasure(y_true, y_pred):\n    return fbeta_score(y_true, y_pred, beta=1)\n\ndef mean_pred(y_true, y_pred):\n    return K.mean(y_pred)\n\ndef f1_score(y_true, y_pred):\n    p = precision(y_true, y_pred)\n    r = recall(y_true, y_pred)\n    return 2*(p*r) / (p+r+K.epsilon())\n\nprint(\"Evaluation metrics defined ...\")\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"densenet = DenseNet121(\n    weights='../input/densenet-keras/DenseNet-BC-121-32-no-top.h5',\n    include_top=False,\n    input_shape=(224,224,3)\n)\n\nmodel = Sequential()\nmodel.add(densenet)\nmodel.add(layers.Dropout(0.5))\nmodel.add(layers.GlobalAveragePooling2D())\nmodel.add(layers.Dropout(0.5))\nmodel.add(layers.Dense(5, activation='sigmoid'))\n\nmodel.compile(\n    loss='binary_crossentropy',\n    optimizer=Adam(lr=learning_rate),\n    metrics=['accuracy',mean_pred, precision, recall, f1_score, fbeta_score, fmeasure]\n)\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# callback to keep track of kappa score during training\nclass 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\"Epoch: {epoch+1} 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\n    \nkappa_score = metrics()\nearly_stop = EarlyStopping(\n                monitor='val_loss', #Quantity to be monitored.\n                mode='auto', #direction is automatically inferred from the name of the monitored quantity\n                verbose=1, #verbosity mode.\n                patience=8 #Number of epochs with no improvement after which training will be stopped\n              )\n\n\nhistory = model.fit_generator(\n    data_generator,\n    steps_per_epoch=x_train.shape[0] / batch_size,\n    epochs=epochs,\n    validation_data=(x_spval, y_spval),\n    callbacks=[kappa_score,early_stop],\n    verbose=1\n)    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# summarize history for accuracy\nplt.plot(history.history['acc'])\nplt.plot(history.history['val_acc'])\nplt.title('model accuracy')\nplt.ylabel('accuracy')\nplt.xlabel('epoch')\nplt.legend(['train', 'validation'], loc='upper left')\nplt.show()\n# summarize history for loss\nplt.plot(history.history['loss'])\nplt.plot(history.history['val_loss'])\nplt.title('model loss')\nplt.ylabel('loss')\nplt.xlabel('epoch')\nplt.legend(['train', 'validation'], loc='upper left')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"history_df = pd.DataFrame(history.history)\nhistory_df.head(20)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"y_test = model.predict(x_test) > 0.5\ny_test = y_test.astype(int).sum(axis=1) - 1\n\ntest_df['diagnosis'] = y_test\ntest_df.to_csv('submission.csv',index=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df.diagnosis.value_counts()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"f, ax = plt.subplots(figsize=(14, 8.7))\nax = sns.countplot(x=\"diagnosis\", data=test_df, palette=\"cool\")\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"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}