{"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":"# # This Python 3 environment comes with many helpful analytics libraries installed\n# # It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# # For example, here's several helpful packages to load\n\n# import numpy as np # linear algebra\n# import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# # Input data files are available in the read-only \"../input/\" directory\n# # For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\n# import os\n# for dirname, _, filenames in os.walk('/kaggle/input'):\n#     for filename in filenames:\n#         print(os.path.join(dirname, filename))\n\n# # You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# # You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import tensorflow as tf\n# device_name = tf.test.gpu_device_name()\n# print(device_name)\n# if device_name != '/device:GPU:0':\n#   raise SystemError('GPU device not found')\n# print('Found GPU at: {}'.format(device_name))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"> # Include packages and libraries","metadata":{}},{"cell_type":"code","source":"import cv2\nimport os\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport tensorflow as tf\nimport tensorflow_addons as tfa\n\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout, BatchNormalization\nfrom tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau\n\nfrom keras_preprocessing.image import ImageDataGenerator\nfrom keras.utils.np_utils import to_categorical\nfrom keras.preprocessing.image import img_to_array\nfrom keras import backend as K\nfrom keras.layers.core import Activation, Flatten, Dropout, Dense\n\nfrom sklearn.metrics import classification_report, accuracy_score\nfrom sklearn.preprocessing import MultiLabelBinarizer, LabelBinarizer\nfrom sklearn.model_selection import train_test_split","metadata":{"execution":{"iopub.status.busy":"2021-05-26T07:41:06.950313Z","iopub.execute_input":"2021-05-26T07:41:06.950838Z","iopub.status.idle":"2021-05-26T07:41:06.960782Z","shell.execute_reply.started":"2021-05-26T07:41:06.950782Z","shell.execute_reply":"2021-05-26T07:41:06.959201Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"> # About the data","metadata":{}},{"cell_type":"markdown","source":"## Read file data ","metadata":{}},{"cell_type":"code","source":"df = pd.read_csv('../input/plant-pathology-2021-fgvc8/train.csv')\ndf.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.info()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The data contains 2 columns.  \nThe first column is the *images' names* named '**image**', another column is the '**labels**' of all the images in the dataset.  \nThere are 18632 images and 18632 labels so that there are no null data in this dataset.","metadata":{}},{"cell_type":"markdown","source":"> # Process the data","metadata":{}},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"markdown","source":"## Visualize the data","metadata":{}},{"cell_type":"code","source":"print(df['labels'].value_counts().plot.bar())","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df['labels'].value_counts()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## **NOTE:**  \n### As we can see here, there are 12 labels but some labels are the combine other labels.  \n### So that, there actually are 5 diseases which are:  \n* rust\n* scab\n* complex\n* frog_eye_leaf_spot\n* powdery_mildew\n\n### And another label is:  \n* healthy","metadata":{}},{"cell_type":"markdown","source":"### Because one image (leaf) can have multiple diseases so that this task is a multi-label classification problem!!!","metadata":{}},{"cell_type":"code","source":"y_tr = df['labels'].values\ny_tr","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"label_binarizer = LabelBinarizer()\nimage_labels = label_binarizer.fit_transform(y_tr)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_labels[:5]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"n_classes = len(label_binarizer.classes_)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"n_classes","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# device_name = tf.test.gpu_device_name()\n# print(device_name)\n# if device_name != '/device:GPU:0':\n#   raise SystemError('GPU device not found')\n# print('Found GPU at: {}'.format(device_name))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"height = 128 # 256 64\nwidth = 128 # 256 64\ndepth = 3","metadata":{"execution":{"iopub.status.busy":"2021-05-26T07:41:28.968858Z","iopub.execute_input":"2021-05-26T07:41:28.969285Z","iopub.status.idle":"2021-05-26T07:41:28.974803Z","shell.execute_reply.started":"2021-05-26T07:41:28.969251Z","shell.execute_reply":"2021-05-26T07:41:28.973231Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # Read images function\n# default_image_size = tuple((height,width))\n# def convert_image_to_array(image_dir):\n#     try:\n#         image = cv2.imread(image_dir)\n#         if image is not None :\n#             image = cv2.resize(image, default_image_size)   \n#             return img_to_array(image)\n#         else :\n#             return np.array([])\n#     except Exception as e:\n#         print(f\"Error : {e}\")\n#         return None","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # Create a list contains all img_to_aray(images)\n# images = []\n# for filename in os.listdir('../input/plant-pathology-2021-fgvc8/train_images'):\n#     image_directory = os.path.join('../input/plant-pathology-2021-fgvc8/train_images',filename)\n#     images.append(convert_image_to_array(image_directory))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# len(images)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# images[0].shape, images[0]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# np_images = np.array(images, dtype=np.float16) / 255.0","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# np_images.shape, np_images[0].shape, np_images[0]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# save file images\n# np.save('np_images.npy', np_images)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data = np.load(r'../input/np-images/np_images.npy')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"type(image_labels), image_labels.shape, image_labels[0]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"type(image_labels[0]), type(data)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data[0].shape","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data.shape, image_labels.shape","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"x_train, x_val, y_train, y_val = train_test_split(data, image_labels, test_size=0.2, random_state = 42)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# aug = ImageDataGenerator(rotation_range=25, width_shift_range=0.1,\n#     height_shift_range=0.1, shear_range=0.2, \n#     zoom_range=0.2,horizontal_flip=True, \n#     fill_mode=\"nearest\")\naug = ImageDataGenerator()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# input_shape = (height,width,depth)\n# model = Sequential()\n# model.add(Conv2D(64, kernel_size=4, strides=1, activation='relu', input_shape=input_shape))\n# model.add(Conv2D(64, kernel_size=4, strides=2, activation='relu'))\n# model.add(Dropout(0.5))\n# model.add(Conv2D(128, kernel_size=4, strides=1, activation='relu'))\n# model.add(Conv2D(128, kernel_size=4, strides=2, activation='relu'))\n# model.add(Dropout(0.5))\n# model.add(Conv2D(256, kernel_size=4, strides=1, activation='relu'))\n# model.add(Conv2D(256, kernel_size=4, strides=2, activation='relu'))\n# model.add(Flatten())\n# model.add(Dropout(0.5))\n# model.add(Dense(512, activation='relu'))\n# model.add(Dense(n_classes, activation='softmax'))\n\n# model.compile(optimizer='adam', loss='binary_crossentropy', metrics=[\"accuracy\"])\n\n# model = Sequential()\n# inputShape = (height, width, depth)\n# chanDim = -1\n# # if K.image_data_format() == \"channels_first\":\n# #     inputShape = (depth, height, width)\n# #     chanDim = 1\n    \n# model.add(Conv2D(32, (3, 3), padding=\"same\",input_shape=inputShape))\n# model.add(Activation(\"relu\"))\n# model.add(BatchNormalization())#axis=chanDim\n# model.add(MaxPooling2D(pool_size=(3, 3)))\n# model.add(Dropout(0.25))\n\n# model.add(Conv2D(64, (3, 3), padding=\"same\"))\n# model.add(Activation(\"relu\"))\n# model.add(BatchNormalization())#axis=chanDim\n\n# model.add(Conv2D(64, (3, 3), padding=\"same\"))\n# model.add(Activation(\"relu\"))\n# model.add(BatchNormalization())#axis=chanDim\n# model.add(MaxPooling2D(pool_size=(2, 2)))\n# model.add(Dropout(0.25))\n\n# model.add(Conv2D(128, (3, 3), padding=\"same\"))\n# model.add(Activation(\"relu\"))\n# model.add(BatchNormalization())#axis=chanDim\n\n# model.add(Conv2D(128, (3, 3), padding=\"same\"))\n# model.add(Activation(\"relu\"))\n# model.add(BatchNormalization())#axis=chanDim\n# model.add(MaxPooling2D(pool_size=(2, 2)))\n# model.add(Dropout(0.25))\n\n# model.add(Flatten())\n# model.add(Dense(1024))\n# model.add(Activation(\"relu\"))\n# model.add(BatchNormalization())\n# model.add(Dropout(0.5))\n# model.add(Dense(256))\n# model.add(Activation(\"relu\"))\n# model.add(Dense(n_classes))\n# model.add(Activation(\"softmax\"))\n\n# model.compile(loss=\"binary_crossentropy\", optimizer='adam', metrics=[\"accuracy\"])\n\nmodel=Sequential()\nmodel.add(Conv2D(32, (3, 3), padding=\"same\", activation='relu', input_shape=(256, 256, depth)))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size=(3, 3)))\nmodel.add(Dropout(0.25))\n        \nmodel.add(Conv2D(64, (3, 3), padding=\"same\", activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(Conv2D(64, (3, 3), padding=\"same\", activation='relu'))\nmodel.add(BatchNormalization(axis=1))\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Dropout(0.25))\n\nmodel.add(Conv2D(128, (3, 3), padding=\"same\", activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(Conv2D(128, (3, 3), padding=\"same\", activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Dropout(0.25))\n\nmodel.add(Conv2D(256, (3, 3), padding=\"same\", activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(Conv2D(256, (3, 3), padding=\"same\", activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Dropout(0.25))\n\nmodel.add(Conv2D(512, (3, 3), padding=\"same\", activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(Conv2D(512, (3, 3), padding=\"same\", activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Dropout(0.25))\n\nmodel.add(Conv2D(128, (3, 3), padding=\"same\", activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(Conv2D(128, (3, 3), padding=\"same\", activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Dropout(0.25))\n\nmodel.add(Flatten())\nmodel.add(Dense(64))\nmodel.add(Activation(\"relu\"))\nmodel.add(Dropout(0.25))\nmodel.add(BatchNormalization())\nmodel.add(Dropout(0.25))\nmodel.add(Dense(12))\nmodel.add(Activation(\"softmax\"))\n\nmodel.summary()\ntf.keras.utils.plot_model(model, show_shapes=True)","metadata":{"execution":{"iopub.status.busy":"2021-05-26T07:41:44.318155Z","iopub.execute_input":"2021-05-26T07:41:44.318895Z","iopub.status.idle":"2021-05-26T07:41:45.791862Z","shell.execute_reply.started":"2021-05-26T07:41:44.318836Z","shell.execute_reply":"2021-05-26T07:41:45.790355Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"f1 = tfa.metrics.F1Score(num_classes=12,average='macro')\n\nmodel.compile(optimizer=tf.keras.optimizers.Adam(lr=0.0001, decay=0.01/30), loss='categorical_crossentropy',metrics=['accuracy',f1])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"earlyStopping=EarlyStopping(\n    patience=5,\n    monitor=f1,\n    mode='max',\n    restore_best_weights=True\n)\nlrSchedule = ReduceLROnPlateau(\n    monitor='val_loss', \n    factor=0.05, \n    patience=4, \n    verbose=1\n)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Batch_size = 32\nhistory = model.fit(\n    aug.flow(x_train, y_train, batch_size=Batch_size),\n    validation_data=(x_val, y_val),\n#     steps_per_epoch=len(x_train) // Batch_size,\n    epochs=25\n)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"acc = history.history['accuracy']\nval_acc = history.history['val_accuracy']\nloss = history.history['loss']\nval_loss = history.history['val_loss']\nepochs = range(1, len(acc) + 1)\n#Train and validation accuracy\nplt.plot(epochs, acc, 'b', label='Training accurarcy')\nplt.plot(epochs, val_acc, 'r', label='Validation accurarcy')\nplt.title('Training and Validation accurarcy')\nplt.legend()\n\nplt.figure()\n#Train and validation loss\nplt.plot(epochs, loss, 'b', label='Training loss')\nplt.plot(epochs, val_loss, 'r', label='Validation loss')\nplt.title('Training and Validation loss')\nplt.legend()\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_sub = pd.read_csv('../input/plant-pathology-2021-fgvc8/sample_submission.csv')\nsample_sub","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_images = []\nfor filename in os.listdir('../input/plant-pathology-2021-fgvc8/test_images'):\n    image_directory = os.path.join('../input/plant-pathology-2021-fgvc8/test_images',filename)\n    images.append(convert_image_to_array(image_directory))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"np_test_images = np.array(test_images, dtype=np.float16) / 255.0","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i in range(3):\n    result = model.predict(np_test_images[i])\n    itemindex = np.where(result==np.max(result))\n    sample_sub['labels'][i] = label_binarizer.classes_[itemindex[1][0]]","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_sub.to_csv('submission.csv', index=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}