{"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 json\nimport math\nimport os\n\nimport cv2\nfrom PIL import Image\nimport numpy as np\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 pandas as pd\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import cohen_kappa_score, accuracy_score\nimport scipy\nimport tensorflow as tf\nfrom keras.callbacks import EarlyStopping,ReduceLROnPlateau,LearningRateScheduler\nfrom tqdm import tqdm_notebook as tqdm\n\n%matplotlib inline","metadata":{"execution":{"iopub.status.busy":"2021-07-02T10:43:55.376817Z","iopub.execute_input":"2021-07-02T10:43:55.377179Z","iopub.status.idle":"2021-07-02T10:44:00.900453Z","shell.execute_reply.started":"2021-07-02T10:43:55.377101Z","shell.execute_reply":"2021-07-02T10:44:00.899612Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf\nimport timeit\n\ndevice_name = tf.test.gpu_device_name()\nprint(device_name)","metadata":{"execution":{"iopub.status.busy":"2021-07-02T10:44:06.118048Z","iopub.execute_input":"2021-07-02T10:44:06.118421Z","iopub.status.idle":"2021-07-02T10:44:07.763825Z","shell.execute_reply.started":"2021-07-02T10:44:06.118386Z","shell.execute_reply":"2021-07-02T10:44:07.762543Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"np.random.seed(2020)\ntf.random.set_seed(2020)","metadata":{"execution":{"iopub.status.busy":"2021-07-02T10:44:08.717729Z","iopub.execute_input":"2021-07-02T10:44:08.718052Z","iopub.status.idle":"2021-07-02T10:44:08.721972Z","shell.execute_reply.started":"2021-07-02T10:44:08.718020Z","shell.execute_reply":"2021-07-02T10:44:08.721087Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = pd.read_csv('../input/aptos2019-blindness-detection/train.csv')\ntest_df = pd.read_csv('../input/aptos2019-blindness-detection/test.csv')\nprint(train_df.shape)\nprint(test_df.shape)\ntrain_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-07-02T10:44:09.253397Z","iopub.execute_input":"2021-07-02T10:44:09.253725Z","iopub.status.idle":"2021-07-02T10:44:09.296552Z","shell.execute_reply.started":"2021-07-02T10:44:09.253694Z","shell.execute_reply":"2021-07-02T10:44:09.295586Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df['diagnosis'].hist()\ntrain_df['diagnosis'].value_counts()","metadata":{"execution":{"iopub.status.busy":"2021-07-02T10:44:10.166685Z","iopub.execute_input":"2021-07-02T10:44:10.167012Z","iopub.status.idle":"2021-07-02T10:44:10.359403Z","shell.execute_reply.started":"2021-07-02T10:44:10.166979Z","shell.execute_reply":"2021-07-02T10:44:10.358436Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def display_samples(df, columns=4, rows=3):\n    fig=plt.figure(figsize=(5*columns, 4*rows))\n\n    for i in range(columns*rows):\n        image_path = df.loc[i,'id_code']\n        image_id = df.loc[i,'diagnosis']\n        img = cv2.imread(f'../input/aptos2019-blindness-detection/train_images/{image_path}.png')\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n        \n        fig.add_subplot(rows, columns, i+1)\n        plt.title(image_id)\n        plt.imshow(img)\n    \n    plt.tight_layout()\n\ndisplay_samples(train_df)","metadata":{"execution":{"iopub.status.busy":"2021-07-02T10:44:10.430583Z","iopub.execute_input":"2021-07-02T10:44:10.430895Z","iopub.status.idle":"2021-07-02T10:44:19.071501Z","shell.execute_reply.started":"2021-07-02T10:44:10.430865Z","shell.execute_reply":"2021-07-02T10:44:19.070540Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_ht = 256\nimg_wd = 256","metadata":{"execution":{"iopub.status.busy":"2021-07-02T10:44:21.651828Z","iopub.execute_input":"2021-07-02T10:44:21.652173Z","iopub.status.idle":"2021-07-02T10:44:21.656481Z","shell.execute_reply.started":"2021-07-02T10:44:21.652141Z","shell.execute_reply":"2021-07-02T10:44:21.655063Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def crop_image_from_gray(img,tol=7):\n    if img.ndim ==2:\n        mask = img>tol\n        return img[np.ix_(mask.any(1),mask.any(0))]\n    elif img.ndim==3:\n        gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)\n        mask = gray_img>tol\n        \n        check_shape = img[:,:,0][np.ix_(mask.any(1),mask.any(0))].shape[0]\n        if (check_shape == 0): # image is too dark so that we crop out everything,\n            return img # return original image\n        else:\n            img1=img[:,:,0][np.ix_(mask.any(1),mask.any(0))]\n            img2=img[:,:,1][np.ix_(mask.any(1),mask.any(0))]\n            img3=img[:,:,2][np.ix_(mask.any(1),mask.any(0))]\n    #         print(img1.shape,img2.shape,img3.shape)\n            img = np.stack([img1,img2,img3],axis=-1)\n    #         print(img.shape)\n        return img\n    \n    \ndef circle_crop(img, sigmaX):   \n    \"\"\"\n    Create circular crop around image centre    \n    \"\"\"    \n    img = crop_image_from_gray(img)    \n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    \n    height, width, depth = img.shape    \n    \n    x = int(width/2)\n    y = int(height/2)\n    r = np.amin((x,y))\n    \n    circle_img = np.zeros((height, width), np.uint8)\n    cv2.circle(circle_img, (x,y), int(r), 1, thickness=-1)\n    img = cv2.bitwise_and(img, img, mask=circle_img)\n    img = crop_image_from_gray(img)\n    img=cv2.addWeighted(img,4, cv2.GaussianBlur( img , (0,0) , sigmaX) ,-4 ,128)\n    return img ","metadata":{"execution":{"iopub.status.busy":"2021-07-02T10:44:22.540147Z","iopub.execute_input":"2021-07-02T10:44:22.540486Z","iopub.status.idle":"2021-07-02T10:44:22.552797Z","shell.execute_reply.started":"2021-07-02T10:44:22.540456Z","shell.execute_reply":"2021-07-02T10:44:22.551853Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"'''Perform Image Processing on a sample image'''\n\ni = np.random.randint(low = 0,high = len(train_df) - 1)\n\n#img = img_t\nimage_path = train_df.loc[i,'id_code']\nimage_id = train_df.loc[i,'diagnosis']\nimg = cv2.imread(f'../input/aptos2019-blindness-detection/train_images/{image_path}.png')\n#img = cv2.imread(train_df.file_path.iloc[rn])\nimg_t = circle_crop(img,sigmaX = 30)\n\nf, axarr = plt.subplots(1,2,figsize = (11,11))\naxarr[0].imshow(cv2.resize(cv2.cvtColor(img, cv2.COLOR_BGR2RGB),(256,256)))\naxarr[1].imshow(img_t)\nplt.title('After applying Circular Crop and Gaussian Blur')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-07-02T10:44:23.228567Z","iopub.execute_input":"2021-07-02T10:44:23.228886Z","iopub.status.idle":"2021-07-02T10:44:25.092807Z","shell.execute_reply.started":"2021-07-02T10:44:23.228855Z","shell.execute_reply":"2021-07-02T10:44:25.091952Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def preprocess_image(image_path):\n    img = cv2.imread(image_path)\n    img_t = circle_crop(img,sigmaX = 30)\n    img_blue_channel=cv2.resize(cv2.cvtColor(img_t, cv2.COLOR_BGR2RGB),(256,256))\n    #f, axarr = plt.subplots(1,2,figsize = (11,11))\n    #axarr[0].imshow(img_t)\n    #axarr[1].imshow(img_r)\n    #plt.title('After applying Circular Crop and Gaussian Blur')\n    #plt.show()\n    return img_blue_channel","metadata":{"execution":{"iopub.status.busy":"2021-07-02T11:04:01.239652Z","iopub.execute_input":"2021-07-02T11:04:01.239967Z","iopub.status.idle":"2021-07-02T11:04:01.244828Z","shell.execute_reply.started":"2021-07-02T11:04:01.239935Z","shell.execute_reply":"2021-07-02T11:04:01.243759Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"N = train_df.shape[0]\nx_train = np.empty((N, img_ht, img_wd, 3), dtype=np.uint8)\n\nwith tf.device('/gpu:0'):\n    for i, image_id in enumerate(tqdm(train_df['id_code'])):\n        x_train[i, :, :, :] = preprocess_image( f'../input/aptos2019-blindness-detection/train_images/{image_id}.png')","metadata":{"execution":{"iopub.status.busy":"2021-07-02T11:09:09.583167Z","iopub.execute_input":"2021-07-02T11:09:09.583521Z","iopub.status.idle":"2021-07-02T12:01:11.682088Z","shell.execute_reply.started":"2021-07-02T11:09:09.583486Z","shell.execute_reply":"2021-07-02T12:01:11.681234Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_train = pd.get_dummies(train_df['diagnosis']).values\n\nprint(x_train.shape)\nprint(y_train.shape)","metadata":{"execution":{"iopub.status.busy":"2021-07-02T12:33:59.115028Z","iopub.execute_input":"2021-07-02T12:33:59.115378Z","iopub.status.idle":"2021-07-02T12:33:59.122998Z","shell.execute_reply.started":"2021-07-02T12:33:59.115345Z","shell.execute_reply":"2021-07-02T12:33:59.122031Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_train_multi = np.empty(y_train.shape, dtype=y_train.dtype)\ny_train_multi[:, 4] = y_train[:, 4]\n\nfor i in range(3, -1, -1):\n    y_train_multi[:, i] = np.logical_or(y_train[:, i], y_train_multi[:, i+1])\n\nprint(\"Original y_train:\", y_train.sum(axis=0))\nprint(\"Multilabel version:\", y_train_multi.sum(axis=0))","metadata":{"execution":{"iopub.status.busy":"2021-07-02T12:34:00.324997Z","iopub.execute_input":"2021-07-02T12:34:00.325330Z","iopub.status.idle":"2021-07-02T12:34:00.332932Z","shell.execute_reply.started":"2021-07-02T12:34:00.325299Z","shell.execute_reply":"2021-07-02T12:34:00.332104Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"x_train, x_val, y_train, y_val = train_test_split(\n    x_train, y_train_multi, \n    test_size=0.15, \n    random_state=2019\n)","metadata":{"execution":{"iopub.status.busy":"2021-07-02T12:34:02.591787Z","iopub.execute_input":"2021-07-02T12:34:02.592080Z","iopub.status.idle":"2021-07-02T12:34:02.857964Z","shell.execute_reply.started":"2021-07-02T12:34:02.592051Z","shell.execute_reply":"2021-07-02T12:34:02.857121Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"BATCH_SIZE = 4\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        width_shift_range = 0.3,\n        height_shift_range=0.3\n    )\n\n# Using original generator\ndata_generator = create_datagen().flow(x_train, y_train, batch_size=BATCH_SIZE, seed=2020)","metadata":{"execution":{"iopub.status.busy":"2021-07-02T12:34:03.919093Z","iopub.execute_input":"2021-07-02T12:34:03.919399Z","iopub.status.idle":"2021-07-02T12:34:04.899185Z","shell.execute_reply.started":"2021-07-02T12:34:03.919369Z","shell.execute_reply":"2021-07-02T12:34:04.896195Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def build_model():\n    model = Sequential()\n    model.add(effnet)\n    model.add(layers.GlobalAveragePooling2D())\n    model.add(layers.Dropout(0.5))\n    model.add(layers.Dense(5, activation='sigmoid'))\n    \n    model.compile(\n        loss='binary_crossentropy',\n        optimizer=Adam(lr=0.00005),\n        metrics=['accuracy']\n    )\n    \n    return model","metadata":{"execution":{"iopub.status.busy":"2021-07-02T12:34:04.900842Z","iopub.execute_input":"2021-07-02T12:34:04.901173Z","iopub.status.idle":"2021-07-02T12:34:04.909758Z","shell.execute_reply.started":"2021-07-02T12:34:04.901138Z","shell.execute_reply":"2021-07-02T12:34:04.907935Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install efficientnet==1.1.0","metadata":{"execution":{"iopub.status.busy":"2021-07-02T12:34:06.149948Z","iopub.execute_input":"2021-07-02T12:34:06.150310Z","iopub.status.idle":"2021-07-02T12:34:13.339780Z","shell.execute_reply.started":"2021-07-02T12:34:06.150276Z","shell.execute_reply":"2021-07-02T12:34:13.338844Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import efficientnet.tfkeras as efn","metadata":{"execution":{"iopub.status.busy":"2021-07-02T12:34:13.343296Z","iopub.execute_input":"2021-07-02T12:34:13.343560Z","iopub.status.idle":"2021-07-02T12:34:13.651094Z","shell.execute_reply.started":"2021-07-02T12:34:13.343531Z","shell.execute_reply":"2021-07-02T12:34:13.650326Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_ht = 256\nimg_wd = 256","metadata":{"execution":{"iopub.status.busy":"2021-07-02T12:34:14.837850Z","iopub.execute_input":"2021-07-02T12:34:14.838152Z","iopub.status.idle":"2021-07-02T12:34:14.843390Z","shell.execute_reply.started":"2021-07-02T12:34:14.838123Z","shell.execute_reply":"2021-07-02T12:34:14.842346Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"effnet = efn.EfficientNetB5(weights=None,\n                        include_top=False,\n                        input_shape=(img_wd, img_ht, 3))\neffnet.load_weights('../input/efficientnet/efficientnet-b5_imagenet_1000_notop.h5/efficientnet-b5_imagenet_1000_notop.h5')","metadata":{"execution":{"iopub.status.busy":"2021-07-02T12:34:37.347053Z","iopub.execute_input":"2021-07-02T12:34:37.347401Z","iopub.status.idle":"2021-07-02T12:34:43.425958Z","shell.execute_reply.started":"2021-07-02T12:34:37.347366Z","shell.execute_reply":"2021-07-02T12:34:43.425093Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = build_model()","metadata":{"execution":{"iopub.status.busy":"2021-07-02T12:34:44.744727Z","iopub.execute_input":"2021-07-02T12:34:44.745058Z","iopub.status.idle":"2021-07-02T12:34:45.918667Z","shell.execute_reply.started":"2021-07-02T12:34:44.745027Z","shell.execute_reply":"2021-07-02T12:34:45.917840Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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 = x_val, y_val\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","metadata":{"execution":{"iopub.status.busy":"2021-07-02T12:34:47.007614Z","iopub.execute_input":"2021-07-02T12:34:47.007929Z","iopub.status.idle":"2021-07-02T12:34:47.016535Z","shell.execute_reply.started":"2021-07-02T12:34:47.007897Z","shell.execute_reply":"2021-07-02T12:34:47.015565Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"es = EarlyStopping(monitor='val_loss',\n                                      mode='auto',\n                                      verbose=1,\n                                      patience=10)\n\nlearning_rate_reduction = ReduceLROnPlateau(monitor='val_loss',\n                                            patience=3,\n                                            verbose=1,\n                                            mode = 'auto',\n                                            factor=0.25,\n                                            min_lr=0.000001)","metadata":{"execution":{"iopub.status.busy":"2021-07-02T12:34:47.760488Z","iopub.execute_input":"2021-07-02T12:34:47.760764Z","iopub.status.idle":"2021-07-02T12:34:47.766230Z","shell.execute_reply.started":"2021-07-02T12:34:47.760738Z","shell.execute_reply":"2021-07-02T12:34:47.765357Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with tf.device('/gpu:0'):\n    kappa_metrics = Metrics()\n    history = model.fit_generator(\n        data_generator,\n        steps_per_epoch=x_train.shape[0] / BATCH_SIZE,\n        #steps_per_epoch=5,\n        epochs=15,\n        validation_data=(x_val, y_val),\n        callbacks=[kappa_metrics,es, learning_rate_reduction]\n    )","metadata":{"execution":{"iopub.status.busy":"2021-07-02T12:34:49.408542Z","iopub.execute_input":"2021-07-02T12:34:49.408866Z","iopub.status.idle":"2021-07-02T13:08:59.856676Z","shell.execute_reply.started":"2021-07-02T12:34:49.408833Z","shell.execute_reply":"2021-07-02T13:08:59.855740Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with open('history.json', 'w') as f:\n    try:\n        json.dump(history.history, f)\n    except:\n        pass","metadata":{"execution":{"iopub.status.busy":"2021-07-02T13:53:57.225174Z","iopub.execute_input":"2021-07-02T13:53:57.225531Z","iopub.status.idle":"2021-07-02T13:53:57.230671Z","shell.execute_reply.started":"2021-07-02T13:53:57.225501Z","shell.execute_reply":"2021-07-02T13:53:57.229714Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.plot(kappa_metrics.val_kappas)","metadata":{"execution":{"iopub.status.busy":"2021-07-02T13:53:57.630495Z","iopub.execute_input":"2021-07-02T13:53:57.630791Z","iopub.status.idle":"2021-07-02T13:53:57.751440Z","shell.execute_reply.started":"2021-07-02T13:53:57.630764Z","shell.execute_reply":"2021-07-02T13:53:57.750544Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}