{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport math\nimport cv2\nimport os\nimport sys\nimport csv\nimport time\nimport re\nimport keras\nimport collections\nimport json\nimport seaborn as sns\nimport matplotlib as mpl\nimport matplotlib.pyplot as plt\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras import applications\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.layers import Dense, Dropout, BatchNormalization, GlobalAveragePooling2D\nfrom kaggle_datasets import KaggleDatasets\nfrom functools import partial\nfrom sklearn.model_selection import train_test_split\nfrom scipy import stats\nimport shutil","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**DATA ANALYSIS**"},{"metadata":{"trusted":true},"cell_type":"code","source":"base_path = \"../input/cassava-leaf-disease-classification/\"\nsample_path = \"../input/cassava-leaf-disease-classification/sample_submission.csv\"\ntrain_path = \"../input/cassava-leaf-disease-classification/train.csv\"\ntest_path = \"../input/cassava-leaf-disease-classification/test_images\"\nlabel_json_path = \"../input/cassava-leaf-disease-classification/label_num_to_disease_map.json\"\nimages_dir_path = \"../input/cassava-leaf-disease-classification/train_images\"\n\ntrain_csv = pd.read_csv(train_path)\ntrain_csv['label'] = train_csv['label'].astype('string')\n\nlabel_class = pd.read_json(label_json_path, orient='index')\nlabel_class = label_class.values.flatten().tolist()\n\n\ninput_files = os.listdir(os.path.join(base_path, \"train_images\"))\nprint(f\"Number of images in the dataset: {len(input_files)}\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"There are 5 classes in the dataset:"},{"metadata":{"trusted":true},"cell_type":"code","source":"with open(os.path.join(base_path, \"label_num_to_disease_map.json\")) as file:\n    map_classes = json.loads(file.read())\n    map_classes = {int(k) : v for k, v in map_classes.items()}\n    \nprint(json.dumps(map_classes, indent=4))\n\n#print(\"Number of unique classes:\", num_classes)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"samples = 30000\ndf = pd.read_csv(\"../input/cassava-leaf-disease-classification/train.csv\")\ndf_test = pd.read_csv(sample_path)\ndf = df.loc[:samples,:]\nnum_classes = len(df[\"label\"].unique())\nnum_data = len(df)\ndf.head()#Prints the first 5 entries in the data file to get an idea of how the data is formatted","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Number of images per class:"},{"metadata":{"trusted":true},"cell_type":"code","source":"data = pd.DataFrame(df['label'].value_counts()) \ndata.reset_index(inplace=True) \ndata.columns=['class','no. of images']\n\nprint(data.head(10))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Histogram plot showing the number of images per class:"},{"metadata":{"trusted":true},"cell_type":"code","source":"with open('/kaggle/input/cassava-leaf-disease-classification/label_num_to_disease_map.json', 'r') as f:\n    json_data = json.load(f)\n\n    sort_train = df.label.value_counts().reset_index()\nsort_train['disease'] = sort_train['index'].apply(lambda x: str(x)+' : '+json_data[str(x)])\n\nprint(collections.Counter(df.label))\nsns.barplot(y=sort_train.disease, x=sort_train.label)\nplt.xlabel(''); plt.ylabel('')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Plotting four random images from 4 random classes:"},{"metadata":{"trusted":true},"cell_type":"code","source":"def visualize_batch(image_ids, labels):\n    plt.figure(figsize=(16, 12))\n    \n    for ind, (image_id, label) in enumerate(zip(image_ids, labels)):\n        plt.subplot(4, 4, ind + 1)\n        image = cv2.imread(os.path.join(base_path, \"train_images\", image_id))\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n\n        plt.imshow(image)\n        plt.axis(\"off\")\n    \n    plt.show()\n    \n\ntmp_df = df.sample(16)\nimage_ids = tmp_df[\"image_id\"].values\nlabels = tmp_df[\"label\"].values\n\nvisualize_batch(image_ids, labels)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Data augmentation and preprocessing**"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Data agumentation and pre-processing \nBATCH_SIZE = 48\nIMG_SIZE = 320\n\ntrain_gen = ImageDataGenerator(\n                                rotation_range=270,\n                                width_shift_range=0.2,\n                                height_shift_range=0.2,\n                                brightness_range=[0.1,0.9],\n                                shear_range=25,\n                                zoom_range=0.3,\n                                channel_shift_range=0.1,\n                                horizontal_flip=True,\n                                vertical_flip=True,\n                                rescale=1/255,\n                                validation_split=0.2\n                               )\n                                    \n    \nvalid_gen = ImageDataGenerator(rescale=1/255,\n                               validation_split = 0.2\n                              )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_generator = train_gen.flow_from_dataframe(\n                            dataframe=train_csv,\n                            directory = images_dir_path,\n                            x_col = \"image_id\",\n                            y_col = \"label\",\n                            target_size = (IMG_SIZE, IMG_SIZE),\n                            class_mode = \"categorical\",\n                            batch_size = BATCH_SIZE,\n                            shuffle = True,\n                            subset = \"training\",\n\n)\n\nvalid_generator = valid_gen.flow_from_dataframe(\n                            dataframe=train_csv,\n                            directory = images_dir_path,\n                            x_col = \"image_id\",\n                            y_col = \"label\",\n                            target_size = (IMG_SIZE, IMG_SIZE),\n                            class_mode = \"categorical\",\n                            batch_size = BATCH_SIZE,\n                            shuffle = False,\n                            subset = \"validation\"\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"batch = next(train_generator)\nimages = batch[0]\nlabels = batch[1]\n\nplt.figure(figsize=(15,9))\nfor i, (img, label) in enumerate(zip(images, labels)):\n    plt.subplot(5,3, i%15 +1)\n    plt.axis('off')\n    plt.imshow(img)\n    plt.title(label_class[np.argmax(label)])\n    \n    if i==15:\n        break","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Model building**"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Loading the InceptionResNetV2 architecture with imagenet weights as baseline architecture\nbase = applications.InceptionResNetV2(include_top=False, weights='imagenet',input_shape=[IMG_SIZE,IMG_SIZE,3])\n#base.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = tf.keras.Sequential()\nmodel.add(base)\nmodel.add(BatchNormalization(axis=-1))\nmodel.add(GlobalAveragePooling2D())\nmodel.add(Dropout(0.5))\nmodel.add(Dense(256, activation='relu'))\nmodel.add(Dense(5, activation='softmax'))\n\nmodel.compile(loss=tf.keras.losses.CategoricalCrossentropy(), optimizer=tf.keras.optimizers.SGD(learning_rate=0.001, momentum=0.9), metrics=['acc', tf.keras.metrics.TruePositives(name='tp')])\n#model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def scheduler(epoch, lr):\n    if epoch >3 and epoch%2==0:\n        return lr/1.25\n    else:\n        return lr\n\n# A callback to save the model\ncallback0 = tf.keras.callbacks.ModelCheckpoint(\"./Cassava.h5\", \n                                               monitor='val_loss',save_best_only=True)\n\n# A callback to reduce the learning rate with increase in epoch\ncallback1 = tf.keras.callbacks.LearningRateScheduler(scheduler)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**TRAINING**"},{"metadata":{"trusted":true},"cell_type":"code","source":"def plot_history(history):\n    loss_list = [s for s in history.history.keys() if 'loss' in s and 'val' not in s]\n    val_loss_list = [s for s in history.history.keys() if 'loss' in s and 'val' in s]\n    acc_list = [s for s in history.history.keys() if 'acc' in s and 'val' not in s]\n    val_acc_list = [s for s in history.history.keys() if 'acc' in s and 'val' in s]\n    \n    if len(loss_list) == 0:\n        print('Loss is missing in history')\n        return \n    \n\n    epochs = range(1,len(history.history[loss_list[0]]) + 1)\n    \n    ## Loss\n    plt.figure(1)\n    for l in loss_list:\n        plt.plot(epochs, history.history[l], 'b', label='Training loss (' + str(str(format(history.history[l][-1],'.5f'))+')'))\n    for l in val_loss_list:\n        plt.plot(epochs, history.history[l], 'g', label='Validation loss (' + str(str(format(history.history[l][-1],'.5f'))+')'))\n    \n    plt.title('Loss')\n    plt.xlabel('Epochs')\n    plt.ylabel('Loss')\n    plt.legend()\n    \n    ## Accuracy\n    plt.figure(2)\n    for l in acc_list:\n        plt.plot(epochs, history.history[l], 'b', label='Training accuracy (' + str(format(history.history[l][-1],'.5f'))+')')\n    for l in val_acc_list:    \n        plt.plot(epochs, history.history[l], 'g', label='Validation accuracy (' + str(format(history.history[l][-1],'.5f'))+')')\n\n    plt.title('Accuracy')\n    plt.xlabel('Epochs')\n    plt.ylabel('Accuracy')\n    plt.legend()\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"history = model.fit(train_generator, validation_data=valid_generator, epochs=3, callbacks=[callback0, callback1])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_history(history)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_img_path = \"../input/cassava-leaf-disease-classification/test_images/2216849948.jpg\"\n\nimg = cv2.imread(test_img_path)\nresized_img = cv2.resize(img, (IMG_SIZE, IMG_SIZE)).reshape(-1, IMG_SIZE, IMG_SIZE, 3)/255\n\nplt.figure(figsize=(8,4))\nplt.title(\"TEST IMAGE\")\nplt.imshow(resized_img[0])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"preds = []\nss = pd.read_csv('../input/cassava-leaf-disease-classification/sample_submission.csv')\n\nfor image in ss.image_id:\n    img = tf.keras.preprocessing.image.load_img('../input/cassava-leaf-disease-classification/test_images/' + image)\n    img = tf.keras.preprocessing.image.img_to_array(img)\n    img = tf.keras.preprocessing.image.smart_resize(img, (IMG_SIZE, IMG_SIZE))\n    img = tf.reshape(img, (-1, IMG_SIZE, IMG_SIZE, 3))\n    prediction = model.predict(img/255)\n    preds.append(np.argmax(prediction))\n\nmy_submission = pd.DataFrame({'image_id': ss.image_id, 'label': preds})\nmy_submission.to_csv('submission.csv', index=False) ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(\"Submission File: \\n---------------\\n\")\nprint(my_submission.head()) ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"> **Results**"},{"metadata":{"trusted":true},"cell_type":"code","source":"STEP_SIZE = valid_generator.n // valid_generator.batch_size\n\npredict = model.predict(valid_generator, STEP_SIZE)\nprint(predict)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"good_preds = []\nbad_preds = []\n\nval_filenames = valid_generator.filenames\nlabel_map = (valid_generator.class_indices)\n#label_categories = to_categorical(np.asarray(labels)) \ncla = np.argmax(predict, axis=-1)\nlabel_map = list(map(int, label_map.keys()))\nval_label = valid_generator.labels\n\nfor idx, res in enumerate(predict):\n    #print(\"image_id: \", val_filenames[idx], \", class predict: \", label_map[cla[idx]], \"class: \", label_map[val_label[idx]])\n    \n    if label_map[cla[idx]] != label_map[val_label[idx]]:\n        bad_preds.append([val_filenames[idx], label_map[cla[idx]], label_map[val_label[idx]], res[cla[idx]]])\n    else:\n        good_preds.append([val_filenames[idx], label_map[cla[idx]], label_map[val_label[idx]], res[cla[idx]]])\nprint(\"wrong predictions: \", len(bad_preds), \" right predictions: \", len(good_preds), \" acc: \", np.round(100*(len(predict)-len(bad_preds))/len(predict),2))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fig=plt.figure(figsize=(16, 8))\n\ngood_preds = np.array(good_preds)\ngood_preds = np.array(sorted(good_preds, key = lambda x: x[3], reverse=True))\n#print(good_preds.shape)\n\ncolumns = 5\nrows = 1\nfor i in range(1, columns*rows +1):\n    n = good_preds[i,0]\n    #print(n)\n    img = cv2.imread(os.path.join(images_dir_path,n))\n    lbl = good_preds[i,2]\n    fig.add_subplot(rows, columns, i)\n    plt.imshow(img)\n    lbl2 = good_preds[i,1]\n    plt.title(\"Label = \" + str(lbl) + \"\\nClassified:\" + str(lbl2) + \"\\nConfidence:\" + str(good_preds[i,3]))\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"### plot the worst predictions\n\nfig=plt.figure(figsize=(16, 8))\n\nbad_preds = np.array(bad_preds)\nbad_preds = np.array(sorted(bad_preds, key = lambda x: x[3], reverse=True))\n#print(bad_preds.shape)\n\ncolumns = 5\nrows = 1\nfor i in range(1, columns*rows +1):\n    n = bad_preds[i,0]\n    #print(n)\n    img = cv2.imread(os.path.join(images_dir_path,n))\n    lbl = bad_preds[i,2]\n    fig.add_subplot(rows, columns, i)\n    plt.imshow(img)\n    lbl2 = bad_preds[i,1]\n    plt.title(\"Label = \" + str(lbl) + \"\\nClassified:\" + str(lbl2) + \"\\nConfidence:\" + str(good_preds[i,3]))\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#data = pd.DataFrame(df['label'].value_counts()) \n#data.reset_index(inplace=True) \n#data.columns=['class','no. of images']\n\n\nseed_value = 131\nmax_sample_per_class = 14000\nfrom collections import Counter\nno_classes_keep = 1000\nc = df.label.values\ncount = Counter(c).most_common(no_classes_keep)\nkeep_labels = [i[0] for i in count]\ntrain_keep = pd.DataFrame()\nfor label in keep_labels:\n    if len(df[df.label.isin([label])]) < max_sample_per_class:\n        max_sample_per_class = len(df[df.label.isin([label])])\n    train_keep_label = df[df.label.isin([label])].sample(n=max_sample_per_class)\n    train_keep = train_keep.append(train_keep_label, ignore_index=True)\n\n\n\ntrain_val = df.label.value_counts()\ntrain_keep_df = pd.DataFrame({'label':train_val.index, 'frequency':train_val.values})#.head(30)\ntrain_keep_df.reset_index(inplace=True)\n#print(train_keep_df)\nall_preds = np.concatenate((good_preds, bad_preds), axis=0)\nval_img_per_class = Counter(all_preds[:,2])\nbad_val_labels = Counter(bad_preds[:,2])\ngood_val_labels =  Counter(good_preds[:,2])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df.set_index(\"label\", inplace = True)\nprint(\"\\nAccuracy\")\n\nbad_label_pos = 0\n\nfor i in range(5):\n    if i == 0:\n        label = bad_preds[bad_label_pos, 2]\n        pre_label = label\n        bad_label_pos += 1\n    else:\n        label = bad_preds[bad_label_pos, 2]\n        while pre_label == label and bad_label_pos < len(bad_preds):\n            bad_label_pos += 1\n            label = bad_preds[bad_label_pos, 2]\n        pre_label = label    \n    \n    label_counts = train_keep_df.loc[int(label)]\n    print(\"label:\", label, \"has\", label_counts[\"frequency\"], \"images in the class and \",  )\n    print(\"label:\", label, \"has\", val_img_per_class[label], \" validation images images in the class \\nand \",  bad_val_labels[label], \" images classified wrong\")\n    \ngood_label_pos = 0 \nprint(\"\\nAccuracy\")\nfor i in range(5):\n    if i == 0:\n        label = good_preds[good_label_pos, 2]\n        pre_label = label\n        good_label_pos += 1\n    else:\n        label = good_preds[good_label_pos, 2]\n        while pre_label == label and good_label_pos < len(good_preds):\n            good_label_pos += 1\n            label = good_preds[bad_label_pos, 2]\n        pre_label = label\n    label_counts = train_keep_df.loc[int(label)]\n    print(\"label:\", label, \"has\", val_img_per_class[label], \" validation images images in the class \\nand \",  good_val_labels[label], \" images classified correct\")","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}