{"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":"# Miscelaneous.\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport time as t\nimport cv2\nimport warnings\nimport shutil\nimport os\n\n# Sklearn utils.\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import confusion_matrix\nfrom sklearn.utils import shuffle\n\n# Keras.\nfrom keras.applications.resnet50 import ResNet50\nfrom keras.applications import DenseNet169\nfrom keras.utils import Sequence\nfrom keras.layers import Dense, Dropout, Flatten, Input, ZeroPadding2D, GlobalAveragePooling2D\nfrom keras.models import Sequential\nfrom keras.layers import Conv2D, MaxPooling2D\nfrom keras.layers.normalization import BatchNormalization\nfrom keras import regularizers\nfrom keras.models import Model\nfrom keras.callbacks import EarlyStopping, ReduceLROnPlateau, ModelCheckpoint\nfrom keras import optimizers\nfrom keras.utils import to_categorical\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras import backend as K\nimport tensorflow as tf","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-07-02T06:09:52.318386Z","iopub.execute_input":"2021-07-02T06:09:52.318679Z","iopub.status.idle":"2021-07-02T06:09:59.798389Z","shell.execute_reply.started":"2021-07-02T06:09:52.318624Z","shell.execute_reply":"2021-07-02T06:09:59.797538Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.listdir('../input/densenet')","metadata":{"execution":{"iopub.status.busy":"2021-07-02T06:09:59.800317Z","iopub.execute_input":"2021-07-02T06:09:59.800609Z","iopub.status.idle":"2021-07-02T06:09:59.821984Z","shell.execute_reply.started":"2021-07-02T06:09:59.800564Z","shell.execute_reply":"2021-07-02T06:09:59.821102Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"PATH = '../input/'\nPATH_APTOS = PATH + 'aptos2019-blindness-detection/'\nPATH_2015 = PATH + 'retinopathy-train-2015/rescaled_train_896/'\ndensenet_weights_path = PATH + 'densenet/densenet169_weights_tf_dim_ordering_tf_kernels_notop.h5'\nPATH_AUGM = '/data_augm/'\nHEIGHT, WIDTH = 256, 256\nRANDOM_STATE = 974\nVERBOSE = True\nBATCH_SIZE = 32\nDATA_AUGM = True\nDATA_AUGM_FACTOR = 1\nwarnings.filterwarnings('ignore')","metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","execution":{"iopub.status.busy":"2021-07-02T06:09:59.823419Z","iopub.execute_input":"2021-07-02T06:09:59.823834Z","iopub.status.idle":"2021-07-02T06:09:59.829497Z","shell.execute_reply.started":"2021-07-02T06:09:59.823669Z","shell.execute_reply":"2021-07-02T06:09:59.828818Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_aptos = pd.read_csv(PATH_APTOS + 'train.csv')\ndf_aptos.rename(index=str, columns={\"id_code\": \"id_code_aptos\"}, inplace=True)","metadata":{"execution":{"iopub.status.busy":"2021-07-02T06:09:59.831041Z","iopub.execute_input":"2021-07-02T06:09:59.831606Z","iopub.status.idle":"2021-07-02T06:09:59.863136Z","shell.execute_reply.started":"2021-07-02T06:09:59.831556Z","shell.execute_reply":"2021-07-02T06:09:59.862487Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_2015 = pd.read_csv(PATH_2015 + 'trainLabels.csv')\ndf_2015.rename(index=str, columns={\"image\": \"id_code_2015\", \"level\": \"diagnosis\"}, inplace=True)\ndf_2015 = df_2015.drop(df_2015[df_2015['diagnosis'] == 0].sample(frac=0.8).index)","metadata":{"execution":{"iopub.status.busy":"2021-07-02T06:09:59.867996Z","iopub.execute_input":"2021-07-02T06:09:59.868221Z","iopub.status.idle":"2021-07-02T06:09:59.949885Z","shell.execute_reply.started":"2021-07-02T06:09:59.868179Z","shell.execute_reply":"2021-07-02T06:09:59.949295Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = df_aptos.append(df_2015)\ndf[\"data_augm\"] = np.nan\nif VERBOSE:\n    display(df.head())\n    print(df.shape)","metadata":{"execution":{"iopub.status.busy":"2021-07-02T06:09:59.953293Z","iopub.execute_input":"2021-07-02T06:09:59.953529Z","iopub.status.idle":"2021-07-02T06:09:59.980871Z","shell.execute_reply.started":"2021-07-02T06:09:59.953485Z","shell.execute_reply":"2021-07-02T06:09:59.978522Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if VERBOSE:\n    plt.hist(df.diagnosis, bins=[-0.2, 0.2, 0.8, 1.2, 1.8, 2.2, 2.8, 3.2, 3.8, 4.2])\n    plt.xlabel(\"Severity of Diabetic Retinopathy\")\n    plt.ylabel(\"Count\")\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-07-02T06:09:59.982153Z","iopub.execute_input":"2021-07-02T06:09:59.982555Z","iopub.status.idle":"2021-07-02T06:10:00.211073Z","shell.execute_reply.started":"2021-07-02T06:09:59.982407Z","shell.execute_reply":"2021-07-02T06:10:00.210291Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def imagePreprocessing(image, normalize=True):\n    # Cutting black border.\n    row, col = image.shape[0], image.shape[1]\n    center_row, center_col = row // 2, col // 2\n    x_left, x_right, y_top, y_bot = 0, col, 0, row\n    while image[center_row, x_left:x_left + 10].mean().max() <= 10  and x_left < col:\n        x_left += 1\n    while image[center_row, x_right - 10:x_right].mean().max() <= 10 and x_right > 0:\n        x_right -= 1\n    while image[y_top:y_top + 10, center_col].mean().max() <= 10 and y_top < row:\n        y_top += 1\n    while image[y_bot - 10:y_bot, center_col].mean().max() <= 10 and y_bot > 0:\n        y_bot -= 1\n    if y_top < y_bot and x_left < x_right and y_bot - y_top > 0.6 * row and x_right - x_left > 0.6 * col:\n        image = image[y_top:y_bot, x_left:x_right]\n\n    # Cutting to remove black corner.\n    row, col = image.shape[0], image.shape[1]\n    top_left_x, top_left_y = 0, 0\n    while image[0, top_left_x:top_left_x + 10].mean().max() <= 10  and top_left_x < col:\n        top_left_x += 1\n    while image[top_left_y:top_left_y + 10, 0].mean().max() <= 10  and top_left_y < row:\n        top_left_y += 1\n    if 2 * np.abs(top_left_y - top_left_x) / (top_left_y + top_left_x) > 0.85 :\n        crop_left_right = int(0.5 * top_left_x)\n        if crop_left_right < 0.3 * col:\n            image = image[:, crop_left_right:col - crop_left_right]\n    else:\n        crop = int(0.15 * (top_left_x + top_left_y) / 2)\n        if crop < 0.3 * col and crop < 0.3 * row:\n            image = image[crop:row - crop, crop:col - crop]\n    \n    # Resizing image.\n    image = cv2.resize(image, (WIDTH, HEIGHT))\n    \n    # Applying GaussianBlur.\n    blurred = cv2.blur(image, ksize=(int(WIDTH / 6), int(HEIGHT / 6)))\n    image = cv2.addWeighted(image, 4, blurred, -4, 128)\n    \n    try:\n        if normalize:\n            image = image / 255\n            image -= image.mean()\n            return image\n        else:\n            return image\n    except:\n        return np.zeros((WIDTH, HEIGHT, 3))","metadata":{"execution":{"iopub.status.busy":"2021-07-02T06:10:00.212351Z","iopub.execute_input":"2021-07-02T06:10:00.212739Z","iopub.status.idle":"2021-07-02T06:10:00.240359Z","shell.execute_reply.started":"2021-07-02T06:10:00.212695Z","shell.execute_reply":"2021-07-02T06:10:00.239314Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def openImage(row, train=True, resize=False):\n    image = None\n    if not train:\n        image = cv2.imread('{}test_images/{}.png'.format(PATH_APTOS, row.id_code))\n    elif not pd.isnull(row.data_augm):\n        image = cv2.imread(row.data_augm)\n    elif not pd.isnull(row.id_code_aptos):\n        image = cv2.imread('{}train_images/{}.png'.format(PATH_APTOS, row.id_code_aptos))\n    elif not pd.isnull(row.id_code_2015):\n        image = cv2.imread('{}rescaled_train_896/{}.png'.format(PATH_2015, row.id_code_2015))\n    else:\n        print(\"[Error] Could not open the image. Log: {}\".format(row))\n    if resize and not image is None:\n        return cv2.resize(image, (WIDTH, HEIGHT))\n    return image","metadata":{"execution":{"iopub.status.busy":"2021-07-02T06:10:00.241683Z","iopub.execute_input":"2021-07-02T06:10:00.242256Z","iopub.status.idle":"2021-07-02T06:10:00.255086Z","shell.execute_reply.started":"2021-07-02T06:10:00.242048Z","shell.execute_reply":"2021-07-02T06:10:00.254152Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if VERBOSE:\n    nb_row = 4\n    nb_col = 6\n    nb = 1\n    plt.figure(figsize=(25, 15))\n    for row in df.itertuples():\n        if nb > nb_col * nb_row:\n            break\n        plt.subplot(nb_row, nb_col, nb)\n        plt.imshow(cv2.cvtColor(imagePreprocessing(openImage(row), normalize=False), cv2.COLOR_BGR2RGB))\n        plt.title('Diagnosed {}'.format(row.diagnosis))\n        nb += 1\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-07-02T06:10:00.256562Z","iopub.execute_input":"2021-07-02T06:10:00.257005Z","iopub.status.idle":"2021-07-02T06:10:08.387661Z","shell.execute_reply.started":"2021-07-02T06:10:00.25693Z","shell.execute_reply":"2021-07-02T06:10:08.3867Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class RetinaGenerator():\n    def __init__(self, image_df, batch_size, train=True):\n        self.image_df = image_df\n        self.batch_size = batch_size\n        self.train = train\n        self.step_per_epoch = len(self.image_df) // self.batch_size\n        self.step_per_pred = 1 + (len(self.image_df) - 1) // self.batch_size\n    def getGenerator(self):\n        while True:\n            for idx in range(self.step_per_epoch):\n                batch_x = np.array([imagePreprocessing(openImage(row)) for row in self.image_df[idx * self.batch_size:(idx + 1) * self.batch_size].itertuples()])\n                batch_y_cat= to_categorical([row.diagnosis for row in self.image_df[idx * self.batch_size:(idx + 1) * self.batch_size].itertuples()], num_classes=5)\n                batch_y = np.empty(batch_y_cat.shape, dtype=batch_y_cat.dtype)\n                batch_y[:, 4] = batch_y_cat[:, 4]\n                for i in range(3, -1, -1):\n                    batch_y[:, i] = np.logical_or(batch_y_cat[:, i], batch_y[:, i+1])\n                yield batch_x, batch_y\n    def getInputGenerator(self):\n        for idx in range(self.step_per_pred + 1):\n            yield np.array([imagePreprocessing(openImage(row, self.train)) for row in self.image_df[idx * self.batch_size:min((idx + 1) * self.batch_size, len(self.image_df))].itertuples()])","metadata":{"execution":{"iopub.status.busy":"2021-07-02T06:10:08.3889Z","iopub.execute_input":"2021-07-02T06:10:08.389214Z","iopub.status.idle":"2021-07-02T06:10:08.407277Z","shell.execute_reply.started":"2021-07-02T06:10:08.389145Z","shell.execute_reply":"2021-07-02T06:10:08.406523Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if DATA_AUGM:\n    shutil.rmtree(PATH_AUGM, ignore_errors=True, onerror=None)\n    shutil.os.mkdir(PATH_AUGM)\n    df = shuffle(df, random_state=RANDOM_STATE)\n    max_size = int(df.diagnosis.value_counts().max() * DATA_AUGM_FACTOR)\n    for diag in range(5):\n        shutil.rmtree('{}diag_{}'.format(PATH_AUGM, diag), ignore_errors=True, onerror=None)\n        shutil.os.mkdir('{}diag_{}'.format(PATH_AUGM, diag))\n        diag_df = df[df.diagnosis == diag]\n        size = len(diag_df)\n        to_create = max_size - size\n        augm_per_img = max(to_create // size, 1)\n        while to_create > 0:\n            for row in diag_df.itertuples():\n                if to_create < 0:\n                    break\n                image = np.expand_dims(cv2.cvtColor(openImage(row, resize=True), cv2.COLOR_BGR2RGB), 0)\n                data_generator = ImageDataGenerator(rotation_range=360, vertical_flip=True, horizontal_flip=True, zoom_range=0.1)\n                data_generator.fit(image)\n                id_code = row.id_code_aptos if not pd.isnull(row.id_code_aptos) else row.id_code_2015\n                for x, val in zip(data_generator.flow(image, save_to_dir='{}diag_{}'.format(PATH_AUGM, diag), \n                                                      save_prefix=id_code, save_format='png'), \n                                  range(augm_per_img - 1)):\n                    pass\n                to_create -= augm_per_img\n    for diag in range(5):\n        images = np.array(os.listdir(\"{}diag_{}\".format(PATH_AUGM, diag)))\n        for image in images:#diagnosis\tid_code_2015\tid_code_aptos\tdata_augm\n            df = df.append(pd.DataFrame([[diag, np.nan, np.nan, \"{}diag_{}/{}\".format(PATH_AUGM, diag, image)]], columns=df.columns))\n    df = shuffle(df, random_state=RANDOM_STATE)\n    display(df.head())","metadata":{"execution":{"iopub.status.busy":"2021-07-02T06:10:08.408692Z","iopub.execute_input":"2021-07-02T06:10:08.409187Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if VERBOSE:\n    nb_row = 4\n    nb_col = 6\n    nb = 1\n    plt.figure(figsize=(25, 15))\n    for row in df.itertuples():\n        if nb > nb_col * nb_row:\n            break\n        plt.subplot(nb_row, nb_col, nb)\n        plt.imshow(cv2.cvtColor(imagePreprocessing(openImage(row), normalize=False), cv2.COLOR_BGR2RGB))\n        plt.title('Diagnosed {}'.format(row.diagnosis))\n        nb += 1\n    plt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if VERBOSE:\n    plt.hist(df.diagnosis, bins=[-0.2, 0.2, 0.8, 1.2, 1.8, 2.2, 2.8, 3.2, 3.8, 4.2])\n    plt.xlabel(\"Severity of Diabetic Retinopathy\")\n    plt.ylabel(\"Count\")\n    plt.show()\n    print(df.shape)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df, val_df = train_test_split(df, test_size=0.2, random_state=RANDOM_STATE)\ntrain_df, test_df = train_test_split(train_df, test_size=0.2, random_state=RANDOM_STATE)\nif VERBOSE:\n    print(train_df.shape, val_df.shape, test_df.shape)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"LEARNING_RATE = 0.005\nEPOCHS = 3\nPATIENCE = 3\nLR_PATIENCE =3\nVALIDATION_GENERATOR = RetinaGenerator(val_df, BATCH_SIZE)\nTRAINING_GENERATOR = RetinaGenerator(train_df, BATCH_SIZE)\nALL_GENERATOR = RetinaGenerator(df, BATCH_SIZE)\nSTEPS_PER_EPOCH = TRAINING_GENERATOR.step_per_epoch\nVALIDATION_STEPS = VALIDATION_GENERATOR.step_per_epoch","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"visible = Input(shape=(HEIGHT, WIDTH, 3))\ndensenet = DenseNet169(include_top=False,\n                 weights=None,\n                 input_tensor=visible)\ndensenet.load_weights(densenet_weights_path)\n\nmodel = Sequential()\nmodel.add(densenet)\nmodel.add(GlobalAveragePooling2D())\nmodel.add(Dropout(0.5))\nmodel.add(Dense(5, activation='sigmoid'))\n    \nmodel.compile(\n    loss='binary_crossentropy',\n    optimizer=optimizers.Adam(lr=0.00005),\n    metrics=['accuracy']\n)\nprint(model.summary())\n\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"opt = optimizers.SGD(lr=LEARNING_RATE, decay=1e-6, momentum=0.9, nesterov=True)\n\nCallbacks=[EarlyStopping(patience=PATIENCE, restore_best_weights=True), \n           ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=LR_PATIENCE, verbose=VERBOSE)]\nwith tf.device('/device:GPU:0'):\n    H = model.fit_generator(generator=TRAINING_GENERATOR.getGenerator(),\n                            validation_data=VALIDATION_GENERATOR.getGenerator(),\n                            steps_per_epoch=STEPS_PER_EPOCH,\n                            validation_steps=VALIDATION_STEPS,\n                            epochs=EPOCHS,\n                            callbacks=Callbacks,\n                            verbose=VERBOSE)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.metrics import accuracy_score, cohen_kappa_score\n\nif VERBOSE:\n    TEST_GENERATOR = RetinaGenerator(test_df, BATCH_SIZE)\n    STEPS = TEST_GENERATOR.step_per_pred\n    Y_pred = (model.predict_generator(TEST_GENERATOR.getInputGenerator(), steps=STEPS) > 0.5).sum(axis=1) - 1\n    Y_test = np.array(test_df.diagnosis)\n    print(\"Average absolute distance is: {:.2f}\".format(np.abs(Y_pred - Y_test).mean()))\n    display(confusion_matrix(Y_test, Y_pred))\n    print(\"Accuracy Score:\" + str(accuracy_score(Y_test, Y_pred)))\n    print(\"Cohen Kappa Score:\" + str(cohen_kappa_score(Y_test, Y_pred, weights='quadratic')))\n    ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"STEPS = ALL_GENERATOR.step_per_pred\nY_pred = model.predict_generator(ALL_GENERATOR.getInputGenerator(), steps=STEPS)\nY_true = to_categorical(np.array(df.diagnosis), 5)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Y_true.shape","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"post_model = Sequential()\npost_model.add(Dense(5, input_dim=5, activation='relu'))\npost_model.add(Dense(5, activation='softmax'))\npost_model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])\n    \nopt = optimizers.SGD(lr=LEARNING_RATE, decay=1e-6, momentum=0.9, nesterov=True)\n\nCallbacks=[EarlyStopping(patience=PATIENCE, restore_best_weights=True), \n           ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=LR_PATIENCE, verbose=VERBOSE)]\nwith tf.device('/device:GPU:0'):\n    H = post_model.fit(Y_pred, Y_true, batch_size=10, epochs=10, verbose=VERBOSE )\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df = pd.read_csv(PATH_APTOS + 'test.csv')\nif VERBOSE:\n    print(sub_df.shape)\n    display(sub_df.head())","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"SUB_GENERATOR = RetinaGenerator(sub_df, BATCH_SIZE, False)\nSTEPS = SUB_GENERATOR.step_per_pred\nY_sub_preview = model.predict_generator(SUB_GENERATOR.getInputGenerator(), steps=STEPS)\nY_sub_cat = post_model.predict(Y_sub_preview)\nY_sub = np.argmax(Y_sub_cat, axis=1)\n#Y_sub = np.argmax(model.predict_generator(SUB_GENERATOR.getInputGenerator(), steps=STEPS), axis=1)\nif VERBOSE:\n    print(Y_sub.shape)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Y_sub","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df['diagnosis'] = Y_sub\nif VERBOSE:\n    print(sub_df.shape)\n    display(sub_df)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if VERBOSE:\n    nb_row = 4\n    nb_col = 6\n    nb = 1\n    plt.figure(figsize=(25, 15))\n    for row in sub_df.itertuples():\n        if nb > nb_col * nb_row:\n            break\n        plt.subplot(nb_row, nb_col, nb)\n        plt.imshow(cv2.cvtColor(imagePreprocessing(openImage(row, False), normalize=False), cv2.COLOR_BGR2RGB))\n        plt.title('Diagnosed {}'.format(row.diagnosis))\n        nb += 1\n    plt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df.to_csv('submission.csv', index=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.save('model1.h5')\npost_model.save('model2.h5')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}