{"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":"### Our aim is to predict if the cassava leaves in the photo is dieseased (0 - 3 represent 4 dieseses) or healthy (represented by 4)\nWe first import necessary dependencies and create a DataFrame to store image file name -> label relations for training data","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 os","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf\nimport matplotlib.pyplot as plt\ntrain_labels = pd.read_csv('../input/cassava-leaf-disease-classification/train.csv')\ntrain_labels.head()","metadata":{"execution":{"iopub.status.busy":"2023-02-25T08:29:32.763680Z","iopub.execute_input":"2023-02-25T08:29:32.763948Z","iopub.status.idle":"2023-02-25T08:29:40.718004Z","shell.execute_reply.started":"2023-02-25T08:29:32.763923Z","shell.execute_reply":"2023-02-25T08:29:40.717045Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Expanding our initial DataFrame with new field namely path ","metadata":{}},{"cell_type":"code","source":"#import cv2\nmain_path = '../input/cassava-leaf-disease-classification/train_images/'\n","metadata":{"execution":{"iopub.status.busy":"2023-02-25T08:29:40.720121Z","iopub.execute_input":"2023-02-25T08:29:40.720648Z","iopub.status.idle":"2023-02-25T08:29:40.725242Z","shell.execute_reply.started":"2023-02-25T08:29:40.720611Z","shell.execute_reply":"2023-02-25T08:29:40.724191Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"here, uncommenting the commented parts lead to long execution time and eventually running out of memory dont know why so commented","metadata":{}},{"cell_type":"markdown","source":"### check if data is missing and or need of data cleaning","metadata":{}},{"cell_type":"code","source":"train_labels.isna().sum()","metadata":{"execution":{"iopub.status.busy":"2023-02-25T08:29:40.726807Z","iopub.execute_input":"2023-02-25T08:29:40.727505Z","iopub.status.idle":"2023-02-25T08:29:40.746630Z","shell.execute_reply.started":"2023-02-25T08:29:40.727469Z","shell.execute_reply":"2023-02-25T08:29:40.745569Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_labels['label'].value_counts()","metadata":{"execution":{"iopub.status.busy":"2023-02-25T08:29:40.748053Z","iopub.execute_input":"2023-02-25T08:29:40.748557Z","iopub.status.idle":"2023-02-25T08:29:40.761661Z","shell.execute_reply.started":"2023-02-25T08:29:40.748507Z","shell.execute_reply":"2023-02-25T08:29:40.760579Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Representation of each of the 5 categories with corrosponding images","metadata":{}},{"cell_type":"code","source":"from PIL import Image\nplt.figure(figsize=(15,12))\nfor id,i in enumerate(train_labels.label.unique()):\n    plt.subplot(4,7,id+1)\n    df = train_labels.loc[train_labels['label']==i].reset_index(drop=True)\n    image_path = df.loc[0,'image_id']\n    image_path = main_path + image_path\n    img = Image.open(image_path)\n    plt.imshow(img)\n    plt.axis('off')\n    plt.title(i)\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-02-25T08:30:03.065489Z","iopub.execute_input":"2023-02-25T08:30:03.066100Z","iopub.status.idle":"2023-02-25T08:30:04.105539Z","shell.execute_reply.started":"2023-02-25T08:30:03.066056Z","shell.execute_reply":"2023-02-25T08:30:04.104551Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_path = main_path + train_labels.loc[0,'image_id']\nsample_img = Image.open(sample_path)\nsample_img.size","metadata":{"execution":{"iopub.status.busy":"2023-02-25T08:30:23.922252Z","iopub.execute_input":"2023-02-25T08:30:23.922664Z","iopub.status.idle":"2023-02-25T08:30:23.931536Z","shell.execute_reply.started":"2023-02-25T08:30:23.922627Z","shell.execute_reply":"2023-02-25T08:30:23.930287Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Transfer learning implementation\n\nHere we will use pretrained models to offer predictions \nThe two models selected initially for this process are VGG 16 and ResNet50","metadata":{}},{"cell_type":"markdown","source":"Here i could not figure out how to do data augmentation on transfer learning models, like how to connect the output of augmentation layers to the input of vgg16 so am not implementing the augmentaiton code, merely commenting it out for now","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras.applications.vgg16 import VGG16\nfrom tensorflow.keras.applications import ResNet50\nimport keras\n\nvgg16 = VGG16(include_top=False, input_shape=(512,512,3), weights='imagenet')\nfor layer in vgg16.layers:\n    layer.trainable = False\n    \n#x1 = keras.layers.experimental.preprocessing.RandomFlip(mode='horizontal')(input)\n#x2 = keras.layers.experimental.preprocessing.RandomFlip(mode='vertical')(x1)\n\n\nx = keras.layers.GlobalAveragePooling2D()(vgg16.output)\noutput = keras.layers.Dense(5, activation='softmax')(x)\n\nvgg16_model = keras.models.Model(inputs = vgg16.input, outputs = output)","metadata":{"execution":{"iopub.status.busy":"2023-02-25T08:30:33.929800Z","iopub.execute_input":"2023-02-25T08:30:33.930187Z","iopub.status.idle":"2023-02-25T08:30:38.427227Z","shell.execute_reply.started":"2023-02-25T08:30:33.930136Z","shell.execute_reply":"2023-02-25T08:30:38.426188Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"resnet = ResNet50(include_top=False, input_shape=(512,512,3), weights='imagenet')\nfor layer in resnet.layers:\n    layer.trainable = False\n    \nx = keras.layers.GlobalAveragePooling2D()(resnet.output)\noutput = keras.layers.Dense(5, activation='softmax')(x)\n\nresnet_model = keras.models.Model(inputs=resnet.inputs, outputs=output)","metadata":{"execution":{"iopub.status.busy":"2023-02-25T08:30:41.056038Z","iopub.execute_input":"2023-02-25T08:30:41.056407Z","iopub.status.idle":"2023-02-25T08:30:43.320934Z","shell.execute_reply.started":"2023-02-25T08:30:41.056374Z","shell.execute_reply":"2023-02-25T08:30:43.319635Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"vgg16_model.compile(\n    loss='sparse_categorical_crossentropy',\n    optimizer='adam',\n    metrics=['accuracy'],\n)\n\nresnet_model.compile(\n    loss='sparse_categorical_crossentropy',\n    optimizer='adam',\n    metrics=['accuracy'],\n)","metadata":{"execution":{"iopub.status.busy":"2023-02-25T09:01:28.919012Z","iopub.execute_input":"2023-02-25T09:01:28.919377Z","iopub.status.idle":"2023-02-25T09:01:28.938768Z","shell.execute_reply.started":"2023-02-25T09:01:28.919345Z","shell.execute_reply":"2023-02-25T09:01:28.937594Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\n\ntrain_labels.label = train_labels.label.astype('str')\n\ntrain_datagen = ImageDataGenerator(validation_split=0.2,\n                                  preprocessing_function = None,\n                                  rescale = 1./255,\n                                  rotation_range = 45,\n                                  zoom_range = 0.2,\n                                  horizontal_flip = True,\n                                  vertical_flip = True,\n                                  #fill_mode = 'Nearest',\n                                  shear_range = 0.1,\n                                  height_shift_range = 0.1,\n                                  width_shift_range = 0.1,)\n\ntrain_generator = train_datagen.flow_from_dataframe(dataframe = train_labels,\n                                                   directory = '../input/cassava-leaf-disease-classification/train_images',\n                                                   subset='training',\n                                                   x_col = 'image_id',\n                                                   y_col = 'label',\n                                                   target_size = (512,512),\n                                                   batch_size = 32,\n                                                   class_mode = 'sparse',\n                                                   )\n\nvalidation_datagen = ImageDataGenerator(validation_split = 0.2,\n                                       rescale=1./255,\n                                       )\n\nvalidation_generator = validation_datagen.flow_from_dataframe(train_labels,\n                         directory = '../input/cassava-leaf-disease-classification/train_images',\n                         subset = \"validation\",\n                         x_col = \"image_id\",\n                         y_col = \"label\",\n                         target_size = (512,512),\n                         batch_size = 32,\n                         class_mode = \"sparse\")","metadata":{"execution":{"iopub.status.busy":"2023-02-25T09:01:31.660082Z","iopub.execute_input":"2023-02-25T09:01:31.660441Z","iopub.status.idle":"2023-02-25T09:01:40.888228Z","shell.execute_reply.started":"2023-02-25T09:01:31.660406Z","shell.execute_reply":"2023-02-25T09:01:40.887126Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Finally !!! We figured out how to input images from .jpg format into cnns using ImageDataGenerator and flow_from_dataframe, former is deprecated according to tf so hard luck and the later is written by a ml enthutiast so a huge shout out to vijay bhakar\nlink to his article - https://vijayabhaskar96.medium.com/tutorial-on-keras-flow-from-dataframe-1fd4493d237c","metadata":{}},{"cell_type":"markdown","source":"## Introducing callbacks and fitting both the models on data","metadata":{}},{"cell_type":"code","source":"steps_per_epoch = len(train_labels)*0.8 / 32\nvalidation_steps = len(train_labels)*0.2 / 32\n\nearly_stop = tf.keras.callbacks.EarlyStopping(monitor = 'val_loss', min_delta = 0.001, \n                           patience = 5, mode = 'min', verbose = 1,\n                           restore_best_weights = True)\nreduce_lr = tf.keras.callbacks.ReduceLROnPlateau(monitor = 'val_loss', factor = 0.3, \n                              patience = 2, min_delta = 0.001, \n                              mode = 'min', verbose = 1)\n\n# history_vgg = vgg16_model.fit(train_generator,\n#                              validation_data = validation_generator,\n#                               validation_steps = validation_steps,\n#                               steps_per_epoch = steps_per_epoch,\n#                               epochs = 20,\n#                               #callbacks = [early_stop]\n#                              )\n\nhistory_vgg = vgg16_model.fit(\n    train_generator,\n    steps_per_epoch = steps_per_epoch,\n    epochs = 10,\n    validation_data = validation_generator,\n    validation_steps = validation_steps,\n    callbacks = [early_stop, reduce_lr]\n)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ss = pd.read_csv('../input/cassava-leaf-disease-classification/sample_submission.csv')\nss","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preds = []\n\nfor image_id in ss.image_id:\n    image = Image.open('../input/cassava-leaf-disease-classification/test_images/'+image_id)\n    image = image.resize((512,512))\n    image = np.expand_dims(image, axis = 0)\n    preds.append(np.argmax(vgg16_model.predict(image)))\n\nss['label'] = preds\nss","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ss.to_csv('submission.csv', index=False)","metadata":{},"execution_count":null,"outputs":[]}]}