{"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":"import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport os \nimport json\nimport seaborn as sns\nimport plotly.graph_objects as go\nimport plotly_express as px\nimport plotly.figure_factory as ff\nfrom plotly.subplots import make_subplots\nfrom matplotlib.ticker import MaxNLocator\nfrom sklearn.utils import shuffle\nimport keras\nimport tensorflow as tf\nfrom tensorflow.keras.models import Model,load_model,Sequential\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.applications import EfficientNetB7\nfrom tensorflow.keras.layers import Dense, Activation,Flatten,Conv2D,Dropout,MaxPooling2D,AveragePooling2D,BatchNormalization,GlobalAveragePooling2D\nfrom tensorflow.keras import layers\nfrom keras.callbacks import EarlyStopping, ModelCheckpoint, ReduceLROnPlateau\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.layers.experimental import preprocessing\nfrom keras.utils.vis_utils import plot_model\nfrom tqdm.notebook import tqdm\nfrom pathlib import Path\nimport cv2\nfrom PIL import Image \n\nimport warnings \nwarnings.filterwarnings('ignore')","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Tensorflow version \" + tf.__version__)\nAUTO = tf.data.experimental.AUTOTUNE","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Exploratory Data Analysis","metadata":{}},{"cell_type":"code","source":"Train_Classification = pd.read_csv('/kaggle/input/cassava-leaf-disease-classification/train.csv')\nTrain_Classification = shuffle(Train_Classification,random_state = 9417)\nTrain_Classification['label'] = pd.Series(Train_Classification['label'], dtype=\"string\")\nTrain_Classification","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"disease_names = open('/kaggle/input/cassava-leaf-disease-classification/label_num_to_disease_map.json')\ndisease_names = json.load(disease_names)\ndisease_names","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Train_Classification[\"Classification\"] = Train_Classification[\"label\"].apply(lambda x: disease_names.get(x))\nTrain_Classification","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# here we group labels and count the number of diseases type\nlabel_count = Train_Classification.groupby('label', as_index=False).count()\nlabel_count.rename(columns={'image_id': 'Count', 'label': 'Label'}, inplace=True)\nlabel_count['Label'] = label_count['Label'].apply(lambda x: disease_names[x])\n\nfig, ax = plt.subplots(1, 1, figsize=(12, 8))\nfont1 = {'family': 'Times New Roman','weight': 'bold','style':'normal','size': 20}\nax.set_xlabel('Type of disease',font1)\nax.set_ylabel('Count',font1)\nax = sns.barplot(x=label_count['Count'], y=label_count['Label'], palette='viridis')\nax.tick_params(labelsize=16)\n\nplt.show()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Sampling some images of CMD in the dataset \ndef show_image(image_ids, labels):\n    plt.figure(figsize=(15,10))\n    \n    for i, (image_id,label) in enumerate(zip(image_ids, labels)):\n        plt.subplot(3,3,i+1)\n        img = cv2.imread(os.path.join('/kaggle/input/cassava-leaf-disease-classification/train_images', image_id))\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n\n        plt.imshow(img)\n        plt.title(f\"Class: {label}\", fontsize=12)\n        plt.axis(\"off\")\n    \n    plt.show()\n    \n    \nsamples = Train_Classification.sample(9, random_state = 9417)\nimage_ids = samples['image_id'].values\nlabels = samples['Classification'].values\n\nshow_image(image_ids, labels)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Loading images function \ndef load_img(path):\n    img_bgr = cv2.imread(path)\n    img_rgb = img_bgr[:, :, ::-1]\n    return img_rgb\n# explore the pixels of cassava leaf pictures\nif True:\n    img_names = Path('/kaggle/input/cassava-leaf-disease-classification/train_images').glob('*')\n    plt.figure(figsize=(12,8),dpi=800)\n    pbar = tqdm(img_names, total=len(Train_Classification))\n    for img_name in pbar:\n        img = load_img(img_name.as_posix())\n        # here use the calchist method in cv2 to show the histogram of photo pixels\n        hist = cv2.calcHist([img],[0],None,[256],[0,256])\n        plt.plot(hist)\n    plt.show()\nelse:\n    print('Can not show the details of images')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Healthy_Cassava = Train_Classification[Train_Classification['Classification'] == 'Healthy']['image_id'].to_list()\n\nCMD_Cassava = Train_Classification[Train_Classification['Classification'] == 'Cassava Mosaic Disease (CMD)']['image_id'].to_list()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Healthy Cassava Leaves","metadata":{}},{"cell_type":"code","source":"np.random.seed(20239417)\n\nbase_path = Path('/kaggle/input/cassava-leaf-disease-classification')\ntrain_img_dir =  base_path/'train_images'\n\nrandom_images=[]\nplt.figure(figsize=(16,12))\nfor i in range(9):\n    random_images.append(np.random.choice(Healthy_Cassava))\n\nfor i in range(9):\n    \n    plt.subplot(3, 3, i + 1)\n    img = plt.imread(train_img_dir/random_images[i])\n    plt.imshow(img)\nplt.show()   ","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"f = plt.figure(figsize=(16,8))\nf.add_subplot(1,2, 1)\n\nfont2 = {'family': 'Times New Roman','weight': 'bold','style':'normal','size': 14}\nraw_image = plt.imread(train_img_dir/Healthy_Cassava[2])\nplt.imshow(raw_image, cmap='gray')\nplt.colorbar()\nplt.title('Healthy Image',font2)\nprint(f\"Image dimensions:  {raw_image.shape[0],raw_image.shape[1]}\")\nprint(f\"Maximum pixel value : {raw_image.max():.1f} ; Minimum pixel value:{raw_image.min():.1f}\")\nprint(f\"Mean value of the pixels : {raw_image.mean():.1f} ; Standard deviation : {raw_image.std():.1f}\")\n\nf.add_subplot(1,2, 2)\n\nplt.hist(raw_image[:, :, 0].ravel(), bins = 256, color = 'red', alpha = 0.5)\nplt.hist(raw_image[:, :, 1].ravel(), bins = 256, color = 'Green', alpha = 0.5)\nplt.hist(raw_image[:, :, 2].ravel(), bins = 256, color = 'Blue', alpha = 0.5)\nplt.xlabel('Intensity Value',font2)\nplt.ylabel('Count',font2)\nplt.legend(['Red_Channel', 'Green_Channel', 'Blue_Channel'])\nplt.show()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"imageArray=[]\nfor i in range(len(Healthy_Cassava)):\n    imageArray.append(cv2.cvtColor(cv2.imread(str(train_img_dir/Healthy_Cassava[i])), cv2.COLOR_BGR2RGB))\n\nred_values = []\ngreen_values = []\nblue_values = []\nvalues = []\n\nfor i in range(len(imageArray)):\n    red_values.append(np.mean(imageArray[i][:, :, 0]))\n    green_values.append(np.mean(imageArray[i][:, :, 1]))\n    blue_values.append(np.mean(imageArray[i][:, :, 2]))\n    values.append(np.mean(imageArray[i]))\n\nhist_data = [red_values, green_values, blue_values, values]\ngroup_labels = ['Red', 'Green', 'Blue', 'All']\n\nfig = ff.create_distplot(hist_data, group_labels,colors = ['red', 'green','blue','grey'])\nfig.update_layout(template = 'plotly_white', title_text = 'Channel Distribution - Healthy')\nfig.show()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"figData = []\nfor i, name in zip(range(3), ['Red', 'Green', 'Blue']):\n    trace = go.Box(y = hist_data[i], name = name, boxpoints='all', marker_color  = name)\n    figData.append(trace)\n\nfig = go.Figure(figData)\nfig.update_layout(title_text = 'Pixel Intensity Distribution - health leaf', template = 'plotly_white')\nfig.show() ","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### CMD Cassava Leaves","metadata":{}},{"cell_type":"code","source":"np.random.seed(20239417)\n\nrandom_images=[]\nplt.figure(figsize=(16,12))\nfor i in range(9):\n    random_images.append(np.random.choice(CMD_Cassava))\n\nfor i in range(9):\n    \n    plt.subplot(3, 3, i + 1)\n    img = plt.imread(train_img_dir/random_images[i])\n    plt.imshow(img)\nplt.show()   ","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"f = plt.figure(figsize=(16,8))\nf.add_subplot(1,2, 1)\n\nraw_image = plt.imread(train_img_dir/CMD_Cassava[2])\nplt.imshow(raw_image, cmap='gray')\nplt.colorbar()\nplt.title('CMD Image',font2)\nprint(f\"Image dimensions:  {raw_image.shape[0],raw_image.shape[1]}\")\nprint(f\"Maximum pixel value : {raw_image.max():.1f} ; Minimum pixel value:{raw_image.min():.1f}\")\nprint(f\"Mean value of the pixels : {raw_image.mean():.1f} ; Standard deviation : {raw_image.std():.1f}\")\n\nf.add_subplot(1,2, 2)\n\nplt.hist(raw_image[:, :, 0].ravel(), bins = 256, color = 'red', alpha = 0.5)\nplt.hist(raw_image[:, :, 1].ravel(), bins = 256, color = 'Green', alpha = 0.5)\nplt.hist(raw_image[:, :, 2].ravel(), bins = 256, color = 'Blue', alpha = 0.5)\nplt.xlabel('Intensity Value',font2)\nplt.ylabel('Count',font2)\nplt.legend(['Red_Channel', 'Green_Channel', 'Blue_Channel'])\nplt.show()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"imageArray=[]\nfor i in range(len(CMD_Cassava[:2000])):\n    imageArray.append(cv2.cvtColor(cv2.imread(str(train_img_dir/CMD_Cassava[i])), cv2.COLOR_BGR2RGB))\n\nred_values = []\ngreen_values = []\nblue_values = []\nvalues = []\n\nfor i in range(len(imageArray)):\n    red_values.append(np.mean(imageArray[i][:, :, 0]))\n    green_values.append(np.mean(imageArray[i][:, :, 1]))\n    blue_values.append(np.mean(imageArray[i][:, :, 2]))\n    values.append(np.mean(imageArray[i]))\n\nhist_data = [red_values, green_values, blue_values, values]\ngroup_labels = ['Red', 'Green', 'Blue', 'All']\n\nfig = ff.create_distplot(hist_data, group_labels,colors = ['red', 'green','blue','grey'])\nfig.update_layout(template = 'plotly_white', title_text = 'Channel Distribution - CMD Images')\nfig.show()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"figData = []\nfor i, name in zip(range(3), ['Red', 'Green', 'Blue']):\n    trace = go.Box(y = hist_data[i], name = name, boxpoints='all', marker_color  = name)\n    figData.append(trace)\n\nfig = go.Figure(figData)\nfig.update_layout(title_text = 'Pixel Intensity Distribution - CMD Images', template = 'plotly_white')\nfig.show() ","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Modelling ","metadata":{}},{"cell_type":"code","source":"# Set the input of image size and batch size during the modelling\n# image_size = 224\n# image_size = 312\nimage_size = 224\n\n#batch_size = 32 * strategy.num_replicas_in_sync\n#batch_size = 16 * strategy.num_replicas_in_sync\nbatch_size = 16\n#previous 64\n\n\n# Reread the training dataset\ntrain_dataset = pd.read_csv('/kaggle/input/cassava-leaf-disease-classification/train.csv')\n\n# Transform the attribute \"label\" to the string\ntrain_dataset[\"label\"] = train_dataset[\"label\"].astype(str)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Parameters: rotation_range is the angle of rotating images when data augmentation \n# width_shift_range is the proportion of the iamge width, which means the range of image shifts horizontally when data augmentation\n# height_shift_range is the proportion of the iamge height, which means the range of image shifts vertically when data augmentation\n# horizontal_flip means conducting filp horizontally randomly\n# vertical_flip means conducting filp vertically randomly\n# shear_range means cutting degrees\n# zoom_range means zooming degrees\n# channel_shift_range means the degrees of randomly shifting\n# rescale means the factor of rescaling\n# fill_mode means the points which exceeds the boundary will be operated by given method\n\n# parameter adjustment：\n# rotation_range=40(270), width_shift_range=0.2, height_shift_range=0.2(0.3), remove brightness_range=[0.1,0.9]\n# remove channel_shift_range=0.1, remove rescale=1/255,shear_range=0.2,zoom_range=0.2(0.3)\n\nData_Generator = ImageDataGenerator(rotation_range=40, \n                                    width_shift_range=0.2, \n                                    height_shift_range=0.2, \n        \n                                    shear_range = 0.2, \n                                    zoom_range = 0.2, \n                                 \n                                    horizontal_flip = True, \n                                    vertical_flip = True, \n                           \n                                    validation_split = 0.2,\n                                    fill_mode = 'nearest')\n\n# remove rescale=1/255\nValid_Generator = ImageDataGenerator(validation_split = 0.2)\n\n\ntr_dataset = Data_Generator.flow_from_dataframe(dataframe=train_dataset, directory = \"/kaggle/input/cassava-leaf-disease-classification/train_images\", seed = 9417, \nx_col = \"image_id\", y_col = \"label\", interpolation = 'nearest', target_size = (image_size, image_size), class_mode = \"categorical\", \nbatch_size = batch_size, shuffle = True, subset = \"training\")\n\n\nvalid_dataset = Valid_Generator.flow_from_dataframe(dataframe=train_dataset, directory = \"/kaggle/input/cassava-leaf-disease-classification/train_images\", seed = 9417, \nx_col = \"image_id\",y_col = \"label\", interpolation = 'nearest', target_size = (image_size, image_size), class_mode = \"categorical\",\nbatch_size = batch_size, shuffle = True, subset = \"validation\")","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Here we use the code below to construct our model, and then load this model directly:","metadata":{}},{"cell_type":"markdown","source":"# Define the loss function\nloss = tf.keras.losses.CategoricalCrossentropy(from_logits = False,label_smoothing=0.0001,name='categorical_crossentropy')\n\ndef EfficientNetB7_Model(weights=None):\n    #with strategy.scope():\n    base_model = EfficientNetB7(include_top = False,weights = weights, input_shape = [image_size,image_size,3])\n    model = Sequential()\n    model.add(base_model)\n    model.add(Dropout(0.6))\n    model.add(GlobalAveragePooling2D())\n    model.add(Flatten())\n    model.add(Dense(512, activation='elu', bias_regularizer=tf.keras.regularizers.L1L2(l1=0.01, l2=0.001)))\n    model.add(Dropout(0.5))\n    model.add(Dense(256, activation='elu', bias_regularizer=tf.keras.regularizers.L1L2(l1=0.01, l2=0.001)))\n    model.add(Dropout(0.5))\n    model.add(Dense(5, activation = 'softmax'))\n    #steps_per_execution=16\n    model.compile(loss = loss, optimizer = Adam(lr = 0.001), metrics = [\"categorical_accuracy\",keras.metrics.Precision(),keras.metrics.Recall()])\n    return model","metadata":{}},{"cell_type":"markdown","source":"EfficientNetB7_model = EfficientNetB7_Model(weights = \"imagenet\")","metadata":{}},{"cell_type":"code","source":"EfficientNetB7_model = keras.models.load_model('/kaggle/input/efficientnetb7-pretrained-model/EfficientNetB7_pretrained_model.h5')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"EfficientNetB7_model.summary()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Plot the neural network structure\nplot_model(EfficientNetB7_model,to_file='EfficientNetB7_model.png',show_shapes=True)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.2, patience=2, min_lr=1e-6, mode='min', verbose=1)\n\nearly_stopping = EarlyStopping(monitor = \"val_loss\", mode = \"min\", patience = 10, restore_best_weights=True, verbose=1)\n\ncheck_point = tf.keras.callbacks.ModelCheckpoint(\"Cassava_Leaf_Disease_Detection_EfficientNetB7_model_BestModel.h5\", \n                                                 monitor = 'val_loss',mode = 'min', save_best_only=True,save_weights_only=True)\n#steps_per_epoch=STEPS_PER_EPOCH, \nhistory_EfficientNetB7 = EfficientNetB7_model.fit(tr_dataset, validation_data = valid_dataset, epochs = 20, \n                                      callbacks = [early_stopping, reduce_lr, check_point])","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Results","metadata":{}},{"cell_type":"code","source":"# Models Evaluation \naccuracy = history_EfficientNetB7.history[\"categorical_accuracy\"]\nv_accuracy = history_EfficientNetB7.history[\"val_categorical_accuracy\"]\n\nloss = history_EfficientNetB7.history[\"loss\"]\nv_loss = history_EfficientNetB7.history[\"val_loss\"]\n\nprecision = history_EfficientNetB7.history[\"precision\"]\nv_precision = history_EfficientNetB7.history[\"val_precision\"]\n\nrecall = history_EfficientNetB7.history[\"recall\"]\nv_recall = history_EfficientNetB7.history[\"val_recall\"]\n\n# Plot four main Evaluation criterions\nepochs = range(20)\n\nplt.figure(figsize = (12, 12))\nplt.subplot(2, 2, 1)\nplt.plot(epochs, accuracy, label = \"Training Set Accuracy\")\nplt.plot(epochs, v_accuracy, label = \"Validation Set Accuracy\")\nplt.legend(loc = \"lower right\")\nplt.title(\"Training and Validation Accuracy\")\n\nplt.subplot(2, 2, 2)\nplt.plot(epochs, loss, label = \"Training Set Loss\")\nplt.plot(epochs, v_loss, label = \"Validation Set Loss\")\nplt.legend(loc = \"lower right\")\nplt.title(\"Training and Validation Loss\")\nplt.show()\n\nplt.subplot(2, 2, 3)\nplt.plot(epochs, precision, label = \"Training Set Precision\")\nplt.plot(epochs, v_precision, label = \"Validation Set Precision\")\nplt.legend(loc = \"lower right\")\nplt.title(\"Training and Validation Precision\")\nplt.show()\n\nplt.subplot(2, 2, 4)\nplt.plot(epochs, recall, label = \"Training Set Recall\")\nplt.plot(epochs, v_recall, label = \"Validation Set Recall\")\nplt.legend(loc = \"lower right\")\nplt.title(\"Training and Validation Recall\")\nplt.show()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Submission","metadata":{}},{"cell_type":"code","source":"preds = []\nsample_sub_csv = pd.read_csv('/kaggle/input/cassava-leaf-disease-classification/sample_submission.csv')\n\nfor image in sample_sub_csv.image_id:\n    img = tf.keras.preprocessing.image.load_img('/kaggle/input/cassava-leaf-disease-classification/test_images/' + image)\n    img = tf.keras.preprocessing.image.img_to_array(img)\n    img = tf.keras.preprocessing.image.smart_resize(img, (image_size, image_size))\n    img = tf.reshape(img, (-1, image_size, image_size, 3))\n    prediction = EfficientNetB7_model.predict(img/255)\n    preds.append(np.argmax(prediction))\n\nfinal_submission = pd.DataFrame({'image_id': sample_sub_csv.image_id, 'label': preds})\nfinal_submission.to_csv('submission.csv', index=False) ","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(final_submission.head())","metadata":{},"execution_count":null,"outputs":[]}]}