{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"scrolled":true,"collapsed":true},"cell_type":"code","source":"# https://www.pyimagesearch.com/2017/NUM_CLASSES/11/image-classification-with-keras-and-deep-learning/\n# https://machinelearningmastery.com/grid-search-hyperparameters-deep-learning-models-python-keras/\n# https://machinelearningmastery.com/save-load-keras-deep-learning-models/\n#https://www.learnopencv.com/image-classification-using-convolutional-neural-networks-in-keras/\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport os\nimport random\nimport sys\nimport cv2\nimport matplotlib\nfrom subprocess import check_output\n\nfrom keras.models import Sequential\nfrom keras.layers import Dense, Conv2D, MaxPooling2D, Dropout, Flatten\nfrom keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img\nfrom keras.optimizers import Adam\nfrom sklearn.model_selection import train_test_split\nfrom keras.utils import to_categorical\n#list the files in the input directory\n#print(os.listdir(\"../input\"))\n#print(check_output([\"ls\", \"../input\"]).decode(\"utf8\")) #trainLabels.csv\n#print(check_output([\"pwd\", \"\"]).decode(\"utf8\")) # /kaggle/working/\n#classes : 0 - No DR, 1 - Mild, 2 - Moderate, 3 - Severe, 4 - Proliferative DR\ndef classes_to_int(label):\n    # label = classes.index(dir)\n    label = label.strip()\n    if label == \"No DR\":  return 0\n    if label == \"Mild\":  return 1\n    if label == \"Moderate\":  return 2\n    if label == \"Severe\":  return 3\n    if label == \"Proliferative DR\":  return 4\n    print(\"Invalid Label\", label)\n    return 5\n\ndef int_to_classes(i):\n    if i == 0: return \"No DR\"\n    elif i == 1: return \"Mild\"\n    elif i == 2: return \"Moderate\"\n    elif i == 3: return \"Severe\"\n    elif i == 4: return \"Proliferative DR\"\n    print(\"Invalid class \", i)\n    return \"Invalid Class\"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"collapsed":true,"_uuid":"a8392f068f3887a4ef107e51530e2eb05fb3035a"},"cell_type":"code","source":"NUM_CLASSES = 5\n# we need images of same size so we convert them into the size\nWIDTH = 128\nHEIGHT = 128\nDEPTH = 3\ninputShape = (HEIGHT, WIDTH, DEPTH)\n# initialize number of epochs to train for, initial learning rate and batch size\nEPOCHS = 15\nINIT_LR = 1e-3\nBS = 32\n#global variables\nImageNameDataHash = {}\nuniquePatientIDList = []","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"collapsed":true,"_uuid":"18c3c3a9599a32a49199918bef643166cde51928"},"cell_type":"code","source":"def readTrainData(trainDir):\n    global ImageNameDataHash\n    # loop over the input images\n    images = os.listdir(trainDir)\n    print(\"Number of files in \" + trainDir + \" is \" + str(len(images)))\n    for imageFileName in images:\n        if (imageFileName == \"trainLabels.csv\"):\n            continue\n        # load the image, pre-process it, and store it in the data list\n        imageFullPath = os.path.join(os.path.sep, trainDir, imageFileName)\n        #print(imageFullPath)\n        img = load_img(imageFullPath)\n        arr = img_to_array(img)  # Numpy array with shape (233,233,3)\n        dim1 = arr.shape[0]\n        dim2 = arr.shape[1]\n        dim3 = arr.shape[2]\n        if (dim1 < HEIGHT or dim2 < WIDTH or dim3 < DEPTH):\n            print(\"Error image dimensions are less than expected \"+str(arr.shape))\n        arr = cv2.resize(arr, (HEIGHT,WIDTH)) #Numpy array with shape (HEIGHT, WIDTH,3)\n        #print(arr.shape) # 128,128,3\n        dim1 = arr.shape[0]\n        dim2 = arr.shape[1]\n        dim3 = arr.shape[2]\n        if (dim1 != HEIGHT or dim2 != WIDTH or dim3 != DEPTH):\n            print(\"Error after resize, image dimensions are not equal to expected \"+str(arr.shape))\n        #print(type(arr))\n        # scale the raw pixel intensities to the range [0, 1] - TBD TEST\n        arr = np.array(arr, dtype=\"float\") / 255.0\n        imageFileName = imageFileName.replace('.jpeg','')\n        ImageNameDataHash[str(imageFileName)] = np.array(arr) \n    return","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a255507029c703ab70b7bd82e2dba11487abf73a","collapsed":true},"cell_type":"code","source":"from datetime import datetime\nprint(\"Loading images at...\"+ str(datetime.now()))\nsys.stdout.flush()\nreadTrainData(\"/kaggle/working/../input/\")\nprint(\"Loaded \" + str(len(ImageNameDataHash)) + \" images at...\"+ str(datetime.now())) # 1000","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true,"collapsed":true},"cell_type":"code","source":"#csv contains image\tlevel\n#10_left 0\n#10_right 0\nimport csv\ndef readTrainCsv():\n    raw_df = pd.read_csv('/kaggle/working/../input/trainLabels.csv', sep=',')\n    print(type(raw_df)) #<class 'pandas.core.frame.DataFrame'>\n    row_count=raw_df.shape[0] #gives number of row count row_count=35126 \n    col_count=raw_df.shape[1] #gives number of col count col count=2\n    print(\"row_count=\"+str(row_count)+\" col count=\"+str(col_count))\n    raw_df[\"PatientID\"] = ''\n    header_list = list(raw_df.columns)\n    print(header_list) # ['image', 'level', 'PatientID']\n    # double check if level of left and right are same or not\n    ImageLevelHash = {}\n    patientIDList = []\n    for index, row in raw_df.iterrows():\n        # 0 is image, 1 is level, 2 is PatientID, 3 is data\n        key = row[0] + ''\n        patientID = row[0] + ''\n        patientID = patientID.replace('_right','')\n        patientID = patientID.replace('_left','')\n        #print(\"Adding patient ID\"+ patientID)\n        raw_df.at[index, 'PatientID'] = patientID\n        patientIDList.append(patientID)\n        ImageLevelHash[key] = str(row[1]) # level\n                \n    global uniquePatientIDList\n    uniquePatientIDList = sorted(set(patientIDList))\n    count=0;\n    for patientID in uniquePatientIDList:\n        left_level = ImageLevelHash[str(patientID+'_left')]\n        right_level = ImageLevelHash[str(patientID+'_right')]\n        #right_exists = str(patientID+'_right') in raw_df.values\n        if (left_level != right_level):\n            count = count+1\n            #print(\"Warning for patient=\"+ str(patientID) + \" left_level=\" + left_level+ \" right_level=\" +right_level)\n    print(\"count of images with both left and right eye level not matching=\"+str(count)) # 2240\n    print(\"number of unique patients=\"+str(len(uniquePatientIDList))) # 17563\n    return raw_df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"da157990920eda7c89bd96f6457cf2696d45b01b","scrolled":true,"collapsed":true},"cell_type":"code","source":"random.seed(10)\nprint(\"Reading trainLabels.csv...\")\ndf = readTrainCsv()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"bbceaf7b7abd5a2c2f562b63f2ead55c00e451e2","collapsed":true},"cell_type":"code","source":"for i in range(0,10):\n    s = df.loc[df.index[i], 'PatientID'] # get patient id of patients\n    print(str(i) + \" patient's patientID=\"+str(s))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"98a5849022c032a33b2d75f54ec2d05da2cd9245","collapsed":true},"cell_type":"code","source":"# df has 3 columns ['image', 'level', 'PatientID']\nkeepImages =  list(ImageNameDataHash.keys())\ndf = df[df['image'].isin(keepImages)]\nprint(len(df)) # 1000","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"2d8c229035728a04562a428aed1b685974e172e8","collapsed":true},"cell_type":"code","source":"#convert hash to dataframe\nimageNameArr = []\ndataArr = []\nfor index, row in df.iterrows():\n    key = str(row[0])\n    if key in ImageNameDataHash:\n        imageNameArr.append(key)\n        dataArr.append(np.array(ImageNameDataHash[key])) # np.array\n\ndf2 = pd.DataFrame({'image': imageNameArr, 'data': dataArr})\ndf2_header_list = list(df2.columns) \nprint(df2_header_list) # ['image', 'data']\nprint(len(df2)) # 1000\n#print(df2.describe(include='all'))\n#print(df2.sample(3)) # 3 rows x 2 columns","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ea37d7a5dffecdb0744c223090c98c91ee097ccf","collapsed":true},"cell_type":"code","source":"if len(df) != len(df2):\n    print(\"Error length of df != df2\")\n    \nfor idx in range(0,len(df)):\n    if (df.loc[df.index[idx], 'image'] != df2.loc[df2.index[idx], 'image']):\n        print(\"Error \" + df.loc[df.index[idx], 'image'] +\"==\" + df2.loc[df2.index[idx], 'image'])\n        \nprint(df2.dtypes)\nprint(df.dtypes)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c3fd926f29c25be1bd728da76c175e283b1fac83","collapsed":true},"cell_type":"code","source":"df = pd.merge(df2, df, left_on='image', right_on='image', how='outer')\ndf_header_list = list(df.columns) \nprint(df_header_list) # 'image', 'data', level', 'PatientID'\nprint(len(df)) # 1000\nprint(df.sample())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"25fd586d9cc4b7a1beeb2e8c7cdee896f068b8c6","collapsed":true},"cell_type":"code","source":"sample0 = df.loc[df.index[0], 'data']\nprint(sample0)\nprint(type(sample0)) # <class 'numpy.ndarray'>\nprint(sample0.shape) # 128,128,3\nfrom matplotlib import pyplot as plt\nplt.imshow(sample0, interpolation='nearest')\nplt.show()\nprint(\"Sample Image\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"5de4e16737d21bd5c842e3b3fe7ca16b3177f76a","collapsed":true},"cell_type":"code","source":"X = df['data']\nY = df['level']\n# scale the raw pixel intensities to the range [0, 1]\n#print(type(X)) # 'pandas.core.series.Series'\n#X = np.array(X, dtype=\"float\") / 255.0 -- TBD moved to top\nY = np.array(Y)\n# convert the labels from integers to vectors\nY =  to_categorical(Y, num_classes=NUM_CLASSES)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"4550440da8759c52ed43bfe0737bfa2684e7583c","collapsed":true},"cell_type":"code","source":"# partition the data into training and testing splits using 75% training and 25% for validation\nprint(\"Parttition data into 75:25...\")\nsys.stdout.flush()\nprint(\"Unique patients in dataframe df=\" + str(df.PatientID.nunique())) # 500\nunique_ids = df.PatientID.unique()\nprint('unique_ids shape='+ str(len(unique_ids))) #500\n\n# Refer https://www.kaggle.com/kmader/tf-data-tutorial-with-retina-and-keras\ntrain_ids, valid_ids = train_test_split(unique_ids, test_size = 0.25, random_state = 10) #stratify = rr_df['level'])\ntrainid_list = train_ids.tolist()\nprint('trainid_list shape=', str(len(trainid_list))) # 375\n\ntraindf = df[df.PatientID.isin(trainid_list)]\nvalSet = df[~df.PatientID.isin(trainid_list)]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"07f4a9232379f1c7057f9921ad372266caadd887","collapsed":true},"cell_type":"code","source":"print(traindf.head())\nprint(valSet.head())\n\ntraindf = traindf.reset_index(drop=True)\nvalSet = valSet.reset_index(drop=True)\n\nprint(traindf.head())\nprint(valSet.head())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"19f9a8d5aba3229deecf254d2db0b7e5c5cbd81f","collapsed":true},"cell_type":"code","source":"trainX = traindf['data']\ntrainY = traindf['level']\n\nvalX = valSet['data']\nvalY = valSet['level']\n\n#(trainX, valX, trainY, valY) = train_test_split(X,Y,test_size=0.25, random_state=10)\nprint('trainX shape=', trainX.shape[0], 'valX shape=', valX.shape[0]) # 750, 250","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"collapsed":true,"_uuid":"6673e914026947e96d26318834ed6ac914ab4e9d"},"cell_type":"code","source":"trainY =  to_categorical(trainY, num_classes=NUM_CLASSES)\nvalY =  to_categorical(valY, num_classes=NUM_CLASSES)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"8925ee30a9086c36f0e8f7cc88ff24e177870051","collapsed":true},"cell_type":"code","source":"#construct the image generator for data augmentation\nprint(\"Generating images...\")\nsys.stdout.flush()\naug = ImageDataGenerator(rotation_range=30, width_shift_range=0.1, \\\n    height_shift_range=0.1, shear_range=0.2, zoom_range=0.2,\\\n    horizontal_flip=True, fill_mode=\"nearest\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"collapsed":true,"_uuid":"ff8002067d4fb19fd8ef9634f3bab2a8daa35b1a"},"cell_type":"code","source":"def createModel():\n    model = Sequential()\n    # first set of CONV => RELU => MAX POOL layers\n    model.add(Conv2D(32, (3, 3), padding='same', activation='relu', input_shape=inputShape))\n    model.add(Conv2D(32, (3, 3), activation='relu'))\n    model.add(MaxPooling2D(pool_size=(2, 2)))\n    model.add(Dropout(0.25))\n    \n    model.add(Conv2D(64, (3, 3), padding='same', activation='relu'))\n    model.add(Conv2D(64, (3, 3), activation='relu'))\n    model.add(MaxPooling2D(pool_size=(2, 2)))\n    model.add(Dropout(0.25))\n    \n    model.add(Conv2D(64, (3, 3), padding='same', activation='relu'))\n    model.add(Conv2D(64, (3, 3), activation='relu'))\n    model.add(MaxPooling2D(pool_size=(2, 2)))\n    model.add(Dropout(0.25))\n    \n    model.add(Flatten())\n    model.add(Dense(512, activation='relu'))\n    model.add(Dropout(0.5))\n    model.add(Dense(output_dim=NUM_CLASSES, activation='softmax'))\n    # returns our fully constructed deep learning + Keras image classifier \n    opt = Adam(lr=INIT_LR, decay=INIT_LR / EPOCHS)\n    # use binary_crossentropy if there are two classes\n    model.compile(loss=\"categorical_crossentropy\", optimizer=opt, metrics=[\"accuracy\"])\n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"55ee93f18f850e1fb144e578778a3b5420637684","collapsed":true},"cell_type":"code","source":"print(\"Reshaping trainX at...\"+ str(datetime.now()))\n#print(trainX.sample()) \nprint(type(trainX)) # <class 'pandas.core.series.Series'>\nprint(trainX.shape) # (750,)\nfrom numpy import zeros\nXtrain = np.zeros([trainX.shape[0],HEIGHT, WIDTH, DEPTH])\nfor i in range(trainX.shape[0]): # 0 to traindf Size -1\n    Xtrain[i] = trainX[i]\nprint(Xtrain.shape) # (750,128,128,3)\nprint(\"Reshaped trainX at...\"+ str(datetime.now()))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"2f61c84f7f96522c7355bd126c8722676c8e3836","collapsed":true},"cell_type":"code","source":"print(\"Reshaping valX at...\"+ str(datetime.now()))\nprint(type(valX)) # <class 'pandas.core.series.Series'>\nprint(valX.shape) # (250,)\nfrom numpy import zeros\nXval = np.zeros([valX.shape[0],HEIGHT, WIDTH, DEPTH])\nfor i in range(valX.shape[0]): # 0 to traindf Size -1\n    Xval[i] = valX[i]\nprint(Xval.shape) # (250,128,128,3)\nprint(\"Reshaped valX at...\"+ str(datetime.now()))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6a66f5862854d1b03730a172f38ef25465fd2421","collapsed":true},"cell_type":"code","source":"# initialize the model\nprint(\"compiling model...\")\nsys.stdout.flush()\nmodel = createModel()\n\n# print the summary of model\nfrom keras.utils import print_summary\nprint_summary(model, line_length=None, positions=None, print_fn=None)\n\n# add some visualization\nfrom IPython.display import SVG\nfrom keras.utils.vis_utils import model_to_dot\nSVG(model_to_dot(model).create(prog='dot', format='svg'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"701909840ec8ee1f5da90a8cac0902d880d4f79a","collapsed":true},"cell_type":"code","source":"# train the network\nprint(\"training network...\")\nsys.stdout.flush()\n#class_mode ='categorical', # 2D one-hot encoded labels\nH = model.fit_generator(aug.flow(Xtrain, trainY, batch_size=BS), \\\n    validation_data=(Xval, valY), \\\n    steps_per_epoch=len(trainX) // BS, \\\n    epochs=EPOCHS, verbose=1)\n\n# save the model to disk\nprint(\"Saving model to disk\")\nsys.stdout.flush()\nmodel.save(\"/tmp/mymodel\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ebaac96c16fc39a6665ac3e8917ca856029f12dc","collapsed":true},"cell_type":"code","source":"# set the matplotlib backend so figures can be saved in the background\n# plot the training loss and accuracy\nprint(\"Generating plots...\")\nsys.stdout.flush()\nmatplotlib.use(\"Agg\")\nmatplotlib.pyplot.style.use(\"ggplot\")\nmatplotlib.pyplot.figure()\nN = EPOCHS\nmatplotlib.pyplot.plot(np.arange(0, N), H.history[\"loss\"], label=\"train_loss\")\nmatplotlib.pyplot.plot(np.arange(0, N), H.history[\"val_loss\"], label=\"val_loss\")\nmatplotlib.pyplot.plot(np.arange(0, N), H.history[\"acc\"], label=\"train_acc\")\nmatplotlib.pyplot.plot(np.arange(0, N), H.history[\"val_acc\"], label=\"val_acc\")\nmatplotlib.pyplot.title(\"Training Loss and Accuracy on diabetic retinopathy detection\")\nmatplotlib.pyplot.xlabel(\"Epoch #\")\nmatplotlib.pyplot.ylabel(\"Loss/Accuracy\")\nmatplotlib.pyplot.legend(loc=\"lower left\")\nmatplotlib.pyplot.savefig(\"plot.png\")","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}