{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Cassava Leaf Disease Detection "},{"metadata":{},"cell_type":"markdown","source":"**Import Required packages**"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import os\nimport glob\nimport shutil\nimport json\nimport keras \nimport itertools\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport tensorflow as tf\nfrom PIL import Image\nimport matplotlib.pyplot as plt\nfrom keras.models import Sequential\nfrom keras.optimizers import RMSprop, Adam\nfrom tensorflow.keras.applications import ResNet50\nfrom tensorflow.keras.applications import EfficientNetB4\nfrom tensorflow.keras.applications import VGG16\nfrom sklearn.model_selection import train_test_split\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.layers import GlobalAveragePooling2D, Flatten, Dense, Dropout\nfrom keras.callbacks import EarlyStopping, ModelCheckpoint, ReduceLROnPlateau\n!pip install -U efficientnet\nimport efficientnet.keras as efn\nfrom tensorflow.keras.mixed_precision import experimental as mixed_precision\npolicy = mixed_precision.Policy('mixed_float16')\nmixed_precision.set_policy(policy)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"work_dir = '../input/cassava-leaf-disease-classification/'\nos.listdir(work_dir) \ntrain_path = '/kaggle/input/cassava-leaf-disease-classification/train_images'","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"data = pd.read_csv(work_dir + 'train.csv')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Let's Have a look at the Class Distribution**"},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"data['label'].value_counts()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Add the class names for better understanding of the labels**"},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"f = open(work_dir + 'label_num_to_disease_map.json')\nreal_labels = json.load(f)\nreal_labels = {int(k):v for k,v in real_labels.items()}\n\ndata['class_name'] = data['label'].map(real_labels)\ndata.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Before anything, let's split the data to train and validation, since I can't have test images before submission**"},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"train,val = train_test_split(data, test_size = 0.25, random_state = 7, stratify = data['class_name'])","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"print(f\"The train size : {train.shape} \\nThe Validation size : {val.shape}\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Trying out ResNet50 on imagenet weights**"},{"metadata":{"trusted":true},"cell_type":"code","source":"IMG_SIZE = 512\nsize = (IMG_SIZE,IMG_SIZE)\nn_CLASS = 5\nBATCH_SIZE = 8\n# prep_func = tf.keras.applications.resnet50.preprocess_input\n# prep_func_vgg16 = tf.keras.applications.vgg16.preprocess_input\n\ndatagen_train = ImageDataGenerator(\n#                     preprocessing_function = prep_func_vgg16,\n                    rotation_range = 40,\n                    width_shift_range = 0.2,\n                    height_shift_range = 0.2,\n                    shear_range = 0.2,\n                    zoom_range = 0.2,\n                    horizontal_flip = True,\n                    vertical_flip = True,\n                    fill_mode = 'nearest')\n\ndatagen_val = ImageDataGenerator(\n#                     preprocessing_function = prep_func_vgg16,\n                    )\n\ntrain_set = datagen_train.flow_from_dataframe(train,\n                             directory = train_path,\n                             seed=7,\n                             x_col = 'image_id',\n                             y_col = 'class_name',\n                             target_size = size,\n                             class_mode = 'categorical',\n                             interpolation = 'nearest',\n                             shuffle = True,\n                             batch_size = BATCH_SIZE)\n\nval_set = datagen_val.flow_from_dataframe(val,\n                             directory = train_path,\n                             seed=7,\n                             x_col = 'image_id',\n                             y_col = 'class_name',\n                             target_size = size,\n                             #color_mode=\"rgb\",\n                             class_mode = 'categorical',\n                             interpolation = 'nearest',\n                             shuffle = True,\n                             batch_size = BATCH_SIZE)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def create_model_resnet50():\n    \n    model = Sequential()\n    model.add(ResNet50(input_shape = (IMG_SIZE, IMG_SIZE, 3), include_top = False, weights = 'imagenet'))\n    model.add(GlobalAveragePooling2D())\n    model.add(Flatten())\n    model.add(Dense(512, activation = 'relu', bias_regularizer=tf.keras.regularizers.L1L2(l1=0.01, l2=0.001)))\n    model.add(Dropout(0.7))\n    model.add(Dense(n_CLASS, activation = 'softmax'))\n    \n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def create_model_vgg16():\n    \n    model = Sequential()\n    model.add(VGG16(input_shape = (IMG_SIZE, IMG_SIZE, 3), include_top = False, weights = 'imagenet'))\n    model.add(GlobalAveragePooling2D())\n    model.add(Flatten())\n    model.add(Dense(512, activation = 'relu', bias_regularizer=tf.keras.regularizers.L1L2(l1=0.01, l2=0.001)))\n    model.add(Dropout(0.5))\n    model.add(Dense(n_CLASS, activation = 'softmax'))\n    \n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def create_model_effnetb4():\n    \n    model = Sequential()\n    e = efn.EfficientNetB4(input_shape = (IMG_SIZE, IMG_SIZE, 3), include_top = False, weights = 'noisy-student')\n#     for i in e.layers:\n#         if isinstance(i, keras.layers.BatchNormalization):\n#             i.trainable = False\n    model.add(e)\n    model.add(GlobalAveragePooling2D())\n    model.add(Dense(64, activation = 'relu', bias_regularizer=tf.keras.regularizers.L1L2(l1=0.01, l2=0.001)))\n    model.add(Dropout(0.5))\n    model.add(Dense(n_CLASS, activation = 'softmax',dtype='float32'))\n    \n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# resnet50 = create_model_resnet50()\n# vgg16 = create_model_vgg16()\n# effnetb4 = create_model_effnetb4()\neffnetb4 = keras.models.load_model('../input/cassava-challenge-models/Cassava_best_model_effnetb4.h5')\nkeras.utils.plot_model(effnetb4)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"EPOCHS = 40\nSTEP_SIZE_TRAIN = train_set.n//train_set.batch_size\nSTEP_SIZE_VALID = val_set.n//val_set.batch_size","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"loss = tf.keras.losses.CategoricalCrossentropy(from_logits = False,\n                                               label_smoothing=0.2,\n                                               name='categorical_crossentropy' )\n    \neffnetb4.compile(optimizer = Adam(learning_rate = 1e-3),\n                loss = loss, #'categorical_crossentropy'\n                metrics = ['categorical_accuracy']) #'acc'\n\n# Stop training when the val_loss has stopped decreasing for 3 epochs.\nes = EarlyStopping(monitor='val_loss', mode='min', patience=3,\n               restore_best_weights=True, verbose=1)\n\n# Save the model with the minimum validation loss\ncheckpoint_cb = ModelCheckpoint(\"effnetb4 with noisy student weights.h5\",\n                            save_best_only=True,\n                            monitor = 'val_loss',\n                            mode='min')\n\n# reduce learning rate\nreduce_lr = ReduceLROnPlateau(monitor = 'val_loss',\n                          factor = 0.3,\n                          patience = 2,\n                          min_lr = 1e-6,\n                          mode = 'min',\n                          verbose = 1)\n\nhistory = effnetb4.fit(train_set,\n                     validation_data = val_set,\n                     epochs= EPOCHS,\n                     batch_size = BATCH_SIZE,\n                     #class_weight = d_class_weights,\n                     steps_per_epoch = STEP_SIZE_TRAIN,\n                     validation_steps = STEP_SIZE_VALID,\n                     callbacks=[es, checkpoint_cb, reduce_lr])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Submission Notebook : [Here](https://www.kaggle.com/mohneesh7/submission-notebook-for-cassava)**"},{"metadata":{"trusted":true},"cell_type":"code","source":"","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}