{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.7.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":13836,"databundleVersionId":1718836,"sourceType":"competition"},{"sourceId":1971344,"sourceType":"datasetVersion","datasetId":1101834}],"dockerImageVersionId":30043,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nfrom PIL import Image\nimport os\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom tqdm import tqdm\nfrom sklearn.utils import shuffle\nfrom sklearn.utils import class_weight\nfrom sklearn.preprocessing import minmax_scale\nimport random\nimport cv2\nfrom imgaug import augmenters as iaa\nimport warnings\nwarnings.filterwarnings('ignore')\n\nimport tensorflow as tf\nfrom tensorflow.keras.models import Sequential, Model\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.layers import Dense, Dropout, Activation, Input, BatchNormalization, GlobalAveragePooling2D\nfrom tensorflow.keras import layers\nfrom tensorflow.keras.callbacks import ModelCheckpoint, ReduceLROnPlateau, EarlyStopping\nfrom tensorflow.keras.experimental import CosineDecay\nfrom tensorflow.keras.utils import to_categorical\nfrom tensorflow.keras.applications import EfficientNetB3\nfrom tensorflow.keras.layers.experimental.preprocessing import RandomCrop,CenterCrop, RandomRotation","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-04-15T10:51:58.585106Z","iopub.execute_input":"2024-04-15T10:51:58.585602Z","iopub.status.idle":"2024-04-15T10:52:04.693204Z","shell.execute_reply.started":"2024-04-15T10:51:58.585557Z","shell.execute_reply":"2024-04-15T10:52:04.692368Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"training_folder = '../input/cassava-leaf-disease-classification/train_images/'","metadata":{"execution":{"iopub.status.busy":"2024-04-15T10:52:04.695521Z","iopub.execute_input":"2024-04-15T10:52:04.695965Z","iopub.status.idle":"2024-04-15T10:52:04.700737Z","shell.execute_reply.started":"2024-04-15T10:52:04.695915Z","shell.execute_reply":"2024-04-15T10:52:04.699553Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"samples_df = pd.read_csv(\"../input/cassava-leaf-disease-classification/train.csv\")\nsamples_df = shuffle(samples_df, random_state=42)\nsamples_df[\"filepath\"] = training_folder+samples_df[\"image_id\"]\nsamples_df.head()\n","metadata":{"execution":{"iopub.status.busy":"2024-04-15T10:52:04.702304Z","iopub.execute_input":"2024-04-15T10:52:04.702729Z","iopub.status.idle":"2024-04-15T10:52:04.775672Z","shell.execute_reply.started":"2024-04-15T10:52:04.702685Z","shell.execute_reply":"2024-04-15T10:52:04.774584Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"training_percentage = 0.8\ntraining_item_count = int(len(samples_df)*training_percentage)\nvalidation_item_count = len(samples_df)-int(len(samples_df)*training_percentage)\ntraining_df = samples_df[:training_item_count]\nvalidation_df = samples_df[training_item_count:]\n","metadata":{"execution":{"iopub.status.busy":"2024-04-15T10:52:04.777185Z","iopub.execute_input":"2024-04-15T10:52:04.777613Z","iopub.status.idle":"2024-04-15T10:52:04.783883Z","shell.execute_reply.started":"2024-04-15T10:52:04.777561Z","shell.execute_reply":"2024-04-15T10:52:04.782999Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch_size = 8\nimage_size = 512\ninput_shape = (image_size, image_size, 3)\ndropout_rate = 0.4\nclasses_to_predict = sorted(training_df.label.unique())","metadata":{"execution":{"iopub.status.busy":"2024-04-15T10:52:04.787852Z","iopub.execute_input":"2024-04-15T10:52:04.788266Z","iopub.status.idle":"2024-04-15T10:52:04.795998Z","shell.execute_reply.started":"2024-04-15T10:52:04.788221Z","shell.execute_reply":"2024-04-15T10:52:04.795198Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"training_data = tf.data.Dataset.from_tensor_slices((training_df.filepath.values, training_df.label.values))\nvalidation_data = tf.data.Dataset.from_tensor_slices((validation_df.filepath.values, validation_df.label.values))","metadata":{"execution":{"iopub.status.busy":"2024-04-15T10:52:04.797731Z","iopub.execute_input":"2024-04-15T10:52:04.798084Z","iopub.status.idle":"2024-04-15T10:52:06.610768Z","shell.execute_reply.started":"2024-04-15T10:52:04.798053Z","shell.execute_reply":"2024-04-15T10:52:06.609876Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_image_and_label_from_path(image_path, label):\n    img = tf.io.read_file(image_path)\n    img = tf.image.decode_jpeg(img, channels=3)\n    return img, label\n\nAUTOTUNE = tf.data.experimental.AUTOTUNE\n\ntraining_data = training_data.map(load_image_and_label_from_path, num_parallel_calls=AUTOTUNE)\nvalidation_data = validation_data.map(load_image_and_label_from_path, num_parallel_calls=AUTOTUNE)\n\n\ntraining_data_batches = training_data.shuffle(buffer_size=1000).batch(batch_size).prefetch(buffer_size=AUTOTUNE)\nvalidation_data_batches = validation_data.shuffle(buffer_size=1000).batch(batch_size).prefetch(buffer_size=AUTOTUNE)","metadata":{"execution":{"iopub.status.busy":"2024-04-15T10:52:06.612008Z","iopub.execute_input":"2024-04-15T10:52:06.612313Z","iopub.status.idle":"2024-04-15T10:52:06.740356Z","shell.execute_reply.started":"2024-04-15T10:52:06.612283Z","shell.execute_reply":"2024-04-15T10:52:06.739608Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"adapt_data = tf.data.Dataset.from_tensor_slices(training_df.filepath.values)\ndef adapt_mode(image_path):\n    img = tf.io.read_file(image_path)\n    img = tf.image.decode_jpeg(img, channels=3)\n    img = layers.experimental.preprocessing.Rescaling(1.0 / 255)(img)\n    return img\n\nadapt_data = adapt_data.map(adapt_mode, num_parallel_calls=AUTOTUNE)\nadapt_data_batches = adapt_data.shuffle(buffer_size=1000).batch(batch_size).prefetch(buffer_size=AUTOTUNE)","metadata":{"execution":{"iopub.status.busy":"2024-04-15T10:52:06.741618Z","iopub.execute_input":"2024-04-15T10:52:06.741962Z","iopub.status.idle":"2024-04-15T10:52:06.829736Z","shell.execute_reply.started":"2024-04-15T10:52:06.741917Z","shell.execute_reply":"2024-04-15T10:52:06.828397Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_augmentation_layers = tf.keras.Sequential(\n    [\n        layers.experimental.preprocessing.RandomCrop(height=image_size, width=image_size),\n        layers.experimental.preprocessing.RandomFlip(\"horizontal_and_vertical\"),\n        layers.experimental.preprocessing.RandomRotation(0.25),\n        layers.experimental.preprocessing.RandomZoom((-0.2, 0)),\n        layers.experimental.preprocessing.RandomContrast((0.2,0.2))\n    ]\n)","metadata":{"execution":{"iopub.status.busy":"2024-04-15T10:52:06.831298Z","iopub.execute_input":"2024-04-15T10:52:06.831734Z","iopub.status.idle":"2024-04-15T10:52:07.185342Z","shell.execute_reply.started":"2024-04-15T10:52:06.83169Z","shell.execute_reply":"2024-04-15T10:52:07.184499Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"efficientnet = EfficientNetB3(weights=\"../input/keras-efficientnetb3-no-top-weights/efficientnetb3_notop.h5\", \n                              include_top=False, \n                              input_shape=input_shape, \n                              drop_connect_rate=dropout_rate)\n\ninputs = Input(shape=input_shape)\naugmented = data_augmentation_layers(inputs)\nefficientnet = efficientnet(augmented)\npooling = layers.GlobalAveragePooling2D()(efficientnet)\ndropout = layers.Dropout(dropout_rate)(pooling)\noutputs = Dense(len(classes_to_predict), activation=\"softmax\")(dropout)\nmodel = Model(inputs=inputs, outputs=outputs)\n    \nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2024-04-15T10:52:07.186637Z","iopub.execute_input":"2024-04-15T10:52:07.187017Z","iopub.status.idle":"2024-04-15T10:52:14.203274Z","shell.execute_reply.started":"2024-04-15T10:52:07.186971Z","shell.execute_reply":"2024-04-15T10:52:14.202416Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"epochs = 50","metadata":{"execution":{"iopub.status.busy":"2024-04-15T10:52:14.204541Z","iopub.execute_input":"2024-04-15T10:52:14.204829Z","iopub.status.idle":"2024-04-15T10:52:14.209148Z","shell.execute_reply.started":"2024-04-15T10:52:14.2048Z","shell.execute_reply":"2024-04-15T10:52:14.20802Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"decay_steps = int(round(len(training_df)/batch_size))*epochs\ncosine_decay = CosineDecay(initial_learning_rate=1e-4, decay_steps=decay_steps, alpha=0.3)\n\ncallbacks = [ModelCheckpoint(filepath='best_model.h5', monitor='val_loss', save_best_only=True)]\n\nmodel.compile(loss=\"sparse_categorical_crossentropy\", optimizer=tf.keras.optimizers.Adam(cosine_decay), metrics=[\"accuracy\"])","metadata":{"execution":{"iopub.status.busy":"2024-04-15T10:52:14.210356Z","iopub.execute_input":"2024-04-15T10:52:14.210686Z","iopub.status.idle":"2024-04-15T10:52:14.245Z","shell.execute_reply.started":"2024-04-15T10:52:14.210656Z","shell.execute_reply":"2024-04-15T10:52:14.243903Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = model.fit(training_data_batches,\n                  epochs = epochs, \n                  validation_data=validation_data_batches,\n                  callbacks=callbacks)","metadata":{"execution":{"iopub.status.busy":"2024-04-15T10:52:14.246401Z","iopub.execute_input":"2024-04-15T10:52:14.246696Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#### ei part ta lagbe \n\nplt.plot(history.history['loss'])\nplt.plot(history.history['val_loss'])\nplt.title('Loss over epochs')\nplt.ylabel('Loss')\nplt.xlabel('Epoch')\nplt.legend(['Train', 'Validation'], loc='best')\nplt.show()\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.load_weights(\"./best_model.h5\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def scan_over_image(img_path, crop_size=512):\n    '''\n    Will extract 512x512 images covering the whole original image\n    with some overlap between images\n    '''\n    \n    img = Image.open(img_path)\n    img_height, img_width = img.size\n    img = np.array(img)\n    \n    y = random.randint(0,img_height-crop_size)\n    x = random.randint(0,img_width-crop_size)\n\n    x_img_origins = [0,img_width-crop_size]\n    y_img_origins = [0,img_height-crop_size]\n    img_list = []\n    for x in x_img_origins:\n        for y in y_img_origins:\n            img_list.append(img[x:x+crop_size , y:y+crop_size,:])\n  \n    return np.array(img_list)\n\n\n\ndef display_samples(img_path):\n    '''\n    Display all 512x512 images extracted from original images\n    '''\n    \n    img_list = scan_over_image(img_path)\n    sample_number = len(img_list)\n    fig = plt.figure(figsize = (8,sample_number))\n    for i in range(0,sample_number):\n        ax = fig.add_subplot(2, 4, i+1)\n        ax.imshow(img_list[i])\n        ax.set_title(str(i))\n    plt.tight_layout()\n    plt.show()\n\ndisplay_samples(\"../input/cassava-leaf-disease-classification/train_images/3412658650.jpg\")\n\ntest_time_augmentation_layers = tf.keras.Sequential(\n    [\n        layers.experimental.preprocessing.RandomFlip(\"horizontal_and_vertical\"),\n        layers.experimental.preprocessing.RandomZoom((-0.2, 0)),\n        layers.experimental.preprocessing.RandomContrast((0.2,0.2))\n    ]\n)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"## ei part pedict korar jnnw. App er time e lagbe\n\ndef predict_and_vote(image_filename, folder, TTA_runs=4):\n    '''\n    Run the model over 4 local areas of the given image,\n    before making a decision depending on the most predicted\n    disease.\n    '''\n    \n    #apply TTA to each of the 4 images and sum all predictions for each local image\n    localised_predictions = []\n    local_image_list = scan_over_image(folder+image_filename)\n    for local_image in local_image_list:\n        duplicated_local_image = tf.convert_to_tensor(np.array([local_image for i in range(TTA_runs)]))\n        augmented_images = test_time_augmentation_layers(duplicated_local_image)\n        \n        predictions = model.predict(augmented_images)\n        localised_predictions.append(np.sum(predictions, axis=0))\n    \n    #sum all predictions from all 4 images and retrieve the index of the highest value\n    global_predictions = np.sum(np.array(localised_predictions),axis=0)\n    final_prediction = np.argmax(global_predictions)\n    \n    return final_prediction\n\n\n\ndef run_predictions_over_image_list(image_list, folder):\n    predictions = []\n    with tqdm(total=len(image_list)) as pbar:\n        for image_filename in image_list:\n            pbar.update(1)\n            predictions.append(predict_and_vote(image_filename, folder))\n    return predictions\n\n\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}