{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"_Import Necessary Libraries_ ","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport numpy as np \nimport pandas as pd \nimport json\nimport seaborn as sns\nimport os, time\n\nimport tensorflow as tf\nfrom PIL import Image\n\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\n\n#########################\n# DL Libraries\n#########################\nfrom keras.layers import Input, Conv2D, GlobalAveragePooling2D, Flatten, Dense, Dropout, BatchNormalization, LeakyReLU, MaxPooling2D\nfrom tensorflow.keras.layers.experimental.preprocessing import RandomRotation, RandomFlip, RandomZoom, Rescaling\nfrom keras.optimizers import RMSprop, Adam\nfrom keras.callbacks import EarlyStopping, ModelCheckpoint, ReduceLROnPlateau\nfrom tensorflow.keras.applications import InceptionResNetV2\nfrom tensorflow.keras.applications.inception_resnet_v2 import preprocess_input\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.models import load_model","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-08-25T07:18:25.314344Z","iopub.execute_input":"2021-08-25T07:18:25.314737Z","iopub.status.idle":"2021-08-25T07:18:31.315976Z","shell.execute_reply.started":"2021-08-25T07:18:25.314649Z","shell.execute_reply":"2021-08-25T07:18:31.315328Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"### set seed for producing same results\nseed = 2020\nnp.random.seed(seed)\ntf.random.set_seed(seed)\nos.environ['PYTHONHASHSEED'] = str(seed)\nos.environ['TF_DETERMINISTIC_OPS'] = '1'","metadata":{"execution":{"iopub.status.busy":"2021-08-24T08:27:23.28577Z","iopub.execute_input":"2021-08-24T08:27:23.28619Z","iopub.status.idle":"2021-08-24T08:27:23.291476Z","shell.execute_reply.started":"2021-08-24T08:27:23.286153Z","shell.execute_reply":"2021-08-24T08:27:23.290176Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Load Training Data","metadata":{}},{"cell_type":"code","source":"dir_path = '../input/cassava-leaf-disease-classification'\ntrain_read = pd.read_csv(dir_path + \"/train.csv\", sep=',')\nprint ('dataframe shape: ', train_read.shape)\ntrain_read.head(10)","metadata":{"execution":{"iopub.status.busy":"2021-08-25T07:18:37.12647Z","iopub.execute_input":"2021-08-25T07:18:37.126942Z","iopub.status.idle":"2021-08-25T07:18:37.177555Z","shell.execute_reply.started":"2021-08-25T07:18:37.126914Z","shell.execute_reply":"2021-08-25T07:18:37.176926Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Plot Class Distribution","metadata":{}},{"cell_type":"code","source":"fig = plt.figure(figsize=(8, 6))\n\nsns.set(font_scale=1.1)\nlabel_count = sns.countplot(x='label', data=train_read, order = train_read['label'].value_counts().index)\nlabel_count.set_xticklabels(label_count.get_xticklabels(), rotation=10)\nplt.ylabel('Count', fontsize=12)\nplt.xlabel('Labels', fontsize=12)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-08-24T08:28:34.832768Z","iopub.execute_input":"2021-08-24T08:28:34.833418Z","iopub.status.idle":"2021-08-24T08:28:35.069987Z","shell.execute_reply.started":"2021-08-24T08:28:34.83338Z","shell.execute_reply":"2021-08-24T08:28:35.068981Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Highly Class Imbalance Data : Class weight can be used later on. \nSparse class or categroical class ? For simplicity I went along with sparse class, also going via categorical (one hot encoding the labels) path takes a lot of time (training the data).  ","metadata":{}},{"cell_type":"code","source":"with open(dir_path + '/label_num_to_disease_map.json') as f:\n    labelnames = json.loads(f.read())\n    labelnames = {int(k): v for k,v in labelnames.items()}\n\nprint(labelnames)\nprint(labelnames[4])","metadata":{"execution":{"iopub.status.busy":"2021-08-25T07:18:40.239184Z","iopub.execute_input":"2021-08-25T07:18:40.239666Z","iopub.status.idle":"2021-08-25T07:18:40.249696Z","shell.execute_reply.started":"2021-08-25T07:18:40.239639Z","shell.execute_reply":"2021-08-25T07:18:40.248924Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"### this was done to check sparse categorical cross entropy part \n### otherwise can be omitted \ntrain_read['label'] = train_read['label'].astype('string')\ntrain_read.head(3)","metadata":{"execution":{"iopub.status.busy":"2021-08-24T08:31:37.145514Z","iopub.execute_input":"2021-08-24T08:31:37.145878Z","iopub.status.idle":"2021-08-24T08:31:37.18924Z","shell.execute_reply.started":"2021-08-24T08:31:37.145846Z","shell.execute_reply":"2021-08-24T08:31:37.188257Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Visualize Different Classes of Disease ","metadata":{}},{"cell_type":"code","source":"train_im_path = dir_path + '/train_images/'\n\n\nfig = plt.figure(figsize=(15, 10))\nnpics= 6\n\ncount = 1\nimage_list = train_read[train_read['label'] == str(list(labelnames.keys())[list(labelnames.values()).index('Healthy')])]['image_id'].sample(frac=1)[:npics].to_list()  \nfor i, img in enumerate(image_list):\n    \n    sample = os.path.join(train_im_path, img) \n    sample_img = Image.open(sample)   \n    ax = fig.add_subplot(npics/2 , 3, count, xticks=[],yticks=[])   \n    plt.imshow(sample_img)\n    count +=1\nfig.suptitle('All Healthy')\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-08-24T08:49:01.316326Z","iopub.execute_input":"2021-08-24T08:49:01.316878Z","iopub.status.idle":"2021-08-24T08:49:02.398009Z","shell.execute_reply.started":"2021-08-24T08:49:01.316832Z","shell.execute_reply":"2021-08-24T08:49:02.3969Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = plt.figure(figsize=(15, 10))\nnpics= 6\n\ncount = 1\nimage_list = train_read[train_read['label'] == str(list(labelnames.keys())[list(labelnames.values()).index('Cassava Bacterial Blight (CBB)')])]['image_id'].sample(frac=1)[:npics].to_list()  \nfor i, img in enumerate(image_list):\n    \n    sample = os.path.join(train_im_path, img) \n    sample_img = Image.open(sample)   \n    ax = fig.add_subplot(npics/2 , 3, count, xticks=[],yticks=[])   \n    plt.imshow(sample_img)\n    count +=1\nfig.suptitle('CBB')\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-08-24T08:50:10.748403Z","iopub.execute_input":"2021-08-24T08:50:10.748825Z","iopub.status.idle":"2021-08-24T08:50:11.756462Z","shell.execute_reply.started":"2021-08-24T08:50:10.748775Z","shell.execute_reply":"2021-08-24T08:50:11.755365Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = plt.figure(figsize=(15, 10))\nnpics= 6\n\ncount = 1\nimage_list = train_read[train_read['label'] == str(list(labelnames.keys())[list(labelnames.values()).index('Cassava Brown Streak Disease (CBSD)')])]['image_id'].sample(frac=1)[:npics].to_list()  \nfor i, img in enumerate(image_list):\n    \n    sample = os.path.join(train_im_path, img) \n    sample_img = Image.open(sample)   \n    ax = fig.add_subplot(npics/2 , 3, count, xticks=[],yticks=[])   \n    plt.imshow(sample_img)\n    count +=1\nfig.suptitle('CBSD')\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-08-24T08:50:57.554127Z","iopub.execute_input":"2021-08-24T08:50:57.554496Z","iopub.status.idle":"2021-08-24T08:50:58.554855Z","shell.execute_reply.started":"2021-08-24T08:50:57.554469Z","shell.execute_reply":"2021-08-24T08:50:58.554005Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = plt.figure(figsize=(15, 10))\nnpics= 6\n\ncount = 1\nimage_list = train_read[train_read['label'] == str(list(labelnames.keys())[list(labelnames.values()).index('Cassava Green Mottle (CGM)')])]['image_id'].sample(frac=1)[:npics].to_list()  \nfor i, img in enumerate(image_list):\n    \n    sample = os.path.join(train_im_path, img) \n    sample_img = Image.open(sample)   \n    ax = fig.add_subplot(npics/2 , 3, count, xticks=[],yticks=[])   \n    plt.imshow(sample_img)\n    count +=1\nfig.suptitle('CGM')\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-08-24T09:00:09.993076Z","iopub.execute_input":"2021-08-24T09:00:09.993445Z","iopub.status.idle":"2021-08-24T09:00:11.258384Z","shell.execute_reply.started":"2021-08-24T09:00:09.993416Z","shell.execute_reply":"2021-08-24T09:00:11.254839Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### How to Find Any Differences \n\nI spent some time reading about these diseases, because to be frank just from the images it is almost impossible to distinguish between different classes. \nAfter reading about the diseases and common symptoms I got even more confused because few of them show similar symptoms.   \n\nFor CBSD, I found [this document](http://www.fao.org/3/CA2940EN/ca2940en.pdf) really helpful. \n\nFor CGM, I foind [this webpage](https://apps.lucidcentral.org/ppp_v9/text/web_full/entities/cassava_green_mottle_068.htm) helpful. The point is to show the similar symptoms between different diseases. \n\nIn [this document](https://assets.publishing.service.gov.uk/media/57a08d8140f0b649740018d4/R7563RootsEng.pdf) the authors discussed about how CMD varies from region to region. \n\n* Later on after classification, I reached around 86% accuracy on validation data and to me it is surprisingly good. Because at least to my untrained eyes, they all looked very similar. \n\nAlso since most of the images are of different leaves, it is better to resize the data (maybe something like center crop ?), which will reduce the training time. ","metadata":{}},{"cell_type":"code","source":"### check the image sizes if all are same or not \n\nim_name_lists = train_read['image_id'].tolist()\nim_shape_x_lists = []\nim_shape_y_lists = []\nfor i, img in enumerate(im_name_lists):\n    sample = os.path.join(train_im_path, img) \n    sample_img = Image.open(sample)\n    w, h = sample_img.size\n#     im_shape_x_lists.append(sample_img.shape[0])\n    im_shape_x_lists.append(w)\n    im_shape_y_lists.append(h)\nprint ('check len: ', len(im_shape_x_lists), len(im_shape_y_lists))    ","metadata":{"execution":{"iopub.status.busy":"2021-08-24T09:01:30.048902Z","iopub.execute_input":"2021-08-24T09:01:30.049272Z","iopub.status.idle":"2021-08-24T09:07:42.826544Z","shell.execute_reply.started":"2021-08-24T09:01:30.049231Z","shell.execute_reply":"2021-08-24T09:07:42.825654Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = plt.figure(figsize=(6, 4))\n\nfig.add_subplot(121)\nplt.hist(im_shape_x_lists)\nfig.add_subplot(122)\nplt.hist(im_shape_y_lists)\nplt.tight_layout()\n\nprint (set(im_shape_x_lists), set(im_shape_y_lists)) # 600 x 800 images ","metadata":{"execution":{"iopub.status.busy":"2021-08-24T09:07:43.134095Z","iopub.execute_input":"2021-08-24T09:07:43.134639Z","iopub.status.idle":"2021-08-24T09:07:43.90841Z","shell.execute_reply.started":"2021-08-24T09:07:43.134605Z","shell.execute_reply":"2021-08-24T09:07:43.907265Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"These images are too big and it would exhaust the time and resource to process with original size. \nSo we will resize the image depending on the pretrained model. \n\nI will use InceptionResNetV2 so we will resize the images to 299x299 (wxh)","metadata":{}},{"cell_type":"code","source":"target_size = (300, 300)\ninput_shape = (300, 300, 3)\nbatch_size = 64","metadata":{"execution":{"iopub.status.busy":"2021-08-24T09:12:55.845852Z","iopub.execute_input":"2021-08-24T09:12:55.846279Z","iopub.status.idle":"2021-08-24T09:12:55.85185Z","shell.execute_reply.started":"2021-08-24T09:12:55.846245Z","shell.execute_reply":"2021-08-24T09:12:55.850571Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Create the Batch Generators  ","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras.preprocessing.image import ImageDataGenerator\n\ndatagen = ImageDataGenerator(validation_split=0.05)\n\ntrain_generator = datagen.flow_from_dataframe(train_read,\n                                              directory=train_im_path,\n                                              x_col=\"image_id\",\n                                              y_col=\"label\",\n                                              target_size=target_size,\n                                              batch_size=batch_size,\n                                              class_mode=\"sparse\",\n                                              subset=\"training\",)\n\nval_generator = datagen.flow_from_dataframe(train_read,\n                                            directory=train_im_path,\n                                            x_col=\"image_id\",\n                                            y_col=\"label\",\n                                            target_size=target_size,\n                                            batch_size=batch_size,\n                                            class_mode=\"sparse\", \n                                            subset=\"validation\",)\n","metadata":{"execution":{"iopub.status.busy":"2021-08-24T09:16:38.844115Z","iopub.execute_input":"2021-08-24T09:16:38.844646Z","iopub.status.idle":"2021-08-24T09:17:13.029705Z","shell.execute_reply.started":"2021-08-24T09:16:38.844605Z","shell.execute_reply":"2021-08-24T09:17:13.028859Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = plt.figure(figsize=(15, 10))\nnpics= 16\ncount = 1\nfor i in range(npics):\n    x,y = val_generator.next()\n    image = x[0].astype('uint8')\n#     print (image.shape)\n    label = y[0]  \n    int_label = int(label)  \n    ax = fig.add_subplot(npics/4 , 4, count, xticks=[],yticks=[])\n    ax.set_title(labelnames[int_label], fontsize=10)  \n    plt.imshow(image)\n    count = count + 1  \n\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-08-24T09:18:33.060277Z","iopub.execute_input":"2021-08-24T09:18:33.060823Z","iopub.status.idle":"2021-08-24T09:18:49.748393Z","shell.execute_reply.started":"2021-08-24T09:18:33.060791Z","shell.execute_reply":"2021-08-24T09:18:49.747335Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Build the Model Using Pre-Trained InceptionResNetV2\n\n* We will also include augmentation as a model layer (Inspired from tf.data pipeline)\n* Next target is to remove ImageDataGenerator completely.  ","metadata":{}},{"cell_type":"markdown","source":"Added and tested Cosine Decay following [this notebook](https://www.kaggle.com/frlemarchand/efficientnet-aug-tf-keras-for-cassava-diseases) but the results are worse.  ","metadata":{}},{"cell_type":"code","source":"## This cell was used to compile the baseline model\n### Cosine Decay was tested\n\nclass customCallbacks(tf.keras.callbacks.Callback):\n  def on_epoch_end(self, epoch, logs=None):\n    self.epoch = epoch + 1\n    if self.epoch % 2 == 0:\n      print (\n          'epoch num {}, train loss: {}, validation loss: {}'.format(epoch, logs['loss'], logs['val_loss']))\n\nreduce_lr = ReduceLROnPlateau(monitor='val_loss', patience=2, verbose=1)\n\n\n# epochs = 20\n# decay_steps = int(round(len(train_read)/batch_size))*epochs\n\n# cosine_decay = CosineDecay(initial_learning_rate=8e-4, decay_steps=decay_steps, alpha=0.3)\n\n\nmcp_save = ModelCheckpoint(filepath=\"best_model_weights.h5\",\n                           save_best_only=True, save_weights_only=True, monitor='val_loss')\n\n\n\n\nes = EarlyStopping(monitor=\"val_loss\", patience=10,)\n\n\n# targets are not one hot encoded but integers so we use sparse_categorical crossentropy\n### later one targets were converted to one hot encoded labels \n\n# final_Efficient_model.compile(optimizer=adam, \n#                               loss=tf.keras.losses.CategoricalCrossentropy(from_logits = False,\n#                                                                            label_smoothing=0.001,), \n#                               metrics=['accuracy',])","metadata":{"execution":{"iopub.status.busy":"2021-08-24T09:54:28.82672Z","iopub.execute_input":"2021-08-24T09:54:28.82712Z","iopub.status.idle":"2021-08-24T09:54:28.834681Z","shell.execute_reply.started":"2021-08-24T09:54:28.827088Z","shell.execute_reply":"2021-08-24T09:54:28.833584Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"inception_resnet_v2 = InceptionResNetV2(\n    include_top=False,\n    weights=\"../input/inceptionresnetv2/inception_resnet_v2_weights_tf_dim_ordering_tf_kernels_notop.h5\",\n    input_shape=input_shape,)\n\ndef build_model():\n    inputs = Input(input_shape)\n    \n    x = preprocess_input(inputs)\n    x = Rescaling(1./255)(x)\n    \n    ###### data augmentation layers\n    x = RandomFlip()(x)\n    x = RandomRotation(factor=0.3)(x)\n    \n    ###### InceptionResNetV2 + Some Top Layers\n    x = BatchNormalization()(x)\n    x = inception_resnet_v2(x)\n\n    x = MaxPooling2D((2, 2))(x)\n    x = Conv2D(256, (1, 1), activation=LeakyReLU())(x)\n    x = BatchNormalization()(x)\n    \n    x = Flatten()(x)\n    x = Dropout(0.75)(x)\n\n    x = Dense(256, activation=LeakyReLU())(x)\n    x = Dropout(0.80)(x)\n    x = BatchNormalization()(x)\n    \n    outputs = Dense(5, activation=\"softmax\")(x)\n    \n    model = Model(inputs, outputs)\n    \n    model.compile(optimizer=tf.keras.optimizers.Adam(0.001),\n                  loss=\"sparse_categorical_crossentropy\", \n                  metrics=[\"accuracy\"])\n    \n    return model\n","metadata":{"execution":{"iopub.status.busy":"2021-08-24T09:49:34.792822Z","iopub.execute_input":"2021-08-24T09:49:34.793198Z","iopub.status.idle":"2021-08-24T09:49:44.540988Z","shell.execute_reply.started":"2021-08-24T09:49:34.793167Z","shell.execute_reply":"2021-08-24T09:49:44.540077Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = build_model()\nmodel.summary()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"##### Add Class Weight \n\n\nTreatment for Unbalanced Data \n\n* Try Multi-class Focal Loss later \n\n**Class_Weight** worsens the performace, so omitted from newer versions. ","metadata":{}},{"cell_type":"code","source":"labels_int = pd.to_numeric(train_read['label'], errors='coerce')\nprint (type(labels_int))\nlabels_int_arr = labels_int.to_numpy()\n# np.unique(labels_int_arr)\n# labels_int_arr.shape\n\nfrom sklearn.utils import class_weight\nmod_class_weights = class_weight.compute_class_weight('balanced', \n                                                      np.unique(labels_int_arr), labels_int_arr)\n\nprint (mod_class_weights)\nprint (dict(enumerate(mod_class_weights)))","metadata":{"execution":{"iopub.status.busy":"2021-08-24T09:56:05.030161Z","iopub.execute_input":"2021-08-24T09:56:05.030518Z","iopub.status.idle":"2021-08-24T09:56:05.205211Z","shell.execute_reply.started":"2021-08-24T09:56:05.030489Z","shell.execute_reply":"2021-08-24T09:56:05.20411Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"start_time = time.time()\nhistory = model.fit(train_generator, \n                    validation_data=val_generator, \n                    epochs=100, \n                    callbacks=[mcp_save, es, reduce_lr])\n\nend_time = time.time()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print ('total time taken: in Minutes', (end_time-start_time)/60.)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Training and Validation Curves","metadata":{}},{"cell_type":"code","source":"acc = history.history['accuracy']\nval_acc = history.history['val_accuracy']\nloss = history.history['loss']\nval_loss = history.history['val_loss']\n\nepochs = range(1, len(acc) + 1)\n\nfig = plt.figure(figsize=(15, 5))\nfig.add_subplot(121)\n\nplt.plot(epochs, acc, linestyle='--', label = \"Training acc\")\nplt.plot(epochs, val_acc, linestyle='-.', label = \"Validation acc\")\nplt.title(\"Training and validation acc\")\nplt.legend()\n\nfig.add_subplot(122)\nplt.plot(epochs, loss, linestyle='--', label = \"Training loss\", alpha=0.8)\nplt.plot(epochs, val_loss, linestyle='-.', label = \"Validation loss\", alpha=0.6)\nplt.title(\"Training and validation loss\")\nplt.legend()\n\nplt.show()\n","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.evaluate(val_generator)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"### check if the model is still fine after loading the trained weights\nmodel.load_weights(\"best_model_weights.h5\")\nmodel.evaluate(val_generator)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Preparing for Submission","metadata":{}},{"cell_type":"code","source":"submission_df = pd.read_csv(\"../input/cassava-leaf-disease-classification/sample_submission.csv\")\nsubmission_df.head()\n","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preds = []\n# preds_no_argmax = []\n\n\ntest_images = os.listdir('/kaggle/input/cassava-leaf-disease-classification/test_images/')\npreds = []\n\nfor i in test_images:\n    image = Image.open(f'/kaggle/input/cassava-leaf-disease-classification/test_images/{i}')\n    image = image.resize(target_size)\n    image = np.expand_dims(image, axis=0)\n    preds.append(np.argmax(model.predict(image)))","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_sub = pd.DataFrame({'image_id': test_images, 'label': preds})\ndf_sub.head()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_sub.to_csv(\"submission.csv\", index=None)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Plot the Confusion Matrix (Validation Data)","metadata":{}},{"cell_type":"code","source":"class_types = list(labelnames.values())\nprint (class_types)","metadata":{"execution":{"iopub.status.busy":"2021-08-25T07:18:48.883364Z","iopub.execute_input":"2021-08-25T07:18:48.883784Z","iopub.status.idle":"2021-08-25T07:18:48.888111Z","shell.execute_reply.started":"2021-08-25T07:18:48.883758Z","shell.execute_reply":"2021-08-25T07:18:48.887518Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"### try to plot the confusion matrix\n\nfrom sklearn.metrics import confusion_matrix, classification_report\nimport seaborn as sns\n\n\n\ndef conf_matrix(test_lab, predictions): \n    ''' Plots conf. matrix and classification report '''\n    cm=confusion_matrix(test_lab, np.argmax(np.round(predictions), axis=1))\n    print(\"Classification Report:\\n\")\n    cr=classification_report(test_lab,\n                                np.argmax(np.round(predictions), axis=1), \n                                target_names=[class_types[i] for i in range(len(class_types))])\n    print(cr)\n    plt.figure(figsize=(8,8))\n    sns_hmp = sns.heatmap(cm, annot=True, xticklabels = [class_types[i] for i in range(len(class_types))], \n                yticklabels = [class_types[i] for i in range(len(class_types))], fmt=\"d\")\n    fig = sns_hmp.get_figure()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"npics = 600 # try 500 examples \nvalid_preds = []\nall_valid_ims = []\nall_valid_labels = []\nfor _ in range(npics):\n    x,y = val_generator.next()\n    image = x[0].astype('uint8')\n    label = y[0]\n    all_valid_labels.append(label)\n    image = np.expand_dims(image, axis = 0)\n    all_valid_ims.append(image)\n","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"all_valid_ims_arr = np.array(all_valid_ims)\nall_valid_labels_arr = np.array(all_valid_labels)\n\n\nall_valid_ims_arr = np.reshape(all_valid_ims_arr, (600, 300, 300, 3))\n\nprint ('check shapes now: ', all_valid_ims_arr.shape, all_valid_labels_arr.shape)\n","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pred_class_InceptResV2 = model.predict(all_valid_ims_arr)\nprint ('check shape of preds: ', pred_class_InceptResV2.shape)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"conf_matrix(np.int32(all_valid_labels_arr), pred_class_InceptResV2)","metadata":{},"execution_count":null,"outputs":[]}]}