{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# # This Python 3 environment comes with many helpful analytics libraries installed\n# # It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# # For example, here's several helpful packages to load\n\n# import numpy as np # linear algebra\n# import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# # Input data files are available in the read-only \"../input/\" directory\n# # For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\n# import os\n# for dirname, _, filenames in os.walk('/kaggle/input'):\n#     for filename in filenames:\n#         print(os.path.join(dirname, filename))\n\n# # You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# # You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import os\nimport sys\nimport random\nimport IPython\n\nimport numpy as np\nimport pandas as pd\nimport cv2\nimport matplotlib.pyplot as plt\n\nimport tensorflow as tf\nfrom tensorflow import keras\n\nfrom sklearn.utils import shuffle\nfrom sklearn.datasets import make_classification\nfrom sklearn.metrics import confusion_matrix\n\nfrom matplotlib.pyplot import imread\nfrom cv2 import resize\nimport cv2\n\nfrom keras import layers\nfrom keras.layers import Input, Add, Dense, Activation, ZeroPadding2D, BatchNormalization, Flatten, Conv2D, AveragePooling2D, MaxPooling2D\nfrom keras.models import Model, load_model\nfrom keras.preprocessing import image\nfrom keras.utils import layer_utils\nfrom keras.utils.data_utils import get_file\nfrom keras.applications.imagenet_utils import preprocess_input\nimport pydot\nfrom keras.utils.vis_utils import model_to_dot\nfrom keras.utils import plot_model\nfrom sklearn.preprocessing import OneHotEncoder\n\nfrom keras.initializers import glorot_uniform\nimport scipy.misc\nfrom matplotlib.pyplot import imshow\n\nrandom.seed = 2\nnp.random.seed = 2\ntf.seed = 2\ntf.random.set_seed(2)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Train Data Read"},{"metadata":{"trusted":true},"cell_type":"code","source":"dataset_images_location = \"../input/aptos2019-blindness-detection/train_images\"\ndataset_groundtruth_location = \"../input/aptos2019-blindness-detection/train.csv\"\n\ndf = pd.read_csv(dataset_groundtruth_location)\ndf_ = pd.DataFrame();\ndf_['Image name'] = df['id_code']\ndf_['Retinopathy grade'] = df['diagnosis']\n\nlabels = np.array(df_['Retinopathy grade']).reshape(-1, 1)\nenc = OneHotEncoder(categories='auto', drop=None, sparse=False, dtype = np.int, handle_unknown='error')\nlabels = enc.fit_transform(labels)\n\na = []\nfor i in range(len(labels)):\n    a.append(labels[i])\n    \ndf_['Retinopathy grade encoded'] = a\n\ndf = df_\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df['Retinopathy grade'].hist(figsize = (10, 5))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def balance_data(class_size, df):\n    train_df = df.groupby(['Retinopathy grade']).apply(lambda x: x.sample(class_size, replace = True)).reset_index(drop = True)\n    train_df = train_df.sample(frac=1).reset_index(drop=True)\n    print('New Data Size:', train_df.shape[0], 'Old Size:', df.shape[0])\n    train_df['Retinopathy grade'].hist(figsize = (10, 5))\n    return train_df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.model_selection import train_test_split\ntrain_df, val_df = train_test_split(df,test_size=0.1) # Here we will perform an 90%/10% split of the dataset, with stratification to keep similar distribution in validation set","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df['Retinopathy grade'].hist(figsize = (10, 5))\nlen(val_df)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df.pivot_table(index='Retinopathy grade', aggfunc=len)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df = balance_data(train_df.pivot_table(index='Retinopathy grade', aggfunc=len).max().max(),train_df) # I will oversample such that all classes have the same number of images as the maximum\ntrain_df['Retinopathy grade'].hist(figsize = (10, 5))\nprint(len(train_df))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Data Generator"},{"metadata":{"trusted":true},"cell_type":"code","source":"bs = 16","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def data_gen(df, enc):\n    rot=[-4,-3,-2,-1,1,2,3,4]\n    images = np.zeros(shape = (bs * 4, 224, 224, 3))\n    labels = np.zeros(shape = (bs * 4, 5))\n    im_size = 224\n    \n    counter = 0\n    index = 0\n    while True:\n        if(counter + bs - 1 < len(df)):\n            for i in range(bs):\n                    # filling images\n                    img = cv2.imread(dataset_images_location + '/' + df['Image name'][counter + i] + \".png\")\n                    img = cv2.resize(img, (im_size, im_size))\n                    images[index] = img\n                    images[index + 1] = (np.flip(img, axis = 0))\n                    images[index + 2] = (np.flip(img, axis = 1))\n                    images[index + 3] = (np.rot90(np.rot90(img)))\n\n                    #filling labels\n                    labels[index] = df['Retinopathy grade encoded'][counter + i]\n                    labels[index + 1] = df['Retinopathy grade encoded'][counter + i]\n                    labels[index + 2] = df['Retinopathy grade encoded'][counter + i]\n                    labels[index + 3] = df['Retinopathy grade encoded'][counter + i]\n                    \n                    index = index + 4\n            \n            counter = counter + bs\n            images = images.astype('float') / np.max(images)\n            index = 0\n            yield images, labels\n            \n        if counter + bs - 1 >= len(df):\n            counter = 0\n            index = 0\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Model (ResNet50)"},{"metadata":{"trusted":true},"cell_type":"code","source":"def identity_block(X, f, filters, d = 0.05):\n\n    #Retrieve filters\n    F1, F2, F3 = filters\n    \n    X_shortcut = X;\n\n    #First Layer\n    X = Conv2D(filters = F1, kernel_size = (1, 1), strides = (1, 1), padding = 'valid')(X)\n    X = BatchNormalization(axis = 3)(X)\n    X = Activation('relu')(X)\n    X = layers.Dropout(d)(X)\n\n    #Second Layer\n    X = Conv2D(filters = F2, kernel_size = (f, f), strides = (1, 1), padding = 'same')(X)\n    X = BatchNormalization(axis = 3)(X)\n    X = Activation('relu')(X)\n    X = layers.Dropout(d)(X)\n\n    #Third Layer\n    X = Conv2D(filters = F3, kernel_size = (1, 1), strides = (1, 1), padding = 'valid')(X)\n    X = BatchNormalization(axis = 3)(X)\n\n    #Final Step: Add shortcut to F(X) and pass it through relu activation\n    X = Add()([X, X_shortcut]) \n    X = Activation('relu')(X)\n    X = layers.Dropout(d)(X)\n\n    return X","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def convolutional_block(X, f, filters, s = 2, d = 0.05):\n\n    #Retrieve Filters\n    F1, F2, F3 = filters\n\n    X_shortcut = X\n\n    # First Layer\n    X = Conv2D(filters = F1, kernel_size = (1, 1), strides = (s, s))(X)\n    X = BatchNormalization(axis = 3)(X)\n    X = Activation('relu')(X)  \n    X = layers.Dropout(d)(X)  \n\n    # Second Layer\n    X = Conv2D(filters = F2, kernel_size = (f, f), strides = (1, 1), padding = 'same')(X)\n    X = BatchNormalization(axis = 3)(X)\n    X = Activation('relu')(X)   \n    X = layers.Dropout(d)(X) \n\n    # Third Layer\n    X = Conv2D(filters = F3, kernel_size = (1, 1), strides = (1, 1), padding = 'valid')(X)\n    X = BatchNormalization(axis = 3)(X)\n\n    # Shortcut Path\n    X_shortcut = Conv2D(filters = F3, kernel_size = (1, 1), strides = (s, s), padding = 'valid')(X_shortcut)\n    X_shortcut = BatchNormalization(axis = 3)(X_shortcut)\n\n    X = Add()([X, X_shortcut])\n    X = Activation('relu')(X)\n    X = layers.Dropout(d)(X)\n\n    return X","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def Resnet50(input_shape = (224, 224, 3), classes = 5, d = 0.05):\n\n    X_input = Input(input_shape)\n\n    X = ZeroPadding2D((3, 3))(X_input)\n\n    # Stage 1\n    X = Conv2D(64, (7, 7), strides = (2, 2))(X)\n    X = BatchNormalization(axis = 3)(X)\n    X = Activation('relu')(X)\n    X = MaxPooling2D((3, 3), strides = (2, 2))(X)\n    X = layers.Dropout(d)(X)\n\n    # Stage 2\n    X = convolutional_block(X, f = 3, filters = [64, 64, 256], s = 1)\n    X = identity_block(X, 3, [64, 64, 256])\n    X = identity_block(X, 3, [64, 64, 256])\n\n    # Stage 3\n    X = convolutional_block(X, f = 3, filters = [128, 128, 512], s = 2)\n    X = identity_block(X, 3, [128, 128, 512])\n    X = identity_block(X, 3, [128, 128, 512])\n    X = identity_block(X, 3, [128, 128, 512])\n\n    #Stage 4\n    X = convolutional_block(X, f = 3, filters = [256, 256, 1024], s = 2)\n    X = identity_block(X, 3, [256, 256, 1024])\n    X = identity_block(X, 3, [256, 256, 1024])\n    X = identity_block(X, 3, [256, 256, 1024])\n    X = identity_block(X, 3, [256, 256, 1024])\n    X = identity_block(X, 3, [256, 256, 1024])\n\n    # Stage 5\n    X = convolutional_block(X, f = 3, filters = [512, 512, 2048], s = 2)\n    X = identity_block(X, 3, [512, 512, 2048])\n    X = identity_block(X, 3, [512, 512, 2048])        \n\n    X = AveragePooling2D((2, 2), name = \"avg_pool\")(X)\n    X = layers.Dropout(d)(X)\n\n    # output layer\n    X = Flatten()(X)\n    X = Dense(128, activation = 'relu', kernel_initializer = glorot_uniform(seed = 0))(X)\n    X = Dense(classes, activation = 'softmax', name = 'fc' + str(classes), kernel_initializer = glorot_uniform(seed = 0))(X)\n\n    # Create model\n    model = Model(inputs = X_input, outputs = X, name = 'Resnet50')\n\n    return model","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Model Compile and Fit"},{"metadata":{"trusted":true},"cell_type":"code","source":"random.seed = 2\nnp.random.seed = 2\ntf.seed = 2\ntf.random.set_seed(2)\n\nmodel = Resnet50(input_shape = (224, 224, 3), classes = 5)\nopt = keras.optimizers.Adam(learning_rate = 0.00008, beta_1 = 0.9)\nmodel.compile(optimizer = opt, loss = 'categorical_crossentropy', metrics = ['accuracy'])\n\nearly_stopping= tf.keras.callbacks.EarlyStopping(monitor = 'accuracy', min_delta = 0.01, patience = 10)\n\n# model.summary()\n\ntrain_generator = data_gen(train_df, enc)\n# val_generator = data_gen(val_df, enc)\n\nhist = model.fit(train_generator,\n                 steps_per_epoch = int(len(train_df)/bs),\n                 epochs = 25, \n#                  validation_data = val_generator, \n#                  validation_steps = int(len(val_df) / bs),\n                 callbacks = [early_stopping], \n                 shuffle = True)\n\nprint('Done')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#serialize and save model \n# serialize model to JSON\nmodel_json = model.to_json()\nwith open(\"model_{}.json\".format('gradingNew11'), \"w\") as json_file:\n    json_file.write(model_json)\n# serialize weights to HDF5\nmodel.save_weights(\"model_{}.h5\".format('gradingNew11'))\nprint(\"Saved model to disk\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.plot(hist.history['loss'])","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}