{"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":"<h1 style=\"text-align: center; font-family: Verdana; font-size: 32px; font-style: normal; font-weight: bold; text-decoration: none; text-transform: none; font-variant: small-caps; letter-spacing: 3px; color: red; background-color: #ffffff;\">Plant Pathology : ResNet50</h1>\n\n<center><img src=\"https://miro.medium.com/max/1416/1*McwAbGJjA1lV_xBdg1w5XA.png\"></center>\n\n<center><div class=\"alert alert-danger\" style=\"margin: 2em; line-height: 1.7em; font-family: Verdana;\">\nIncreasing Network depths leads to worst performance</div>\n</center>","metadata":{}},{"cell_type":"markdown","source":"<h1 style=\"font-family: Verdana; font-size: 24px; font-style: normal; font-weight: bold; text-decoration: none; text-transform: none; letter-spacing: 3px; background-color: #ffffff; color: navy;\">ResNet as a rescuer&nbsp;&nbsp;&nbsp;&nbsp;</h1> \n\nAfter the celebrated victory of AlexNet at the LSVRC2012 classification contest, deep Residual Network was arguably the most groundbreaking work in the computer vision/deep learning community in the last few years. ResNet makes it possible to train up to hundreds or even thousands of layers and still achieves compelling performance.\n\nTaking advantage of its powerful representational ability, the performance of many computer vision applications other than image classification have been boosted, such as object detection and face recognition.\nSince ResNet blew people’s mind in 2015, many in the research community have dived into the secrets of its success, many refinements have been made in the architecture.\n\nAccording to the universal approximation theorem, given enough capacity, we know that a feedforward network with a single layer is sufficient to represent any function. However, the layer might be massive and the network is prone to overfitting the data. Therefore, there is a common trend in the research community that our network architecture needs to go deeper.\n\nSince AlexNet, the state-of-the-art CNN architecture is going deeper and deeper. While AlexNet had only 5 convolutional layers, the VGG network and GoogleNet (also codenamed Inception_v1) had 19 and 22 layers respectively.\n\nHowever, increasing network depth does not work by simply stacking layers together. Deep networks are hard to train because of the notorious vanishing gradient problem — as the gradient is back-propagated to earlier layers, repeated multiplication may make the gradient infinitively small. As a result, as the network goes deeper, its performance gets saturated or even starts degrading rapidly.\n\nThe core idea of ResNet is introducing a so-called “identity shortcut connection” that skips one or more layers, as shown in the following figure:\n<center><img src=\"https://miro.medium.com/max/816/1*ByrVJspW-TefwlH7OLxNkg.png\"></center>\n<center><img src=\"https://miro.medium.com/max/1000/1*2ns4ota94je5gSVjrpFq3A.png\"></center>\n<center><h5>the resnet archtecture</h5></center>\n<br>\n\nThe authors of argue that stacking layers shouldn’t degrade the network performance, because we could simply stack identity mappings (layer that doesn’t do anything) upon the current network, and the resulting architecture would perform the same. This indicates that the deeper model should not produce a training error higher than its shallower counterparts. They hypothesize that letting the stacked layers fit a residual mapping is easier than letting them directly fit the desired underlaying mapping. And the residual block above explicitly allows it to do precisely that.\n\nFollowing this intuition, the authors of refined the residual block and proposed a pre-activation variant of residual block, in which the gradients can flow through the shortcut connections to any other earlier layer unimpededly. In fact, using the original residual block in, training a 1202-layer ResNet resulted in worse performance than its 110-layer counterpart.\n\n<img src=\"https://miro.medium.com/max/1400/1*M5NIelQC33eN6KjwZRccoQ.png\">\n<center><h5>variants of residual blocks</h5></center>","metadata":{}},{"cell_type":"markdown","source":"<center><div class=\"alert alert-block alert-success\" style=\"margin: 2em; line-height: 1.7em; font-family: Verdana;\">\n    <b style=\"font-size: 20px;\">\n    <img src=\"https://cdn2.iconfinder.com/data/icons/digital-and-internet-marketing-3-1/50/144-512.png\" width=50 align='left'>\n    Contents\n</div></center>\n    \n<p id=\"toc\"></p>\n\n---\n\n<h3 style=\"text-indent: 10vw; font-family: Verdana; font-size: 20px; font-style: normal; font-weight: normal; text-decoration: none; text-transform: none; letter-spacing: 2px; color: navy; background-color: #ffffff;\"><a href=\"#PS\">&nbsp;&nbsp;&nbsp;&nbsp;1.Problem Statement</a></h3>\n\n---\n    \n<h3 style=\"text-indent: 10vw; font-family: Verdana; font-size: 20px; font-style: normal; font-weight: normal; text-decoration: none; text-transform: none; letter-spacing: 2px; color: navy; background-color: #ffffff;\"><a href=\"#visual\">&nbsp;&nbsp;&nbsp;&nbsp;2.Visualization</a></h3>\n\n---\n\n<h3 style=\"text-indent: 10vw; font-family: Verdana; font-size: 20px; font-style: normal; font-weight: normal; text-decoration: none; text-transform: none; letter-spacing: 2px; color: navy; background-color: #ffffff;\"><a href=\"#model\">&nbsp;&nbsp;&nbsp;&nbsp;3.Model Building</a></h3>\n\n---\n\n<h3 style=\"text-indent: 10vw; font-family: Verdana; font-size: 20px; font-style: normal; font-weight: normal; text-decoration: none; text-transform: none; letter-spacing: 2px; color: navy; background-color: #ffffff;\"><a href=\"#results\">&nbsp;&nbsp;&nbsp;&nbsp;4.Conclusion and Results</a></h3>\n\n---\n","metadata":{}},{"cell_type":"markdown","source":"<h1 style=\"font-family: Verdana; font-size: 24px; font-style: normal; font-weight: bold; text-decoration: none; text-transform: none; letter-spacing: 3px; background-color: #ffffff; color: navy;\">Problem Statement&nbsp;&nbsp;&nbsp;&nbsp;</h1>\n\nApples are one of the most important temperate fruit crops in the world. Foliar (leaf) diseases pose a major threat to the overall productivity and quality of apple orchards. The current process for disease diagnosis in apple orchards is based on manual scouting by humans, which is time-consuming and expensive.\n\nAlthough computer vision-based models have shown promise for plant disease identification, there are some limitations that need to be addressed. Large variations in visual symptoms of a single disease across different apple cultivars, or new varieties that originated under cultivation, are major challenges for computer vision-based disease identification. These variations arise from differences in natural and image capturing environments, for example, leaf color and leaf morphology, the age of infected tissues, non-uniform image background, and different light illumination during imaging etc.\n\nPlant Pathology 2020-FGVC7 challenge competition had a pilot dataset of 3,651 RGB images of foliar disease of apples. For Plant Pathology 2021-FGVC8, we have significantly increased the number of foliar disease images and added additional disease categories. This year’s dataset contains approximately 23,000 high-quality RGB images of apple foliar diseases, including a large expert-annotated disease dataset. This dataset reflects real field scenarios by representing non-homogeneous backgrounds of leaf images taken at different maturity stages and at different times of day under different focal camera settings.\n\n<b>Specific Objectives</b>\n\nThe main objective of the competition is to develop machine learning-based models to accurately classify a given leaf image from the test dataset to a particular disease category, and to identify an individual disease from multiple disease symptoms on a single leaf image.","metadata":{}},{"cell_type":"markdown","source":"<h1 style=\"font-family: Verdana; font-size: 24px; font-style: normal; font-weight: bold; text-decoration: none; text-transform: none; letter-spacing: 3px; background-color: #ffffff; color: navy;\">Import Libraries&nbsp;&nbsp;&nbsp;&nbsp;</h1>","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport cv2\nimport random\nimport os\nimport glob\nfrom tqdm.notebook import tqdm\nimport plotly\nimport plotly.express as ex\nimport plotly.graph_objs as go\nimport matplotlib.pyplot as plt\n%matplotlib inline\n# Preprocessing the data\nimport tensorflow as tf\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator,load_img\nfrom tensorflow.keras.applications.resnet50 import ResNet50\nfrom tensorflow.keras.preprocessing import image\nfrom tensorflow.keras.applications.resnet50 import preprocess_input\nimport keras\nfrom tensorflow.keras.optimizers import Adam, SGD\nfrom keras.models import Model,load_model\nfrom tensorflow.keras.layers import Dense, Dropout,Conv2D,Flatten,MaxPooling2D,BatchNormalization\nfrom keras import backend as K\nfrom tensorflow.keras.layers.experimental import preprocessing\nfrom keras.callbacks import ReduceLROnPlateau,EarlyStopping","metadata":{"execution":{"iopub.status.busy":"2021-05-27T04:57:01.414041Z","iopub.execute_input":"2021-05-27T04:57:01.414574Z","iopub.status.idle":"2021-05-27T04:57:08.333791Z","shell.execute_reply.started":"2021-05-27T04:57:01.414487Z","shell.execute_reply":"2021-05-27T04:57:08.332939Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Look at the training, testing and validation data numbers\ntest_data = glob.glob('../input/plant-pathology-2021-fgvc8/test_images/*.jpg')\ntrain_data = glob.glob('../input/plant-pathology-2021-fgvc8/train_images/*.jpg')\nsubmission=pd.read_csv('../input/plant-pathology-2021-fgvc8/sample_submission.csv')\ntrain_csv=pd.read_csv('../input/plant-pathology-2021-fgvc8/train.csv')\n\nprint(f\"Training Set has: {len(train_data)} images\")\nprint(f\"Testing Set has: {len(test_data)} images\")","metadata":{"execution":{"iopub.status.busy":"2021-05-27T04:57:08.335072Z","iopub.execute_input":"2021-05-27T04:57:08.335344Z","iopub.status.idle":"2021-05-27T04:57:08.844455Z","shell.execute_reply.started":"2021-05-27T04:57:08.335320Z","shell.execute_reply":"2021-05-27T04:57:08.842854Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_csv.head()","metadata":{"execution":{"iopub.status.busy":"2021-05-27T04:57:09.415383Z","iopub.execute_input":"2021-05-27T04:57:09.415769Z","iopub.status.idle":"2021-05-27T04:57:09.442175Z","shell.execute_reply.started":"2021-05-27T04:57:09.415736Z","shell.execute_reply":"2021-05-27T04:57:09.441243Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_image_dir = \"/kaggle/input/plant-pathology-2021-fgvc8/train_images/\"","metadata":{"execution":{"iopub.status.busy":"2021-05-27T04:57:11.885680Z","iopub.execute_input":"2021-05-27T04:57:11.886155Z","iopub.status.idle":"2021-05-27T04:57:11.890416Z","shell.execute_reply.started":"2021-05-27T04:57:11.886115Z","shell.execute_reply":"2021-05-27T04:57:11.889630Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Generate unique labels from the data","metadata":{}},{"cell_type":"code","source":"lab=[]\nfor v in train_csv['labels'].value_counts().index.tolist():\n    temp=v.split()\n    for i in temp:\n        lab.append(i)","metadata":{"execution":{"iopub.status.busy":"2021-05-27T04:57:14.438269Z","iopub.execute_input":"2021-05-27T04:57:14.438818Z","iopub.status.idle":"2021-05-27T04:57:14.451521Z","shell.execute_reply.started":"2021-05-27T04:57:14.438771Z","shell.execute_reply":"2021-05-27T04:57:14.450695Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels=[]\nfor v in lab:\n    if v not in labels:\n        labels.append(v)","metadata":{"execution":{"iopub.status.busy":"2021-05-27T04:57:16.465152Z","iopub.execute_input":"2021-05-27T04:57:16.465644Z","iopub.status.idle":"2021-05-27T04:57:16.470704Z","shell.execute_reply.started":"2021-05-27T04:57:16.465601Z","shell.execute_reply":"2021-05-27T04:57:16.469783Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"### Total 6 unique classes\nlabels","metadata":{"execution":{"iopub.status.busy":"2021-05-27T04:57:18.406459Z","iopub.execute_input":"2021-05-27T04:57:18.406866Z","iopub.status.idle":"2021-05-27T04:57:18.412188Z","shell.execute_reply.started":"2021-05-27T04:57:18.406833Z","shell.execute_reply":"2021-05-27T04:57:18.411086Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"### get the list of labels for every record\ntrain_csv['labels']=train_csv['labels'].apply(lambda x:x.split(' '))","metadata":{"execution":{"iopub.status.busy":"2021-05-27T04:57:20.729229Z","iopub.execute_input":"2021-05-27T04:57:20.729595Z","iopub.status.idle":"2021-05-27T04:57:20.745161Z","shell.execute_reply.started":"2021-05-27T04:57:20.729545Z","shell.execute_reply":"2021-05-27T04:57:20.744086Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_csv.head()","metadata":{"execution":{"iopub.status.busy":"2021-05-27T04:57:22.769925Z","iopub.execute_input":"2021-05-27T04:57:22.770262Z","iopub.status.idle":"2021-05-27T04:57:22.782118Z","shell.execute_reply.started":"2021-05-27T04:57:22.770235Z","shell.execute_reply":"2021-05-27T04:57:22.781060Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h1 style=\"font-family: Verdana; font-size: 24px; font-style: normal; font-weight: bold; text-decoration: none; text-transform: none; letter-spacing: 3px; background-color: #ffffff; color: navy;\">Visualize the image with labels&nbsp;&nbsp;&nbsp;&nbsp;</h1>","metadata":{}},{"cell_type":"code","source":"from PIL import Image\n# create figure\nfig = plt.figure(figsize=(15, 15))\nimport glob\n\n# setting values to rows and column variables\nrows = 3\ncolumns = 3\n\n\nfor i in range(9):\n    image=glob.glob(\"/kaggle/input/plant-pathology-2021-fgvc8/train_images/*\")[i]\n    img_arr=cv2.imread(image)\n    # Adds a subplot at the 1st position\n    fig.add_subplot(rows, columns, i+1)\n    # showing image\n    plt.imshow(cv2.cvtColor(img_arr, cv2.COLOR_BGR2RGB))\n    plt.axis('on')\n    plt.title(\"Image:\"+glob.glob(\"/kaggle/input/plant-pathology-2021-fgvc8/train_images/*\")[i][len(train_image_dir):]+\"\\n\"+str(train_csv.iloc[i][1]))","metadata":{"execution":{"iopub.status.busy":"2021-05-27T04:57:24.947193Z","iopub.execute_input":"2021-05-27T04:57:24.947551Z","iopub.status.idle":"2021-05-27T04:57:35.607218Z","shell.execute_reply.started":"2021-05-27T04:57:24.947521Z","shell.execute_reply":"2021-05-27T04:57:35.605748Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Preprocessing the images","metadata":{}},{"cell_type":"code","source":"imageSize = 224\nbatchSize = 32\nNUM_CLASSES = 6 ## since there are 6 distinct classes","metadata":{"execution":{"iopub.status.busy":"2021-05-27T04:57:35.608884Z","iopub.execute_input":"2021-05-27T04:57:35.609266Z","iopub.status.idle":"2021-05-27T04:57:35.614233Z","shell.execute_reply.started":"2021-05-27T04:57:35.609231Z","shell.execute_reply":"2021-05-27T04:57:35.613228Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Prepare the image generator object","metadata":{}},{"cell_type":"markdown","source":"#### Input parameters of ImageDataGenerator for resnet50 pretrained model:\n1. preprocessing_function : resnet50\n2. rescale : for rescaling the input image \n3. shear range : Shear Intensity (Shear angle in counter-clockwise direction in degrees)\n4. zoom_range : Range for random zoom\n5. horizontal_flip : Randomly flip inputs horizontally\n6. validation_split : validation set ","metadata":{}},{"cell_type":"code","source":"trainGen = ImageDataGenerator(preprocessing_function = tf.keras.applications.resnet50.preprocess_input, \n                              rescale = 1./255,\n                              shear_range = 0.2,\n                              zoom_range = 0.2,\n                              horizontal_flip = True,\n                              vertical_flip=True,\n                              brightness_range=(0.8, 1.2),\n                              featurewise_center=True,\n                              featurewise_std_normalization=True,\n                              rotation_range=20,\n                              validation_split = 0.2)","metadata":{"execution":{"iopub.status.busy":"2021-05-27T04:57:35.616418Z","iopub.execute_input":"2021-05-27T04:57:35.616862Z","iopub.status.idle":"2021-05-27T04:57:35.627631Z","shell.execute_reply.started":"2021-05-27T04:57:35.616823Z","shell.execute_reply":"2021-05-27T04:57:35.626492Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Generated batches with augemented images from image generator class","metadata":{}},{"cell_type":"code","source":"train_generator = trainGen.flow_from_dataframe(dataframe = train_csv,\n                                               directory = train_image_dir,\n                                               x_col = \"image\",\n                                               y_col = \"labels\",\n                                               class_mode= \"categorical\", \n                                               subset = \"training\", \n                                               target_size = (imageSize, imageSize),\n                                               batch_size = batchSize,\n                                               seed = 123)\nval_generator = trainGen.flow_from_dataframe(dataframe = train_csv,\n                                               directory = train_image_dir,\n                                               x_col = \"image\",\n                                               y_col = \"labels\",\n                                               class_mode= \"categorical\", \n                                               subset = \"validation\", \n                                               target_size = (imageSize, imageSize),\n                                               batch_size = batchSize,\n                                               seed = 123)","metadata":{"execution":{"iopub.status.busy":"2021-05-27T04:57:36.849659Z","iopub.execute_input":"2021-05-27T04:57:36.850019Z","iopub.status.idle":"2021-05-27T04:58:03.651441Z","shell.execute_reply.started":"2021-05-27T04:57:36.849980Z","shell.execute_reply":"2021-05-27T04:58:03.650706Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"## lets check the type\ntype(val_generator) ## image generator object","metadata":{"execution":{"iopub.status.busy":"2021-05-27T04:58:03.652559Z","iopub.execute_input":"2021-05-27T04:58:03.652963Z","iopub.status.idle":"2021-05-27T04:58:03.657183Z","shell.execute_reply.started":"2021-05-27T04:58:03.652933Z","shell.execute_reply":"2021-05-27T04:58:03.656533Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"basemodel = tf.keras.applications.ResNet50(weights = \"imagenet\", include_top = False, pooling = \"avg\")\n## We dont want to train our weight , we will use pre trained weights of resnet50 and remove the output layer\nx = basemodel.output\nx = Dense(128, activation='relu')(x)\nx = BatchNormalization()(x)\ntop_dropout_rate = 0.2\nx = Dropout(top_dropout_rate, name=\"top_dropout\")(x)\nx = Dense(64, activation='relu')(x)\npredictions = Dense(NUM_CLASSES, activation='sigmoid')(x)\n# this is the model we will train\nmodel = Model(inputs=basemodel.input, outputs=predictions)","metadata":{"execution":{"iopub.status.busy":"2021-05-27T04:58:03.658492Z","iopub.execute_input":"2021-05-27T04:58:03.658914Z","iopub.status.idle":"2021-05-27T04:58:06.274598Z","shell.execute_reply.started":"2021-05-27T04:58:03.658884Z","shell.execute_reply":"2021-05-27T04:58:06.273719Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"basemodel.input### image of channel 3 and n*n dimension","metadata":{"execution":{"iopub.status.busy":"2021-05-27T04:58:06.275952Z","iopub.execute_input":"2021-05-27T04:58:06.276236Z","iopub.status.idle":"2021-05-27T04:58:06.281341Z","shell.execute_reply.started":"2021-05-27T04:58:06.276210Z","shell.execute_reply":"2021-05-27T04:58:06.280519Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"basemodel.output### flatten numpy array of size 2048","metadata":{"execution":{"iopub.status.busy":"2021-05-27T04:58:06.282460Z","iopub.execute_input":"2021-05-27T04:58:06.282756Z","iopub.status.idle":"2021-05-27T04:58:06.528454Z","shell.execute_reply.started":"2021-05-27T04:58:06.282730Z","shell.execute_reply":"2021-05-27T04:58:06.527468Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.summary()","metadata":{"execution":{"iopub.status.busy":"2021-05-27T04:58:06.529858Z","iopub.execute_input":"2021-05-27T04:58:06.530437Z","iopub.status.idle":"2021-05-27T04:58:06.603775Z","shell.execute_reply.started":"2021-05-27T04:58:06.530392Z","shell.execute_reply":"2021-05-27T04:58:06.595588Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Create callback : Early stopping and ReduceLROnPlateau","metadata":{}},{"cell_type":"code","source":"earlystop = EarlyStopping(monitor='val_loss',\n                          min_delta=0.01,# threshold to consider as no change\n                          patience=1,# stop if  epochs with no change\n                          verbose=1,\n                          mode='auto',\n                          restore_best_weights= True)\n\n# lr = ReduceLROnPlateau(monitor='val_loss', \n#                              factor=0.1, \n#                              patience=20, \n#                              verbose=1, \n#                              mode='auto', \n#                              min_delta=0.0001, \n#                              cooldown=0, \n#                              min_lr=0.0001)","metadata":{"execution":{"iopub.status.busy":"2021-05-27T04:58:06.613765Z","iopub.execute_input":"2021-05-27T04:58:06.614079Z","iopub.status.idle":"2021-05-27T04:58:06.621079Z","shell.execute_reply.started":"2021-05-27T04:58:06.614051Z","shell.execute_reply":"2021-05-27T04:58:06.620071Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"opt = keras.optimizers.Adam(lr=0.001, decay=1e-4)\nmodel.compile(optimizer = opt, loss = \"binary_crossentropy\", metrics = [\"accuracy\"])","metadata":{"execution":{"iopub.status.busy":"2021-05-27T04:58:06.623134Z","iopub.execute_input":"2021-05-27T04:58:06.623524Z","iopub.status.idle":"2021-05-27T04:58:06.648815Z","shell.execute_reply.started":"2021-05-27T04:58:06.623493Z","shell.execute_reply":"2021-05-27T04:58:06.647784Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"## train for 3 epoch only\nhistory = model.fit(train_generator, \n                    epochs=3, \n                    validation_data=val_generator, \n                    verbose=True, \n                    callbacks = earlystop)","metadata":{"execution":{"iopub.status.busy":"2021-05-27T04:58:06.650373Z","iopub.execute_input":"2021-05-27T04:58:06.650734Z","iopub.status.idle":"2021-05-27T11:12:06.367564Z","shell.execute_reply.started":"2021-05-27T04:58:06.650701Z","shell.execute_reply":"2021-05-27T11:12:06.366653Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Save the trained Model","metadata":{}},{"cell_type":"code","source":"model.save(\"resnet50_model.h5\")","metadata":{"execution":{"iopub.status.busy":"2021-05-27T11:12:06.369505Z","iopub.execute_input":"2021-05-27T11:12:06.369921Z","iopub.status.idle":"2021-05-27T11:12:07.214788Z","shell.execute_reply.started":"2021-05-27T11:12:06.369892Z","shell.execute_reply":"2021-05-27T11:12:07.213791Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Check the history","metadata":{}},{"cell_type":"code","source":"print(history.history.keys())","metadata":{"execution":{"iopub.status.busy":"2021-05-27T11:12:07.216540Z","iopub.execute_input":"2021-05-27T11:12:07.216899Z","iopub.status.idle":"2021-05-27T11:12:07.222012Z","shell.execute_reply.started":"2021-05-27T11:12:07.216867Z","shell.execute_reply":"2021-05-27T11:12:07.220898Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Predictions on Test set","metadata":{}},{"cell_type":"code","source":"test_df = pd.read_csv('../input/plant-pathology-2021-fgvc8/sample_submission.csv')","metadata":{"execution":{"iopub.status.busy":"2021-05-27T11:12:33.039044Z","iopub.execute_input":"2021-05-27T11:12:33.039406Z","iopub.status.idle":"2021-05-27T11:12:33.053014Z","shell.execute_reply.started":"2021-05-27T11:12:33.039374Z","shell.execute_reply":"2021-05-27T11:12:33.052207Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_image_dir = \"/kaggle/input/plant-pathology-2021-fgvc8/test_images/\"\ntest_generator = trainGen.flow_from_dataframe(dataframe = test_df,\n                                               directory = test_image_dir,\n                                               x_col = \"image\",\n                                               y_col = \"labels\",\n                                               class_mode= \"categorical\", \n                                               target_size = (imageSize, imageSize),\n                                               batch_size = batchSize,\n                                               seed = 123)","metadata":{"execution":{"iopub.status.busy":"2021-05-27T11:12:35.550524Z","iopub.execute_input":"2021-05-27T11:12:35.551328Z","iopub.status.idle":"2021-05-27T11:12:35.573683Z","shell.execute_reply.started":"2021-05-27T11:12:35.551278Z","shell.execute_reply":"2021-05-27T11:12:35.572633Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Make prediction","metadata":{}},{"cell_type":"code","source":"predResult = []\nprediction = model.predict(test_generator).tolist()","metadata":{"execution":{"iopub.status.busy":"2021-05-27T11:12:44.515256Z","iopub.execute_input":"2021-05-27T11:12:44.515950Z","iopub.status.idle":"2021-05-27T11:12:46.919519Z","shell.execute_reply.started":"2021-05-27T11:12:44.515907Z","shell.execute_reply":"2021-05-27T11:12:46.918600Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"prediction## list of list","metadata":{"execution":{"iopub.status.busy":"2021-05-27T11:12:51.042143Z","iopub.execute_input":"2021-05-27T11:12:51.042654Z","iopub.status.idle":"2021-05-27T11:12:51.048615Z","shell.execute_reply.started":"2021-05-27T11:12:51.042623Z","shell.execute_reply":"2021-05-27T11:12:51.047620Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_generator.class_indices","metadata":{"execution":{"iopub.status.busy":"2021-05-27T11:12:55.089348Z","iopub.execute_input":"2021-05-27T11:12:55.089743Z","iopub.status.idle":"2021-05-27T11:12:55.095655Z","shell.execute_reply.started":"2021-05-27T11:12:55.089712Z","shell.execute_reply":"2021-05-27T11:12:55.094699Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Generate predicted labels","metadata":{}},{"cell_type":"code","source":"THRESHOLD=0.5\npredResult = []\nfor img in prediction:\n    predictionLabels = []\n    index = 0\n    for categoryScore in img:\n        if categoryScore > THRESHOLD:\n            predictionLabels.append(index)\n        index += 1\n    if not predictionLabels:\n        predResult.append(np.argmax(prediction))\n    else:\n        predResult.append(predictionLabels)","metadata":{"execution":{"iopub.status.busy":"2021-05-27T11:13:10.122429Z","iopub.execute_input":"2021-05-27T11:13:10.122794Z","iopub.status.idle":"2021-05-27T11:13:10.128364Z","shell.execute_reply.started":"2021-05-27T11:13:10.122763Z","shell.execute_reply":"2021-05-27T11:13:10.127487Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predResult","metadata":{"execution":{"iopub.status.busy":"2021-05-27T11:13:13.547747Z","iopub.execute_input":"2021-05-27T11:13:13.548136Z","iopub.status.idle":"2021-05-27T11:13:13.553863Z","shell.execute_reply.started":"2021-05-27T11:13:13.548103Z","shell.execute_reply":"2021-05-27T11:13:13.552884Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"label_map = (train_generator.class_indices)\nfinal_label_map = dict((v,k) for k,v in label_map.items())\nprint(final_label_map)\n\nfor i in range(len(test_df)):\n    labels = \"\"\n    for idx in predResult[i]:\n        labels += final_label_map[idx] + \" \"\n    test_df.iloc[i, 1] = labels.strip()","metadata":{"execution":{"iopub.status.busy":"2021-05-27T11:13:19.251293Z","iopub.execute_input":"2021-05-27T11:13:19.251886Z","iopub.status.idle":"2021-05-27T11:13:19.260757Z","shell.execute_reply.started":"2021-05-27T11:13:19.251834Z","shell.execute_reply":"2021-05-27T11:13:19.259679Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Final results ","metadata":{}},{"cell_type":"code","source":"test_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-05-27T11:13:25.222325Z","iopub.execute_input":"2021-05-27T11:13:25.222740Z","iopub.status.idle":"2021-05-27T11:13:25.235343Z","shell.execute_reply.started":"2021-05-27T11:13:25.222704Z","shell.execute_reply":"2021-05-27T11:13:25.234343Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2021-05-27T11:13:29.569656Z","iopub.execute_input":"2021-05-27T11:13:29.570169Z","iopub.status.idle":"2021-05-27T11:13:29.579260Z","shell.execute_reply.started":"2021-05-27T11:13:29.570135Z","shell.execute_reply":"2021-05-27T11:13:29.578246Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}