{"cells":[{"metadata":{},"cell_type":"markdown","source":"This is my first kernel, I'm still really new to Kaggle and even to Neural Networks. Hope it will be easy to understand. Let me know if something is not."},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# import the necessary packages\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd\nimport cv2, os\n\nfrom keras.utils import to_categorical\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.preprocessing import LabelEncoder, OneHotEncoder\nfrom keras.preprocessing import image\n\nfrom keras.models import Sequential\nfrom keras.layers import Conv2D\nfrom keras.layers import MaxPooling2D\nfrom keras.layers import Flatten\nfrom keras.layers import Dense\nfrom keras.layers import Dropout\nfrom keras.layers import Activation\nfrom keras.models import model_from_json\n\nfrom keras.layers import BatchNormalization\nfrom keras.layers import Input\nfrom keras.layers import GlobalAveragePooling2D\nfrom keras.applications.resnet50 import ResNet50\nfrom keras.applications.resnet50 import preprocess_input\nfrom keras.models import Model\nfrom keras.optimizers import rmsprop\nimport keras\nimport gc","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Loading CSV and Visualisation"},{"metadata":{"trusted":true},"cell_type":"code","source":"df_train = pd.read_csv('../input/aptos2019-blindness-detection/train.csv')\ndf_test = pd.read_csv('../input/aptos2019-blindness-detection/test.csv')\n\nx = df_train['id_code']\ny = df_train['diagnosis']\n\nunique, counts = np.unique(y, return_counts=True)\n\nplt.subplot()\nplt.hist(y)\nplt.show()\n\nplt.subplot()\nplt.pie(counts, labels=unique, autopct='%1.1f%%', startangle=90)\nplt.show()\n\n# y = to_categorical(y, num_classes=5)\ny = LabelEncoder().fit_transform(y)\n\nSIZE = 256\n\ntrain_x, valid_x, train_y, valid_y = train_test_split(x, y, test_size=0.2, stratify=y)\nprint(train_x.shape, train_y.shape, valid_x.shape, valid_y.shape)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Crédits for this function to :\nhttps://www.kaggle.com/ratthachat/aptos-updatedv14-preprocessing-ben-s-cropping"},{"metadata":{"trusted":true},"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            img = np.stack([img1,img2,img3],axis=-1)\n        return img\n    \n# preprocessing function\ndef preprocess(img):\n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    img = crop_image_from_gray(img)\n    img = cv2.resize(img, (SIZE, SIZE))\n    img = cv2.addWeighted(img,4, cv2.GaussianBlur(img ,(0,0), 30) ,-4 ,128)\n    return img","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fig = plt.figure(figsize=(25, 16))\nfor class_id in sorted(np.unique(train_y)):\n    for i, (idx, row) in enumerate(df_train.loc[df_train['diagnosis'] == class_id].sample(7).iterrows()):\n        ax = fig.add_subplot(5, 7, class_id * 7 + i + 1, xticks=[], yticks=[])\n        path=f\"../input/aptos2019-blindness-detection/train_images/{row['id_code']}.png\"\n        img = preprocess(cv2.imread(path))\n\n        plt.imshow(img)\n        ax.set_title('%d-%d-%s' % (class_id, idx, row['id_code']) )","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Loading Paths"},{"metadata":{},"cell_type":"markdown","source":"We can't load every image in RAM because our test set is really small compared to the hidden one. Kernel will be out of ressources while scoring. So we need to load images one by one as follow and this is why we are loading paths next."},{"metadata":{"trusted":true},"cell_type":"code","source":"train_x_ = []\nfor i in range(len(train_x)):\n    path = os.path.join('../input/aptos2019-blindness-detection/train_images/', train_x[train_x.index[i]]+'.png')\n    train_x_.append(path)\n\nvalid_x_ = []\nfor i in range(len(valid_x)):\n    path = os.path.join('../input/aptos2019-blindness-detection/train_images/', valid_x[valid_x.index[i]]+'.png')\n    valid_x_.append(path)\n\ntest = []\nfor i in range(len(df_test['id_code'])):\n    path = os.path.join('../input/aptos2019-blindness-detection/test_images/', df_test['id_code'][df_test['id_code'].index[i]]+'.png')\n    test.append(path)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Generator and Model"},{"metadata":{"trusted":true},"cell_type":"code","source":"# construct image generator for data augmentation\ntrain_datagen = image.ImageDataGenerator(rotation_range=30,\n                                         zoom_range=0.25,\n                                         width_shift_range=0.2, \n                                         height_shift_range=0.2, \n                                         shear_range=0.15,\n                                         horizontal_flip=True, \n                                         vertical_flip=True,\n                                         fill_mode=\"nearest\",\n                                         preprocessing_function=preprocess,\n                                         rescale=1./255)\n\n# train the network\n\ntrain_path = pd.concat([pd.Series(train_x_), pd.Series(train_y)], axis=1).rename({0:'path',1:'diagnosis'}, axis=1)\nvalid_path = pd.concat([pd.Series(valid_x_), pd.Series(valid_y)], axis=1).rename({0:'path',1:'diagnosis'}, axis=1)\n\ntrain_path['diagnosis'] = train_path['diagnosis'].astype(str)\nvalid_path['diagnosis'] = valid_path['diagnosis'].astype(str)\n\n#fit model\ngen_train = train_datagen.flow_from_dataframe(train_path, x_col='path', y_col='diagnosis', target_size=(SIZE,SIZE), class_mode='categorical')\ngen_valid = train_datagen.flow_from_dataframe(valid_path, x_col='path', y_col='diagnosis', target_size=(SIZE,SIZE), class_mode='categorical')\n\nsteps_train = gen_train.n//gen_train.batch_size\nsteps_valid = gen_valid.n//gen_valid.batch_size","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Next we use transfert learning and then we customize our model :"},{"metadata":{"trusted":true},"cell_type":"code","source":"def create_resnet(img_dim):\n    input_tensor=Input(shape=(img_dim, img_dim,3))\n    base_model = ResNet50(weights=None,\n                          include_top=False,\n                          input_tensor=input_tensor)\n    base_model.load_weights('../input/resnet50/resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5')\n    x=GlobalAveragePooling2D()(base_model.output)\n    x=Dropout(0.3)(x)\n    x=Dense(2048, activation='relu')(x)\n    x=Dropout(0.3)(x)\n    x=Dense(512, activation='relu')(x)\n    x=Dropout(0.3)(x)\n    x=Dense(128, activation='relu')(x)\n    x=Dropout(0.3)(x)\n    x=BatchNormalization()(x)\n    output_layer=Dense(5,activation='softmax', name=\"Output_Layer\")(x)\n    model_resnet=Model(input_tensor, output_layer)\n    return model_resnet\n\nmodel_resnet=create_resnet(SIZE)\n\nfor layers in model_resnet.layers:\n    layers.trainable=True\n    \nmodel_resnet.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"lr = 1e-3\noptimizer=rmsprop(lr=lr,decay=0.2)\nmodel_resnet.compile(optimizer=optimizer, loss=keras.losses.categorical_crossentropy,  metrics=['accuracy'])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Training"},{"metadata":{"trusted":true},"cell_type":"code","source":"history=model_resnet.fit_generator(generator=gen_train,\n                        steps_per_epoch=steps_train,\n                        validation_data=gen_valid,\n                        validation_steps=steps_valid,\n                        epochs=25,\n                        class_weight=counts)\n\ngc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(8, 8))\nplt.title(\"Learning curve\")\nplt.plot(history.history[\"loss\"], label=\"loss\")\nplt.plot(history.history[\"val_loss\"], label=\"val_loss\")\nplt.plot( np.argmin(history.history[\"val_loss\"]), np.min(history.history[\"val_loss\"]), marker=\"x\", color=\"r\", label=\"best model\")\nplt.xlabel(\"Epochs\")\nplt.ylabel(\"log_loss\")\nplt.legend()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Test"},{"metadata":{"trusted":true},"cell_type":"code","source":"# making predictions\n\nprediction = []\nsample = pd.read_csv('../input/aptos2019-blindness-detection/sample_submission.csv')\n\nfor path in test:\n    img = preprocess(cv2.imread(path))\n    score_predict = model_resnet.predict((img[np.newaxis])/255.)\n    label_predict = np.argmax(score_predict)\n    prediction.append(str(label_predict))\n    \nsample['diagnosis'] = prediction\nsample.to_csv('submission.csv', index=False)\n\nprint(sample.head(20))\n\niii,ii = np.unique(sample['diagnosis'], return_counts=True)\nprint('\\n',ii)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Save"},{"metadata":{},"cell_type":"markdown","source":"We save weights in case we want to try something new on this already trained model."},{"metadata":{"trusted":true},"cell_type":"code","source":"# serialize model to JSON\nmodel_json = model_resnet.to_json()\nwith open(\"model.json\", \"w\") as json_file:\n    json_file.write(model_json)\n    \n# serialize weights to HDF5\nmodel_resnet.save_weights(\"model.h5\")\nprint(\"Saved model to disk\")","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}