{"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":"code","source":"!pip install -U efficientnet","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-07-17T14:46:53.417575Z","iopub.execute_input":"2021-07-17T14:46:53.418038Z","iopub.status.idle":"2021-07-17T14:47:01.104042Z","shell.execute_reply.started":"2021-07-17T14:46:53.417999Z","shell.execute_reply":"2021-07-17T14:47:01.102780Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Import Libraries","metadata":{}},{"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nfrom sklearn.metrics import roc_curve,auc,classification_report,confusion_matrix\nimport matplotlib.pyplot as plt\nfrom PIL import Image\nimport cv2\nimport tensorflow.keras\nimport json\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Conv2D,MaxPooling2D,Dense,Flatten,Dropout  \nfrom tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint,ReduceLROnPlateau\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras import layers\nfrom tensorflow.keras import models\nfrom tensorflow.keras.optimizers import Adam,SGD,RMSprop,Adamax\nfrom tensorflow.keras.models import Model, Sequential\nfrom tensorflow.keras.callbacks import ReduceLROnPlateau\nfrom sklearn.model_selection import StratifiedKFold\nfrom efficientnet.keras import EfficientNetB3\nfrom random import shuffle\nfrom tqdm import tqdm  \nimport scipy\nimport skimage\nfrom skimage.transform import resize\nimport random\nimport os","metadata":{"execution":{"iopub.status.busy":"2021-07-17T14:47:46.488330Z","iopub.execute_input":"2021-07-17T14:47:46.488869Z","iopub.status.idle":"2021-07-17T14:47:46.573576Z","shell.execute_reply.started":"2021-07-17T14:47:46.488837Z","shell.execute_reply":"2021-07-17T14:47:46.572594Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv('/kaggle/input/cassava-leaf-disease-classification/train.csv')\ndf.head(5)","metadata":{"execution":{"iopub.status.busy":"2021-07-17T14:47:50.583590Z","iopub.execute_input":"2021-07-17T14:47:50.583966Z","iopub.status.idle":"2021-07-17T14:47:50.616406Z","shell.execute_reply.started":"2021-07-17T14:47:50.583935Z","shell.execute_reply":"2021-07-17T14:47:50.615054Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"So, lets map the label number to actual names i.e., disease types","metadata":{}},{"cell_type":"code","source":"with open('/kaggle/input/cassava-leaf-disease-classification/label_num_to_disease_map.json') as f:\n    mapping = json.loads(f.read())\n    print(mapping)","metadata":{"execution":{"iopub.status.busy":"2021-07-17T14:47:51.989250Z","iopub.execute_input":"2021-07-17T14:47:51.989865Z","iopub.status.idle":"2021-07-17T14:47:52.003948Z","shell.execute_reply.started":"2021-07-17T14:47:51.989822Z","shell.execute_reply":"2021-07-17T14:47:52.002615Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Target Distribution\n","metadata":{}},{"cell_type":"code","source":"df['label'].value_counts()","metadata":{"execution":{"iopub.status.busy":"2021-07-17T14:47:53.165525Z","iopub.execute_input":"2021-07-17T14:47:53.165939Z","iopub.status.idle":"2021-07-17T14:47:53.177965Z","shell.execute_reply.started":"2021-07-17T14:47:53.165906Z","shell.execute_reply":"2021-07-17T14:47:53.176515Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"There is a huge class imbalance and in it Cassava Mosaic Disease has majority of samples which is more than 6 times to other diseases.","metadata":{}},{"cell_type":"markdown","source":"### Visualize Disease Types","metadata":{}},{"cell_type":"code","source":"def visualize(img_list):\n    rows = 3\n    cols = 3\n\n    plt.figure(figsize=(18, 10))\n\n    for i in range(rows*cols):\n        plt.subplot(10/cols+1, cols, i+1)\n        r = np.random.randint(len(img_list))\n        img_path = \"/kaggle/input/cassava-leaf-disease-classification/train_images/\" + str(img_list[r])\n        img = cv2.imread(img_path)\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n        plt.xticks([])\n        plt.yticks([])\n        plt.title(str(img_list[r]))\n        plt.imshow(img)\n       \n\n    plt.tight_layout()\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-07-17T14:47:54.539767Z","iopub.execute_input":"2021-07-17T14:47:54.540172Z","iopub.status.idle":"2021-07-17T14:47:54.550251Z","shell.execute_reply.started":"2021-07-17T14:47:54.540139Z","shell.execute_reply":"2021-07-17T14:47:54.548692Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Class 0 : Cassava Bacterial Blight (CBB)","metadata":{}},{"cell_type":"code","source":"cbb_df = df[df['label'].isin([0])]\ncbb_img_list = list(df['image_id'])\n\nvisualize(cbb_img_list)","metadata":{"execution":{"iopub.status.busy":"2021-07-17T14:47:55.433314Z","iopub.execute_input":"2021-07-17T14:47:55.433784Z","iopub.status.idle":"2021-07-17T14:47:56.799018Z","shell.execute_reply.started":"2021-07-17T14:47:55.433752Z","shell.execute_reply":"2021-07-17T14:47:56.794676Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Class 1 : Cassava Brown Streak Disease (CBSD)","metadata":{}},{"cell_type":"code","source":"cbb_df = df[df['label'].isin([1])]\ncbb_img_list = list(df['image_id'])\n\nvisualize(cbb_img_list)","metadata":{"execution":{"iopub.status.busy":"2021-07-17T14:47:56.801218Z","iopub.execute_input":"2021-07-17T14:47:56.801671Z","iopub.status.idle":"2021-07-17T14:47:58.142367Z","shell.execute_reply.started":"2021-07-17T14:47:56.801599Z","shell.execute_reply":"2021-07-17T14:47:58.135302Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Class 2 : Cassava Green Mottle (CGM)","metadata":{}},{"cell_type":"code","source":"cbb_df = df[df['label'].isin([2])]\ncbb_img_list = list(df['image_id'])\n\nvisualize(cbb_img_list)","metadata":{"execution":{"iopub.status.busy":"2021-07-17T14:47:58.144587Z","iopub.execute_input":"2021-07-17T14:47:58.145024Z","iopub.status.idle":"2021-07-17T14:47:59.428399Z","shell.execute_reply.started":"2021-07-17T14:47:58.144982Z","shell.execute_reply":"2021-07-17T14:47:59.427347Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Class 3 : Cassava Mosiac Disease (CMD)","metadata":{}},{"cell_type":"code","source":"cbb_df = df[df['label'].isin([3])]\ncbb_img_list = list(df['image_id'])\n\nvisualize(cbb_img_list)","metadata":{"execution":{"iopub.status.busy":"2021-07-17T14:47:59.430119Z","iopub.execute_input":"2021-07-17T14:47:59.430598Z","iopub.status.idle":"2021-07-17T14:48:00.724879Z","shell.execute_reply.started":"2021-07-17T14:47:59.430560Z","shell.execute_reply":"2021-07-17T14:48:00.723653Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Class 4 : Healthy Leaves","metadata":{}},{"cell_type":"code","source":"cbb_df = df[df['label'].isin([4])]\ncbb_img_list = list(df['image_id'])\n\nvisualize(cbb_img_list)","metadata":{"execution":{"iopub.status.busy":"2021-07-17T14:40:23.298619Z","iopub.execute_input":"2021-07-17T14:40:23.299004Z","iopub.status.idle":"2021-07-17T14:40:24.615230Z","shell.execute_reply.started":"2021-07-17T14:40:23.298973Z","shell.execute_reply":"2021-07-17T14:40:24.614209Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Defining Hyperparameters","metadata":{}},{"cell_type":"code","source":"BATCH_SIZE = 16\nTARGET_SIZE = 224\nBASE_DIR = \"/kaggle/input/cassava-leaf-disease-classification/\"\nEPOCHS = 10","metadata":{"execution":{"iopub.status.busy":"2021-07-17T14:48:07.411181Z","iopub.execute_input":"2021-07-17T14:48:07.411537Z","iopub.status.idle":"2021-07-17T14:48:07.417534Z","shell.execute_reply.started":"2021-07-17T14:48:07.411506Z","shell.execute_reply":"2021-07-17T14:48:07.415954Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Image Pre-processing","metadata":{}},{"cell_type":"code","source":"def preprocess(image):\n    #Converting to numpy array from numpy tensor with rank 3\n    image = np.array(image, dtype=np.uint8)\n    #Gaussian Blur\n    gaussian_blur = cv2.GaussianBlur(image,(5,5),0)\n    img = np.asarray(gaussian_blur, dtype=np.float64)\n    return img","metadata":{"execution":{"iopub.status.busy":"2021-07-17T14:48:10.530162Z","iopub.execute_input":"2021-07-17T14:48:10.530644Z","iopub.status.idle":"2021-07-17T14:48:10.539599Z","shell.execute_reply.started":"2021-07-17T14:48:10.530609Z","shell.execute_reply":"2021-07-17T14:48:10.538337Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Converting labels to string to use sparse class mode\ndf.label = df.label.astype('str')","metadata":{"execution":{"iopub.status.busy":"2021-07-17T14:48:11.025656Z","iopub.execute_input":"2021-07-17T14:48:11.026042Z","iopub.status.idle":"2021-07-17T14:48:11.058237Z","shell.execute_reply.started":"2021-07-17T14:48:11.026009Z","shell.execute_reply":"2021-07-17T14:48:11.056938Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Data Augmentation","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras.preprocessing.image import ImageDataGenerator\n#Training  Augumentation\ndatagen = ImageDataGenerator(rescale=1.0/255,\n                             featurewise_center=True,\n                             featurewise_std_normalization=True,\n                             rotation_range=30,\n                             width_shift_range=0.3,\n                             height_shift_range=0.3,\n                             shear_range=15.0,\n                             zoom_range=0.2,\n                             horizontal_flip=True,\n                             brightness_range=[0.2, 0.8],\n                             validation_split=0.2,\n                             fill_mode='nearest',\n                             preprocessing_function=preprocess)\n\n\ntrain_datagen = datagen.flow_from_dataframe(df,\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\n#Validation\nvalidation_datagen = ImageDataGenerator(rescale=1.0/255,\n                                        validation_split=0.2,\n                                       preprocessing_function=preprocess)\n\n\nvalid_datagen = validation_datagen.flow_from_dataframe(df,\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\")","metadata":{"execution":{"iopub.status.busy":"2021-07-17T14:41:24.280871Z","iopub.execute_input":"2021-07-17T14:41:24.281283Z","iopub.status.idle":"2021-07-17T14:42:07.349960Z","shell.execute_reply.started":"2021-07-17T14:41:24.281252Z","shell.execute_reply":"2021-07-17T14:42:07.347837Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Defining Model","metadata":{}},{"cell_type":"code","source":"#He Uniform Initializer for Dense Layer\nimport tensorflow as tf\ndef my_init(shape, dtype=None):\n    initializer = tf.keras.initializers.he_uniform(seed = 1)\n    return initializer(shape, dtype=dtype)\n","metadata":{"execution":{"iopub.status.busy":"2021-07-17T14:48:18.929762Z","iopub.execute_input":"2021-07-17T14:48:18.930219Z","iopub.status.idle":"2021-07-17T14:48:18.936865Z","shell.execute_reply.started":"2021-07-17T14:48:18.930172Z","shell.execute_reply":"2021-07-17T14:48:18.935136Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"base_model = EfficientNetB3(weights = 'imagenet', include_top=False, input_shape = (TARGET_SIZE, TARGET_SIZE, 3), pooling=None)\n\nbase_output = base_model.output\npooling_layer = layers.GlobalAveragePooling2D()(base_output)\nDense1 = layers.Dense(256, activation = \"relu\", kernel_initializer=my_init)(pooling_layer)\nBN1 = layers.BatchNormalization()(Dense1)\ndropout = layers.Dropout(0.2)(BN1)\nmodel = layers.Dense(5, activation=\"softmax\")(dropout)\n\nmodel = models.Model(base_model.input, model)\n\nmodel.compile(optimizer = 'adam', \n              loss = \"sparse_categorical_crossentropy\", \n              metrics=[\"acc\"])\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2021-07-17T14:49:51.039998Z","iopub.execute_input":"2021-07-17T14:49:51.040391Z","iopub.status.idle":"2021-07-17T14:49:56.451914Z","shell.execute_reply.started":"2021-07-17T14:49:51.040359Z","shell.execute_reply":"2021-07-17T14:49:56.450760Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.callbacks import ModelCheckpoint, ReduceLROnPlateau, EarlyStopping\n\nfilepath = \"model.h5\"\n    \ncallbacks = [ReduceLROnPlateau(monitor='val_loss', patience=1, verbose=1, factor=0.1),\n             EarlyStopping(monitor='val_loss', patience=2),\n             ModelCheckpoint(filepath=filepath, monitor='val_loss', save_best_only=True)]","metadata":{"execution":{"iopub.status.busy":"2021-07-17T14:50:36.178560Z","iopub.execute_input":"2021-07-17T14:50:36.179021Z","iopub.status.idle":"2021-07-17T14:50:36.186799Z","shell.execute_reply.started":"2021-07-17T14:50:36.178972Z","shell.execute_reply":"2021-07-17T14:50:36.185517Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = model.fit(train_datagen, epochs = EPOCHS, validation_data = valid_datagen, callbacks=callbacks)","metadata":{"execution":{"iopub.status.busy":"2021-07-17T14:50:41.101423Z","iopub.execute_input":"2021-07-17T14:50:41.101794Z","iopub.status.idle":"2021-07-17T16:03:39.390248Z","shell.execute_reply.started":"2021-07-17T14:50:41.101763Z","shell.execute_reply":"2021-07-17T16:03:39.389086Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.style.use(\"ggplot\")\nplt.figure()\nN = 8\nplt.plot(np.arange(0, 8), history.history[\"acc\"], label=\"train_acc\")\nplt.plot(np.arange(0, 8), history.history[\"val_acc\"], label=\"val_acc\")\nplt.title(\"Accuracy\")\nplt.xlabel(\"Epoch #\")\nplt.ylabel(\"Loss/Accuracy\")\nplt.legend(loc=\"upper left\")\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2021-07-17T16:15:35.328933Z","iopub.execute_input":"2021-07-17T16:15:35.329303Z","iopub.status.idle":"2021-07-17T16:15:35.538503Z","shell.execute_reply.started":"2021-07-17T16:15:35.329273Z","shell.execute_reply":"2021-07-17T16:15:35.537024Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.style.use(\"ggplot\")\nplt.figure()\nN = 8\nplt.plot(np.arange(0, 8), history.history[\"loss\"], label=\"train_loss\")\nplt.plot(np.arange(0, 8), history.history[\"val_loss\"], label=\"val_loss\")\nplt.title(\"Accuracy\")\nplt.xlabel(\"Epoch #\")\nplt.ylabel(\"Loss/Accuracy\")\nplt.legend(loc=\"upper left\")\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2021-07-17T16:16:05.189909Z","iopub.execute_input":"2021-07-17T16:16:05.190296Z","iopub.status.idle":"2021-07-17T16:16:05.490816Z","shell.execute_reply.started":"2021-07-17T16:16:05.190266Z","shell.execute_reply":"2021-07-17T16:16:05.489732Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Model Inspection \n\nIn this step we have visualized the activation layers of the model","metadata":{}},{"cell_type":"code","source":"layer_outputs = [layer.output for layer in model.layers[1:15]]\n\n# This is image of a Rose flower from our dataset. All of the visualizations in this cell are of this image.\ntest_image = BASE_DIR+'test_images/2216849948.jpg'","metadata":{"execution":{"iopub.status.busy":"2021-07-17T16:50:20.878412Z","iopub.execute_input":"2021-07-17T16:50:20.878837Z","iopub.status.idle":"2021-07-17T16:50:20.886511Z","shell.execute_reply.started":"2021-07-17T16:50:20.878807Z","shell.execute_reply":"2021-07-17T16:50:20.884911Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from keras.models import Model\nimport numpy as np\nim=[]\nlayer_outputs = [layer.output for layer in model.layers]\nactivation_model = Model(inputs=model.input, outputs=layer_outputs)\nimage=cv2.imread(test_image)\nimage_from_array = Image.fromarray(image, 'RGB')\nsize_image = image_from_array.resize((224, 224))\nim.append(np.array(size_image))\nfv=np.array(im)\nfv = fv.astype('float32')/255\nactivations = activation_model.predict(fv)\n \ndef display_activation(activations, col_size, row_size, act_index): \n    activation = activations[act_index]\n    activation_index=0\n    fig, ax = plt.subplots(row_size, col_size, figsize=(row_size*4.5,col_size*2.5))\n    for row in range(0,row_size):\n        for col in range(0,col_size):\n            ax[row][col].imshow(activation[0, :, :, activation_index], cmap='gray')\n            activation_index += 1","metadata":{"execution":{"iopub.status.busy":"2021-07-17T16:55:07.991752Z","iopub.execute_input":"2021-07-17T16:55:07.992100Z","iopub.status.idle":"2021-07-17T16:55:19.393610Z","shell.execute_reply.started":"2021-07-17T16:55:07.992069Z","shell.execute_reply":"2021-07-17T16:55:19.392501Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display_activation(activations, 4, 6, 1)","metadata":{"execution":{"iopub.status.busy":"2021-07-17T16:55:52.855687Z","iopub.execute_input":"2021-07-17T16:55:52.856061Z","iopub.status.idle":"2021-07-17T16:55:55.468906Z","shell.execute_reply.started":"2021-07-17T16:55:52.856028Z","shell.execute_reply":"2021-07-17T16:55:55.467565Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display_activation(activations, 4, 6, 3)","metadata":{"execution":{"iopub.status.busy":"2021-07-17T16:56:19.308016Z","iopub.execute_input":"2021-07-17T16:56:19.308427Z","iopub.status.idle":"2021-07-17T16:56:21.630257Z","shell.execute_reply.started":"2021-07-17T16:56:19.308361Z","shell.execute_reply":"2021-07-17T16:56:21.629048Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display_activation(activations, 4, 6, 5)","metadata":{"execution":{"iopub.status.busy":"2021-07-17T16:56:31.009377Z","iopub.execute_input":"2021-07-17T16:56:31.009812Z","iopub.status.idle":"2021-07-17T16:56:33.395984Z","shell.execute_reply.started":"2021-07-17T16:56:31.009782Z","shell.execute_reply":"2021-07-17T16:56:33.394695Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display_activation(activations, 4, 6, 6)","metadata":{"execution":{"iopub.status.busy":"2021-07-17T16:56:58.733255Z","iopub.execute_input":"2021-07-17T16:56:58.733694Z","iopub.status.idle":"2021-07-17T16:57:01.004034Z","shell.execute_reply.started":"2021-07-17T16:56:58.733608Z","shell.execute_reply":"2021-07-17T16:57:01.002739Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}