{"cells":[{"metadata":{},"cell_type":"markdown","source":"References Used:\n\n1 - [Transfer Learning using Keras and VGG](http://https://riptutorial.com/keras/example/32608/transfer-learning-using-keras-and-vgg)\n\n2 - [VGG16 and VGG19](http://keras.io/api/applications/vgg/)"},{"metadata":{},"cell_type":"markdown","source":"# Import required Libraries"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nfrom tensorflow.keras.layers import Dense, Dropout\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.optimizers import Adam\nfrom keras.callbacks import EarlyStopping\nimport tensorflow as tf\nfrom PIL import Image\nimport os\nimport matplotlib.pyplot as plt\nfrom collections import Counter","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# First --> Define the data working paths"},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"main_directory = '/kaggle/input/cassava-leaf-disease-classification/'\ntraining_images_path = main_directory + 'train_images'\nprint('List of Files:\\n',os.listdir(main_directory))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"## image_label_data is the file containing the data \n## which matches eah image file to its corresponding label\nimage_label_data = pd.read_csv(main_directory + 'train.csv')\nlabels = pd.read_json(main_directory + 'label_num_to_disease_map.json', typ='series')\n\nprint('Cassava Leaf Disease Classification Labels are:\\n',dict(labels))\nimage_label_data.sample(10)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Classes Balance:\n\nIt shows that there is an unbalace in the whole images available"},{"metadata":{"trusted":true},"cell_type":"code","source":"print(Counter(image_label_data['label']))\nimage_label_data['label'].value_counts(normalize = True)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Second --> Images to Labels Mapping"},{"metadata":{"trusted":true},"cell_type":"code","source":"image_label_data['disease_name'] = image_label_data.label.map(labels)\nprint(image_label_data)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Third --> Data Splitting for Training and Validation Steps"},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\nTEST_PERCENTAGE = 0.05\n\ntrain_set_splitted, validation_set_splitted = train_test_split(image_label_data, test_size = TEST_PERCENTAGE, random_state = 42,\n                             # Stratify:\n                             # is to make sure that all the testing labels\n                             # has the same % of labels as the whole dataset and\n                             # not to take random images\n                             # 95% trainning set --> \n                             # Ex: Class (3) has 13158 images, so 13158*95% = 12500.\n                             #     Class (4) has 2577 images, so 2577*95% = 2448.\n                             stratify = image_label_data['disease_name'])\n\n#print('Training Dataset:\\n',dict(Counter(list(train_set['label']))))\n#print('\\nValidation Dataset:\\n',dict(Counter(list(validation_set['label']))))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Fourth --> Image Augmentation with KERAS ImageDataGenerator"},{"metadata":{"trusted":true},"cell_type":"code","source":"# By using ImageDataGenerator we can make an on-fly image Augmentation\n\nfrom keras.preprocessing.image import ImageDataGenerator\n\nIMAGE_WIDTH = 224\nIMAGE_HEIGHT = 224\nIMAGE_SIZE = (IMAGE_WIDTH, IMAGE_HEIGHT)\nNO_OF_CLASSES = 5\nBATCH_SIZE = 20\n\n## Frist We have to make the IMAGE_DATA_GENERATOR variable for both\n## Training and Validation sets\n\nTrainingImageGenerator = ImageDataGenerator( \n                                            preprocessing_function = tf.keras.applications.vgg19.preprocess_input,\n                                            horizontal_flip = True,\n                                            vertical_flip = True,\n                                            fill_mode = 'nearest'\n                                            )\n\nValidatonImageGenerator = ImageDataGenerator( \n                                            preprocessing_function = tf.keras.applications.vgg19.preprocess_input)\n\n\ntraining_dataset = TrainingImageGenerator.flow_from_dataframe(\n                                                         train_set_splitted,\n                                                         directory = training_images_path,\n                                                         seed=9806,\n                                                         x_col = 'image_id',\n                                                         y_col = 'disease_name',\n                                                         target_size = IMAGE_SIZE,\n                                                         class_mode = 'categorical',\n                                                         interpolation = 'nearest',\n                                                         shuffle = True,\n                                                         batch_size = BATCH_SIZE)\n\nvalidation_dataset = ValidatonImageGenerator.flow_from_dataframe(\n                                                         validation_set_splitted,\n                                                         directory = training_images_path,\n                                                         seed=9806,\n                                                         x_col = 'image_id',\n                                                         y_col = 'disease_name',\n                                                         target_size = IMAGE_SIZE,\n                                                         class_mode = 'categorical',\n                                                         interpolation = 'nearest',\n                                                         shuffle = True,\n                                                         batch_size = BATCH_SIZE)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Fifth --> Create the Neural Network Model\n\n# Transfer Learning using Keras and VGG-19\n\nLoading weights from available pre-trained model"},{"metadata":{"trusted":true},"cell_type":"code","source":"import keras\nfrom keras.models import Sequential\nfrom keras.layers import GlobalAveragePooling2D, Flatten, Dense, Dropout, BatchNormalization\nfrom keras.optimizers import RMSprop, Adam, SGD\nfrom keras.callbacks import EarlyStopping, ModelCheckpoint, ReduceLROnPlateau\nfrom tensorflow.keras.applications import VGG19\n\nLOAD_MODEL = True\n\nif not LOAD_MODEL:\n    CassaveDisease_model = Sequential(name='Cassava_Neural_Network')\n    CassaveDisease_model.add(VGG19(input_shape = (IMAGE_WIDTH, IMAGE_HEIGHT, 3),\n                                   include_top = False,\n                                   weights = 'imagenet'))\n    CassaveDisease_model.add(GlobalAveragePooling2D())\n    CassaveDisease_model.add(Flatten())\n    CassaveDisease_model.add(Dense(256, activation = 'relu'#, bias_regularizer=tf.keras.regularizers.L1L2(l1=0.01, l2=0.001)\n                                  ))\n    #CassaveDisease_model.add(Dropout(0.5))\n    CassaveDisease_model.add(BatchNormalization());\n    CassaveDisease_model.add(Dense(NO_OF_CLASSES, activation = 'softmax'))\n\n    CassaveDisease_model.summary()\n    keras.utils.plot_model(CassaveDisease_model)\n    \n    ## Optimizer Definition\n    Adam_Optimizer = Adam(learning_rate = 0.001)\n\n    CassaveDisease_model.compile(\n                                loss = \"categorical_crossentropy\", \n                                optimizer = Adam_Optimizer, \n                                metrics = [\"accuracy\"])\n\nelse:\n    CassaveDisease_model = keras.models.load_model('../input/84-percentage-model/Cassava_best_Model_Reached_best_model_7_Jan_04_acc_is_86.h5')\n    print('Model Loaded Successfully!')\n    CassaveDisease_model.optimizers = Adam(learning_rate = 0.00002)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"-----------------------------------------------\n1 - Define the Optimizer that we are going to use\n\n2 - Compile the Neural Network Created"},{"metadata":{"trusted":true},"cell_type":"code","source":"## Epoches Definition\nEPOCHES = 5\n\n## The model fitting will stop if no improvement occured during consecutive 3 EPOCES\nEPOCHES_TO_WAIT_WITH_NO_IMPORVEMENT = 3\n\nEARLY_STOP = EarlyStopping(monitor='val_accuracy',\n                           patience = EPOCHES_TO_WAIT_WITH_NO_IMPORVEMENT,\n                           restore_best_weights = True)\n\n# Save the Cassava Model with only the minimum validation loss reached\nBEST_MODEL_REACHED = ModelCheckpoint(filepath = \"./Cassava_best_Model_Reached_best_model_8_Jan_03.h5\",\n                                save_best_only = True,\n                                monitor = 'val_loss',\n                                mode = 'min')\n\n# Reduce learning rate\n# if no improvement is seen for a 'patience' number of epochs, the learning rate is reduced\nREDUCE_LR = ReduceLROnPlateau(monitor = 'val_loss',\n                              factor = 0.2,\n                              patience = 2,\n                              min_lr = 1e-6,\n                              mode = 'min',\n                              verbose = 1)\n\nTrained_Model = CassaveDisease_model.fit(\n                        training_dataset,\n                        validation_data = validation_dataset, \n                        epochs = EPOCHES,\n                        callbacks = [EARLY_STOP,\n                                     BEST_MODEL_REACHED,\n                                     REDUCE_LR],\n                        verbose=1)\n\nCassaveDisease_model.save(\"./Cassava_best_Model_Reached_8_jan_03.h5\")\nprint(\"Model Saved Successfully!\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(Trained_Model.history.keys())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def Train_Val_Plot(acc,val_acc,loss,val_loss):\n    \n    fig, (ax1, ax2) = plt.subplots(1,2, figsize= (15,10))\n    fig.suptitle(\" MODEL'S METRICS VISUALIZATION \", fontsize=20)\n\n    ax1.plot(range(1, len(acc) + 1), acc)\n    ax1.plot(range(1, len(val_acc) + 1), val_acc)\n    ax1.set_title('History of Accuracy', fontsize=15)\n    ax1.set_xlabel('Epochs', fontsize=15)\n    ax1.set_ylabel('Accuracy', fontsize=15)\n    ax1.legend(['training', 'validation'])\n\n\n    ax2.plot(range(1, len(loss) + 1), loss)\n    ax2.plot(range(1, len(val_loss) + 1), val_loss)\n    ax2.set_title('History of Loss', fontsize=15)\n    ax2.set_xlabel('Epochs', fontsize=15)\n    ax2.set_ylabel('Loss', fontsize=15)\n    ax2.legend(['training', 'validation'])\n    plt.show()\n    \n\n#Train_Val_Plot(Trained_Model.history['accuracy'],Trained_Model.history['val_accuracy'],\n#               Trained_Model.history['loss'],Trained_Model.history['val_loss'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"TEST_DIR = '../input/cassava-leaf-disease-classification/test_images/'\ntest_images = os.listdir(TEST_DIR)\npredictions = []\nsize = (IMAGE_WIDTH, IMAGE_HEIGHT)\nfor image in test_images:\n    img = Image.open(TEST_DIR + image)\n    img = img.resize(size)\n    img = np.expand_dims(img, axis=0)\n    predictions.extend(CassaveDisease_model.predict(img).argmax(axis = 1))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(predictions)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Creating the CSV for final submission\n\nsub = pd.DataFrame({'image_id': test_images, 'label': predictions})\ndisplay(sub)\nsub.to_csv('submission.csv', index = False)","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}