{"cells":[{"metadata":{},"cell_type":"markdown","source":"<h1 style=\"text-align:center;color:orange;background-color:black\">Cassava Leaf Disease Classification: CNN Starter</h1>\n\nThis competition will challenge you to distinguish between several diseases that cause material harm to the food supply of many African countries. In some cases the main remedy is to burn the infected plants to prevent further spread, which can make a rapid automated turnaround quite useful to the farmers."},{"metadata":{},"cell_type":"markdown","source":"<h1 style=\"text-align:center;color:orange;background-color:black\">Import packages</h1>"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"_kg_hide-output":true,"_kg_hide-input":true},"cell_type":"code","source":"import numpy as np\nimport pandas as pd\n\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import accuracy_score\n\nimport tensorflow as tf\nfrom tensorflow.keras import models, layers\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping, ReduceLROnPlateau\nfrom tensorflow.keras.applications import ResNet50, DenseNet121, EfficientNetB0\nfrom tensorflow.keras.optimizers import Adam\n\nimport datetime\nimport os\nimport cv2\nimport json\nfrom PIL import Image\n# ignoring warnings\nimport warnings\nwarnings.simplefilter(\"ignore\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"BASE_DIR = '/kaggle/input/cassava-leaf-disease-classification'\nos.listdir(BASE_DIR)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"In this competition we have 5 classes: 4 diseases and 1 healthy\nWe can find the mapping between the class number and its name in the file label_num_to_disease_map.json"},{"metadata":{"trusted":true},"cell_type":"code","source":"with open(os.path.join(BASE_DIR, \"label_num_to_disease_map.json\")) as file:\n    map_classes = json.loads(file.read())\n    \nprint(json.dumps(map_classes, indent=4))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h1 style=\"text-align:center;color:orange;background-color:black\">Load and look at the data</h1>"},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Train images: %d' %len(os.listdir(\n    os.path.join(BASE_DIR, \"train_images\"))))\nprint('Test images: %d' %len(os.listdir(\n    os.path.join(BASE_DIR, \"test_images\"))))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_images = os.listdir(os.path.join(BASE_DIR, \"train_images\"))\ntest_images = os.listdir(os.path.join(BASE_DIR, \"test_images\"))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h3 style=\"text-align:center;color:orange;background-color:black\">Loading the training dataframe and add a column with the real class name to it.</h3>\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"df_train = pd.read_csv(os.path.join(BASE_DIR, \"train.csv\"))\ndf_train[\"class_name\"] = df_train[\"label\"].astype(str).map(map_classes)\ndf_train.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h3 style=\"text-align:center;color:orange;background-color:black\">Looking at the number of pictures in each class.</h3>"},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(8, 4))\nsns.countplot(x=\"label\", data=df_train, edgecolor = 'orange',\n              palette = sns.color_palette(\"viridis\", 5))\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We have imbalanced data with domination of third class: `Cassava Mosaic Disease (CMD)`"},{"metadata":{},"cell_type":"markdown","source":"<h1 style=\"text-align:center;color:orange;background-color:black\">General Visualization</h1>"},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"def visualize_batch(image_ids, labels):\n    plt.figure(figsize=(16, 12))\n    for ind, (image_id, label) in enumerate(zip(image_ids, labels)):\n        plt.subplot(3, 3, ind + 1)\n        image = cv2.imread(os.path.join(BASE_DIR, \"train_images\", image_id))\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n\n        plt.imshow(image)\n        plt.title(f\"Class: {label}\", fontsize=12)\n        plt.axis(\"off\")\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"tmp_df = df_train.sample(6)\nimage_ids = tmp_df[\"image_id\"].values\nlabels = tmp_df[\"class_name\"].values\nvisualize_batch(image_ids, labels)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h1 style=\"text-align:center;color:orange;background-color:black\">Cassava Bacterial Blight (CBB)</h1>"},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"tmp_df = df_train[df_train[\"label\"] == 0]\nprint(f\"Total train images for class 0: {tmp_df.shape[0]}\")\n\ntmp_df = tmp_df.sample(6)\nimage_ids = tmp_df[\"image_id\"].values\nlabels = tmp_df[\"class_name\"].values\n\nvisualize_batch(image_ids, labels)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h1 style=\"text-align:center;color:orange;background-color:black\">Cassava Brown Streak Disease (CBSD)</h1>"},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"tmp_df = df_train[df_train[\"label\"] == 1]\nprint(f\"Total train images for class 1: {tmp_df.shape[0]}\")\n\ntmp_df = tmp_df.sample(6)\nimage_ids = tmp_df[\"image_id\"].values\nlabels = tmp_df[\"class_name\"].values\n\nvisualize_batch(image_ids, labels)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h1 style=\"text-align:center;color:orange;background-color:black\">Cassava Green Mottle (CGM)</h1>"},{"metadata":{"trusted":true},"cell_type":"code","source":"tmp_df = df_train[df_train[\"label\"] == 2]\nprint(f\"Total train images for class 2: {tmp_df.shape[0]}\")\n\ntmp_df = tmp_df.sample(6)\nimage_ids = tmp_df[\"image_id\"].values\nlabels = tmp_df[\"class_name\"].values\n\nvisualize_batch(image_ids, labels)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h1 style=\"text-align:center;color:orange;background-color:black\">Cassava Mosaic Disease (CMD)</h1>"},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"tmp_df = df_train[df_train[\"label\"] == 3]\nprint(f\"Total train images for class 3: {tmp_df.shape[0]}\")\n\ntmp_df = tmp_df.sample(6)\nimage_ids = tmp_df[\"image_id\"].values\nlabels = tmp_df[\"class_name\"].values\n\nvisualize_batch(image_ids, labels)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h1 style=\"text-align:center;color:orange;background-color:black\">Healthy</h1>"},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"tmp_df = df_train[df_train[\"label\"] == 4]\nprint(f\"Total train images for class 4: {tmp_df.shape[0]}\")\n\ntmp_df = tmp_df.sample(6)\nimage_ids = tmp_df[\"image_id\"].values\nlabels = tmp_df[\"class_name\"].values\n\nvisualize_batch(image_ids, labels)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h1 style=\"text-align:center;color:orange;background-color:black\">Baseline level of accuracy</h1>"},{"metadata":{"trusted":true},"cell_type":"code","source":"y_pred = [3] * len(df_train.label)\nprint('The baseline accuracy: %.3f' \n      %accuracy_score(y_pred, df_train.label))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h1 style=\"text-align:center;color:orange;background-color:black\">Prepare Data For Model</h1>"},{"metadata":{"trusted":true},"cell_type":"code","source":"BATCH_SIZE = 128\nSTEPS_PER_EPOCH = len(df_train)*0.8 / BATCH_SIZE\nVALIDATION_STEPS = len(df_train)*0.2 / BATCH_SIZE\nEPOCHS = 50\nTARGET_SIZE = 224","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_train.label = df_train.label.astype('str')\n\ntrain_generator = ImageDataGenerator(validation_split = 0.2,\n                                     preprocessing_function = None,\n                                     zoom_range = 0.15,\n                                     cval = 0.,\n                                     horizontal_flip = True,\n                                     vertical_flip = True,\n                                     fill_mode = 'nearest') \\\n    .flow_from_dataframe(df_train,\n                         directory = os.path.join(BASE_DIR, \"train_images\"),\n                         subset = \"training\",\n                         x_col = \"image_id\",\n                         y_col = \"label\",\n                         target_size = (TARGET_SIZE, TARGET_SIZE),\n                         batch_size = BATCH_SIZE,\n                         class_mode = \"sparse\")\n\nvalidation_generator = ImageDataGenerator(validation_split = 0.2) \\\n    .flow_from_dataframe(df_train,\n                         directory = os.path.join(BASE_DIR, \"train_images\"),\n                         subset = \"validation\",\n                         x_col = \"image_id\",\n                         y_col = \"label\",\n                         target_size = (TARGET_SIZE, TARGET_SIZE),\n                         batch_size = BATCH_SIZE,\n                         class_mode = \"sparse\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def create_model():\n    model = models.Sequential()\n\n    model.add(EfficientNetB0(include_top = False, weights = 'imagenet',\n                             input_shape = (TARGET_SIZE, TARGET_SIZE, 3)))\n    \n    model.add(layers.GlobalAveragePooling2D())\n    model.add(layers.Dense(5, activation = \"softmax\"))\n\n    model.compile(optimizer = Adam(lr = 0.001),\n                  loss = \"sparse_categorical_crossentropy\",\n                  metrics = [\"acc\"])\n    return model","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"model = create_model()\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"model_save = ModelCheckpoint('./best_baseline_model_30.h5', \n                             save_best_only = True, \n                             save_weights_only = True,\n                             monitor = 'val_loss', \n                             mode = 'min', verbose = 1)\nearly_stop = EarlyStopping(monitor = 'val_loss', min_delta = 0.001, \n                           patience = 5, mode = 'min', verbose = 1,\n                           restore_best_weights = True)\nreduce_lr = ReduceLROnPlateau(monitor = 'val_loss', factor = 0.1, \n                              patience = 2, min_delta = 0.001, \n                              mode = 'min', verbose = 1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"history = model.fit_generator(\n    train_generator,\n    steps_per_epoch = STEPS_PER_EPOCH,\n    epochs = EPOCHS,\n    validation_data = validation_generator,\n    validation_steps = VALIDATION_STEPS,\n    callbacks = [model_save, early_stop, reduce_lr]\n)","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"acc = history.history['acc']\nval_acc = history.history['val_acc']\nloss = history.history['loss']\nval_loss = history.history['val_loss']\n\nepochs = range(1, len(acc) + 1)\n\nfig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 5))\nsns.set_style(\"white\")\nplt.suptitle('Train history', size = 15)\n\nax1.plot(epochs, acc, \"bo\", label = \"Training acc\")\nax1.plot(epochs, val_acc, \"b\", label = \"Validation acc\")\nax1.set_title(\"Training and validation acc\")\nax1.legend()\n\nax2.plot(epochs, loss, \"bo\", label = \"Training loss\", color = 'red')\nax2.plot(epochs, val_loss, \"b\", label = \"Validation loss\", color = 'red')\nax2.set_title(\"Training and validation loss\")\nax2.legend()\n\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.save('./baseline_model.h5')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## WORK IN PROGRESS..."}],"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}