{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"from random import randint\nimport tensorflow as tf\nimport json\nimport os\nfrom PIL import Image\nfrom glob import glob\nfrom zipfile import ZipFile\nimport pandas as pd\nfrom keras.optimizers import Adam\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.callbacks import ModelCheckpoint, Callback, EarlyStopping\nfrom keras.models import Model, Input, load_model\nfrom keras.layers import Dense, GlobalAveragePooling2D, Dropout\nfrom keras.applications.nasnet import NASNetLarge\nfrom keras import backend as K\nfrom matplotlib import pyplot as plt\nfrom matplotlib.image import imread\nimport os\nimport sys\nimport cv2\nimport numpy as np\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import cohen_kappa_score, accuracy_score\nimport scipy\nfrom tqdm import tqdm\nfrom skimage.io import imsave","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Data"},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"def process_csv(dataframe: pd.DataFrame, image_column_name: str,\n                label_column_name: str,\n                folder_with_images: str) -> pd.DataFrame:\n    \"\"\"This function process Pandas DataFrame, which contains image filenames\n    and their corresponding labels.\n\n    Args:\n        dataframe: Pandas DataFrame object. It should consist of 2 columns\n        image_column_name: The name of the column containing the image\n            filenames\n        label_column_name: The name of the column containing the image\n            labels\n        folder_with_images: Folder with images\n\n    Returns:\n        dataframe: processed DataFrame with full paths to images\n    \"\"\"\n    dataframe[image_column_name] = dataframe[image_column_name].apply(\n        lambda x: f\"{folder_with_images}{x}.png\")\n    dataframe[label_column_name] = dataframe[label_column_name].astype('str')\n    return dataframe","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_datagen = ImageDataGenerator(rescale=1. / 255,\n                                   rotation_range=15,\n                                   width_shift_range=0.1,\n                                   height_shift_range=0.1,\n                                   shear_range=0.01,\n                                   zoom_range=[0.9, 1.25],\n                                   horizontal_flip=True,\n                                   vertical_flip=True,\n                                   fill_mode='reflect',\n                                   data_format='channels_last',\n                                   brightness_range=[0.5, 1.5],\n                                   validation_split=0.3)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!mkdir /kaggle/dataset_with_ben","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def crop_image1(img,tol=7):\n    # img is image data\n    # tol  is tolerance\n        \n    mask = img>tol\n    return img[np.ix_(mask.any(1),mask.any(0))]\n\ndef 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","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def ben_color(path, sigmaX=20):\n    image = Image.open(path)\n    image = cv2.imread(path)\n    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n    image = crop_image_from_gray(image)\n    image = cv2.resize(image, (299, 299))\n\n    height, width, depth = image.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    image = cv2.bitwise_and(image, image, mask=circle_img)\n\n    image = cv2.addWeighted ( image,4, cv2.GaussianBlur( image , (0,0) , sigmaX=20) ,-4 ,128)\n    \n    return image","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for path in glob(f\"/kaggle/input/aptos2019-blindness-detection/train_images/*\"):\n    img = ben_color(path, sigmaX=30)\n    name = path.split('/')[-1]\n    name = name.split('.')[0]\n    imsave('/kaggle/dataset_with_ben/'+str(name)+'.png', img)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_csv = pd.read_csv(\"/kaggle/input/aptos2019-blindness-detection/train.csv\")\ntrain_csv = process_csv(\n    dataframe=train_csv,\n    image_column_name=\"id_code\",\n    label_column_name=\"diagnosis\",\n    folder_with_images=\"/kaggle/dataset_with_ben/\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_generator = train_datagen.flow_from_dataframe(\n    dataframe=train_csv, x_col=\"id_code\", y_col=\"diagnosis\", subset=\"training\",\n    batch_size=32, target_size=(299, 299))\nval_generator = train_datagen.flow_from_dataframe(\n    dataframe=train_csv, x_col=\"id_code\", y_col=\"diagnosis\",\n    subset=\"validation\", batch_size=32, target_size=(299, 299))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Optimizer"},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.optimizers import Optimizer\nfrom keras import backend as K\n\n\nclass RAdam(Optimizer):\n\n    def __init__(self, lr, beta1=0.9, beta2=0.99, decay=0, **kwargs):\n        super(RAdam, self).__init__(**kwargs)\n        with K.name_scope(self.__class__.__name__):\n            self.lr = K.variable(lr)\n            self._beta1 = K.variable(beta1, dtype=\"float32\")\n            self._beta2 = K.variable(beta2, dtype=\"float32\")\n            self._max_sma_length = 2 / (1 - self._beta2)\n            self._iterations = K.variable(0)\n            self._decay = K.variable(decay)\n\n    def get_updates(self, loss, params):\n        grads = self.get_gradients(loss, params)\n        self.updates = [K.update_add(self._iterations, 1)]\n        first_moments = [K.zeros(K.int_shape(p), dtype=K.dtype(p))\n                         for (i, p) in enumerate(params)]\n        second_moments = [K.zeros(K.int_shape(p), dtype=K.dtype(p))\n                          for (i, p) in enumerate(params)]\n\n        self.weights = [self._iterations] + first_moments + second_moments\n        bias_corrected_beta1 = K.pow(self._beta1, self._iterations)\n        bias_corrected_beta2 = K.pow(self._beta2, self._iterations)\n        for i, (curr_params, curr_grads) in enumerate(zip(params, grads)):\n            # Updating moving moments\n\n            new_first_moment = self._beta1 * first_moments[i] + (\n                    1 - self._beta1) * curr_grads\n            new_second_moment = self._beta2 * second_moments[i] + (\n                    1 - self._beta2) * K.square(curr_grads)\n            self.updates.append(K.update(first_moments[i],\n                                         new_first_moment))\n            self.updates.append(K.update(second_moments[i],\n                                         new_second_moment))\n\n            # Computing length of approximated SMA\n\n            bias_corrected_moving_average = new_first_moment / (\n                    1 - bias_corrected_beta1)\n            sma_length = self._max_sma_length - 2 * (\n                    self._iterations * bias_corrected_beta2) / (\n                                 1 - bias_corrected_beta2)\n\n            # Bias correction\n\n            variance_rectification_term = K.sqrt(\n                self._max_sma_length * (sma_length - 4) * (sma_length - 2) / (\n                        sma_length * (self._max_sma_length - 4) *\n                        (self._max_sma_length - 2) + K.epsilon()))\n            resulting_parameters = K.switch(\n                sma_length > 5, variance_rectification_term *\n                bias_corrected_moving_average / K.sqrt(\n                    K.epsilon() + new_second_moment / (1 -\n                                                       bias_corrected_beta2)),\n                bias_corrected_moving_average)\n            resulting_parameters = curr_params - self.lr * resulting_parameters\n            self.updates.append(K.update(curr_params, resulting_parameters))\n        if self._decay != 0:\n            new_lr = self.lr * (1. / (1. + self._decay * K.cast(\n                self._iterations, K.dtype(self._decay))))\n            self.updates.append(K.update(self.lr, new_lr))\n        return self.updates\n\n    def get_config(self):\n        config = {\n            \"lr\": float(K.get_value(self.lr)),\n            \"beta1\": float(K.get_value(self._beta1)),\n            \"beta2\": float(K.get_value(self._beta2)),\n        }\n        base_config = super(RAdam, self).get_config()\n        return dict(list(base_config.items()) + list(config.items()))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Model"},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.models import Model, Input\nfrom keras.layers import Dense, GlobalAveragePooling2D\nfrom keras.applications.inception_resnet_v2 import InceptionResNetV2\nfrom keras.applications.xception import Xception\nfrom keras.applications.inception_v3 import InceptionV3\nfrom keras.layers import Average, Input\n\nsys.path.append(os.path.abspath('../input/kerasefficientnetsmaster/keras-efficientnets-master/keras-efficientnets-master/'))\nfrom keras_efficientnets import EfficientNetB7\n\n\n\ndef create_model():\n    input_tensor = Input((299, 299, 3))\n    outputs = []\n    \n    effnet = EfficientNetB7(input_shape=(299,299,3),\n                        weights=sys.path.append(os.path.abspath('/kaggle/input/efficientnetb0b7-keras-weights/efficientnet-b7_weights_tf_dim_ordering_tf_kernels_autoaugment_notop.h5')),\n                        include_top=False)\n    \n    #InceptionResNetV2_model = InceptionResNetV2(weights=None, input_shape=(299, 299, 3),include_top=False)                          \n    #InceptionResNetV2_model.load_weights(\"/kaggle/input/inceptionresnetv2/inception_resnet_v2_weights_tf_dim_ordering_tf_kernels_notop.h5\")\n    \n    xception_model = Xception(weights=None,include_top=False,input_shape=(299,299,3))\n    xception_model.load_weights(\"/kaggle/input/xception/xception_weights_tf_dim_ordering_tf_kernels_notop.h5\")\n    \n    #InceptionV3_model = InceptionV3(weights=None,include_top=False,input_shape=(299, 299, 3))\n    #InceptionV3_model.load_weights(\"/kaggle/input/inceptionv3/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5\")\n    \n    pretrained_models = [\n       effnet,xception_model #xception_model #InceptionResNetV2_model #xception_model #InceptionV3_model, InceptionResNetV2_model,  #xception_model,InceptionV3_model\n    ]\n    for i, model in enumerate(pretrained_models):\n        curr_output = model(input_tensor)\n        curr_output = GlobalAveragePooling2D()(curr_output)\n        curr_output = Dense(1024, activation=\"relu\")(curr_output)\n        outputs.append(curr_output)\n    output_tensor = Average()(outputs)\n    output_tensor = Dense(5, activation=\"softmax\")(output_tensor)\n\n    model = Model(input_tensor, output_tensor)\n    return model ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Metric Kappa Loss"},{"metadata":{"trusted":true},"cell_type":"code","source":"start_lr = 1e-10\nend_lr = 1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def kappa_loss(y_pred, y_true, y_pow=2, eps=1e-10, N=5, bsize=256, name='kappa'):\n    \"\"\"A continuous differentiable approximation of discrete kappa loss.\n        Args:\n            y_pred: 2D tensor or array, [batch_size, num_classes]\n            y_true: 2D tensor or array,[batch_size, num_classes]\n            y_pow: int,  e.g. y_pow=2\n            N: typically num_classes of the model\n            bsize: batch_size of the training or validation ops\n            eps: a float, prevents divide by zero\n            name: Optional scope/name for op_scope.\n        Returns:\n            A tensor with the kappa loss.\"\"\"\n\n    with tf.name_scope(name):\n        y_true = tf.to_float(y_true)\n        repeat_op = tf.to_float(tf.tile(tf.reshape(tf.range(0, N), [N, 1]), [1, N]))\n        repeat_op_sq = tf.square((repeat_op - tf.transpose(repeat_op)))\n        weights = repeat_op_sq / tf.to_float((N - 1) ** 2)\n    \n        pred_ = y_pred ** y_pow\n        try:\n            pred_norm = pred_ / (eps + tf.reshape(tf.reduce_sum(pred_, 1), [-1, 1]))\n        except Exception:\n            pred_norm = pred_ / (eps + tf.reshape(tf.reduce_sum(pred_, 1), [bsize, 1]))\n    \n        hist_rater_a = tf.reduce_sum(pred_norm, 0)\n        hist_rater_b = tf.reduce_sum(y_true, 0)\n    \n        conf_mat = tf.matmul(tf.transpose(pred_norm), y_true)\n    \n        nom = tf.reduce_sum(weights * conf_mat)\n        denom = tf.reduce_sum(weights * tf.matmul(\n            tf.reshape(hist_rater_a, [N, 1]), tf.reshape(hist_rater_b, [1, N])) /\n                              tf.to_float(bsize))\n    \n        return nom / (denom + eps)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Train"},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.callbacks import ReduceLROnPlateau\n\nreduce_lr = ReduceLROnPlateau(monitor='val_acc', factor=0.2,\n                              patience=5, min_lr=1e-5)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"callbacks = [\n    ModelCheckpoint(\n        \"best_weights.hdf5\",\n        monitor='val_acc',\n        verbose=1, save_best_only=True,\n        save_weights_only=True),\n    EarlyStopping(monitor='val_acc', patience=5),\n    reduce_lr\n]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = create_model()\nmodel.compile(optimizer=Adam(1e-4),\n              loss=\"categorical_crossentropy\", metrics=[\"accuracy\"])\nmodel.fit_generator(generator=train_generator,\n                    steps_per_epoch=len(train_generator),\n                    validation_data=val_generator,\n                    validation_steps=len(val_generator),\n                    epochs=10,\n                    callbacks=callbacks)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def test_time_augmentation(image, network_model):\n    datagen = ImageDataGenerator()\n\n    all_images = np.expand_dims(image, axis=0)\n    \n    flip_horizontal_image = np.expand_dims(datagen.apply_transform(\n        x=image, transform_parameters={\"flip_horizontal\": True}), axis=0)\n    all_images = np.append(all_images, flip_horizontal_image, axis=0)\n    \n    flip_vertical_image = np.expand_dims(datagen.apply_transform(\n        x=image, transform_parameters={\"flip_vertical\": True}), axis=0)\n    all_images = np.append(all_images, flip_vertical_image, axis=0)\n    \n    rotated_image = np.expand_dims(datagen.apply_transform(\n        x=image, transform_parameters={\"theta\": randint(0, 15)}), axis=0)\n    all_images = np.append(all_images, rotated_image, axis=0)\n    \n    prediction = int(np.argmax(np.mean(network_model.predict(all_images), axis=0)))\n    return prediction","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.load_weights(\"best_weights.hdf5\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_csv = pd.read_csv(\"/kaggle/input/aptos2019-blindness-detection/test.csv\")\npredicted_csv = pd.DataFrame(columns=[\"id_code\", \"diagnosis\"])\n\nfor id_code in test_csv[\"id_code\"]:\n    filename = f\"/kaggle/input/aptos2019-blindness-detection/test_images/{id_code}.png\"\n    img = imread(filename)\n    img = cv2.resize(img, dsize=(299, 299) , interpolation=cv2.INTER_CUBIC)\n    prediction = test_time_augmentation(img, model)\n    predicted_csv = predicted_csv.append(\n        {'id_code':id_code ,\"diagnosis\": prediction}, ignore_index=True)\n\nwith open(\"submission.csv\", \"w\") as f:\n    f.write(predicted_csv.to_csv(index=False))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!rm -r /kaggle/dataset_with_ben/","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":1}