{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"\nimport re\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nfrom matplotlib import pyplot as plt\nimport os\nimport seaborn as sns\nimport cv2\nimport tensorflow as tf\nfrom keras.models import Sequential\nfrom keras.layers import Dense, Dropout, Conv2D, MaxPooling2D, Flatten,  Dropout, BatchNormalization, LeakyReLU,Input\nfrom keras.optimizers import SGD, Adam\nfrom keras.utils import np_utils\nfrom sklearn.metrics import accuracy_score\nfrom sklearn.model_selection import train_test_split\nfrom kaggle_datasets import KaggleDatasets\nprint('Tensorflow version ' + tf.__version__)\nfrom sklearn.model_selection import KFold\n\n\nimport random, re, math\nimport numpy as np, pandas as pd\nimport matplotlib.pyplot as plt\nfrom sklearn.metrics import f1_score, precision_score, recall_score, confusion_matrix\nimport tensorflow as tf, tensorflow.keras.backend as K\nfrom kaggle_datasets import KaggleDatasets\nprint('Tensorflow version ' + tf.__version__)\nfrom sklearn.model_selection import KFold\nfrom keras.preprocessing.image import ImageDataGenerator\n\nimport math\nimport json, cv2\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport tensorflow as tf \nimport keras\nfrom tqdm.notebook import tqdm\nimport pandas as pd\nimport numpy as np\nfrom functools import partial\npath = \"../input/cassava-leaf-disease-classification/\"","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h2><p style=\"color:blue\">About Notebook</p></h2>\n<h3><p style=\"color:red\">\n1. You can find a EffinetB7/Dense101 implemented here and you can implement any model you like with k fold CV<br>\n2. Basic EDA and understanding of Data<br>\n3. Impoting external data to omprove perfomance<br>\n5. Class Activation Mapping (CAM)!!<br>\n</p></h3>"},{"metadata":{},"cell_type":"markdown","source":"# Understanding the Cassava Leaf Disease Competition\n\n\nManihot esculenta, commonly called cassava (/kəˈsɑːvə/), manioc, yuca, macaxeira, mandioca, aipim, and agbeli, is a woody shrub native to South America of the spurge family, Euphorbiaceae. Although a perennial plant, cassava is extensively cultivated as an annual crop in tropical and subtropical regions for its edible starchy tuberous root, a major source of carbohydrates. Though it is often called yuca in Spanish America and in the United States, it is not related to yucca, a shrub in the family Asparagaceae. Cassava is predominantly consumed in boiled form, but substantial quantities are used to extract cassava starch, called tapioca, which is used for food, animal feed, and industrial purposes. The Brazilian farinha, and the related garri of West Africa, is an edible coarse flour obtained by grating cassava roots, pressing moisture off the obtained grated pulp, and finally drying it (and roasting in the case of farinha).\n\nCassava is the third-largest source of food carbohydrates in the tropics, after rice and maize. Cassava is a major staple food in the developing world, providing a basic diet for over half a billion people. It is one of the most drought-tolerant crops, capable of growing on marginal soils. Nigeria is the world's largest producer of cassava, while Thailand is the largest exporter of cassava starch.\n\nCassava is classified as either sweet or bitter. Like other roots and tubers, both bitter and sweet varieties of cassava contain antinutritional factors and toxins, with the bitter varieties containing much larger amounts.[6] It must be properly prepared before consumption, as improper preparation of cassava can leave enough residual cyanide to cause acute cyanide intoxication, goiters, and even ataxia, partial paralysis, or death. The more toxic varieties of cassava are a fall-back resource (a \"food security crop\") in times of famine or food insecurity in some places. Farmers often prefer the bitter varieties because they deter pests, animals, and thieves\n\n\n\n    \n**Task given in this challange is to classify the images into 5 classes as given below**\n\n1. Cassava Bacterial Blight (CBB)\n2. Cassava Brown Streak Disease (CBSD)\n3. Cassava Green Mottle (CGM)\n4. Cassava Mosaic Disease (CMD)\n5. Healthy\n\nFirst lets take some sample images from each class\n\nImportant Competition rules:\n    - No TPU on submition notebook\n    - No Internet"},{"metadata":{},"cell_type":"markdown","source":"# Cassava Bacterial Blight (CBB)"},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"with open(path + \"label_num_to_disease_map.json\") as file:\n    map_classes = json.loads(file.read())\n    \nprint(json.dumps(map_classes, indent=4))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"tr = pd.read_csv(path + 'train.csv')\n\n\n#\n\n#Mapping label names to each label per image\ntr[\"label_name\"] = tr[\"label\"].astype(str).map(map_classes)\n\ntr = tr[tr['label_name'] == 'Cassava Bacterial Blight (CBB)']\n\n\n#Plot random images and their labels\nrandom_index = np.random.randint(0, tr.shape[0]-1, 9)\n\nfig, axes = plt.subplots(3, 3, figsize = (15, 15))\naxes = axes.ravel()\n\nfor ind, i in enumerate(random_index):\n    img = cv2.imread(path + '/train_images/' + tr.iloc[i, [0]].values[0])\n    label = tr.iloc[i, [2]].values[0]\n    axes[ind].imshow(img)\n    axes[ind].set_title(label)\n    axes[ind].axis('off')\n    \nplt.subplots_adjust(hspace = 0.4);\n\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Cassava Brown Streak Disease (CBSD)"},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"\ntr = pd.read_csv(path + 'train.csv')\n\n#Mapping label names to each label per image\ntr[\"label_name\"] = tr[\"label\"].astype(str).map(map_classes)\n\ntr = tr[tr['label_name'] == 'Cassava Brown Streak Disease (CBSD)']\n\n\n#Plot random images and their labels\nrandom_index = np.random.randint(0, tr.shape[0]-1, 9)\n\nfig, axes = plt.subplots(3, 3, figsize = (15, 15))\naxes = axes.ravel()\n\nfor ind, i in enumerate(random_index):\n    img = cv2.imread(path + '/train_images/' + tr.iloc[i, [0]].values[0])\n    label = tr.iloc[i, [2]].values[0]\n    axes[ind].imshow(img)\n    axes[ind].set_title(label)\n    axes[ind].axis('off')\n    \nplt.subplots_adjust(hspace = 0.4);","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Cassava Green Mottle (CGM)"},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"tr = pd.read_csv(path + 'train.csv')\n\n\n#\n\n#Mapping label names to each label per image\ntr[\"label_name\"] = tr[\"label\"].astype(str).map(map_classes)\n\ntr = tr[tr['label_name'] == 'Cassava Green Mottle (CGM)']\n\n\n#Plot random images and their labels\nrandom_index = np.random.randint(0, tr.shape[0]-1, 9)\n\nfig, axes = plt.subplots(3, 3, figsize = (15, 15))\naxes = axes.ravel()\n\nfor ind, i in enumerate(random_index):\n    img = cv2.imread(path + '/train_images/' + tr.iloc[i, [0]].values[0])\n    label = tr.iloc[i, [2]].values[0]\n    axes[ind].imshow(img)\n    axes[ind].set_title(label)\n    axes[ind].axis('off')\n    \nplt.subplots_adjust(hspace = 0.4);","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Cassava Mosaic Disease (CMD)"},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"tr = pd.read_csv(path + 'train.csv')\n\n\n#\n\n#Mapping label names to each label per image\ntr[\"label_name\"] = tr[\"label\"].astype(str).map(map_classes)\n\ntr = tr[tr['label_name'] == 'Cassava Mosaic Disease (CMD)']\n\n\n#Plot random images and their labels\nrandom_index = np.random.randint(0, tr.shape[0]-1, 9)\n\nfig, axes = plt.subplots(3, 3, figsize = (15, 15))\naxes = axes.ravel()\n\nfor ind, i in enumerate(random_index):\n    img = cv2.imread(path + '/train_images/' + tr.iloc[i, [0]].values[0])\n    label = tr.iloc[i, [2]].values[0]\n    axes[ind].imshow(img)\n    axes[ind].set_title(label)\n    axes[ind].axis('off')\n    \nplt.subplots_adjust(hspace = 0.4);","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Healthy"},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"tr = pd.read_csv(path + 'train.csv')\n\n\n#\n\n#Mapping label names to each label per image\ntr[\"label_name\"] = tr[\"label\"].astype(str).map(map_classes)\n\ntr = tr[tr['label_name'] == 'Healthy']\n\n\n#Plot random images and their labels\nrandom_index = np.random.randint(0, tr.shape[0]-1, 9)\n\nfig, axes = plt.subplots(3, 3, figsize = (15, 15))\naxes = axes.ravel()\n\nfor ind, i in enumerate(random_index):\n    img = cv2.imread(path + '/train_images/' + tr.iloc[i, [0]].values[0])\n    label = tr.iloc[i, [2]].values[0]\n    axes[ind].imshow(img)\n    axes[ind].set_title(label)\n    axes[ind].axis('off')\n    \nplt.subplots_adjust(hspace = 0.4);","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Obserervations\n\n1. Disease color and spread pattern in leaf epithelial cells vary disease to disease\n2. CMD effects shape and strcture of a leaf more than anyother disease\n3. CBB might be hard to identify due to lighting conditiona and other variations\n4. there seam to be multiple copies of same in image few catogory\n"},{"metadata":{},"cell_type":"markdown","source":"# Data Distribution"},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"tr = pd.read_csv(path + 'train.csv')\ntr[\"label_name\"] = tr[\"label\"].astype(str).map(map_classes)\nimport plotly.express as px\n\nfig = px.histogram(tr, x=\"label_name\")\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"As we can see in the plot above the we have 13times more images of CMD than CBB which is not an ideal distribution!! \n\nsolutions:\n    1. Reduce the number of CMD samples!\n    2. Increase the nuber of other samples!\n    \n\n### Upcoming : Cycle GAN\n\n\n\n# External Data"},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"path2 = '../input/cropped-cassava'\ntr2 = pd.read_csv(path2 + '/cropped_cassava.csv')\ntr[\"label_name\"] = tr[\"label\"].astype(str).map(map_classes)\nimport plotly.express as px\n\nfig = px.histogram(tr, x=\"label_name\")\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# When you combine both Data"},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"frame_combined = pd.concat([tr, tr2], ignore_index=True)\nframe_combined[\"label_name\"] = frame_combined[\"label\"].astype(str).map(map_classes)\nimport plotly.express as px\n\nfig = px.histogram(frame_combined, x=\"label_name\")\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Lets Configure GPU/TPU"},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"\n\n# TPU or GPU detection\n# Detect hardware, return appropriate distribution strategy\ntry:\n    tpu = tf.distribute.cluster_resolver.TPUClusterResolver()\n    print('Running on TPU ', tpu.master())\nexcept ValueError:\n    tpu = None\n\nif tpu:\n    tf.config.experimental_connect_to_cluster(tpu)\n    tf.tpu.experimental.initialize_tpu_system(tpu)\n    strategy = tf.distribute.experimental.TPUStrategy(tpu)\nelse:\n    strategy = tf.distribute.get_strategy()\n    \ndef seed_everything(seed=0):\n    np.random.seed(seed)\n    tf.random.set_seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    os.environ['TF_DETERMINISTIC_OPS'] = '1'\n\nseed = 2048\nseed_everything(seed)\nprint(\"REPLICAS: \", strategy.num_replicas_in_sync)\n\n# Data access\n#GCS_DS_PATH = KaggleDatasets().get_gcs_path()\n\n\nAUTO = tf.data.experimental.AUTOTUNE\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Configure the Hyper parameters"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Configuration\nEPOCHS = 2\n\nAUTO = tf.data.experimental.AUTOTUNE\n# Configuration\nIMAGE_SIZE = [224, 224]\nIMG_SIZE = 224\nFOLDS = 3\nSEED = 777\nBATCH_SIZE = 8\nGCS_DS_PATH = path\nHEIGHT = 224\nWIDTH =224\nCLASSES = ['Cassava Bacterial Blight (CBB)','Cassava Brown Streak Disease (CBSD)','Cassava Green Mottle (CGM)','Cassava Mosaic Disease (CMD)','Healthy']","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Lets Desgin custom preprocessors"},{"metadata":{"trusted":true},"cell_type":"code","source":"\ndef transform_shear(image, height, shear):\n    # input image - is one image of size [dim,dim,3] not a batch of [b,dim,dim,3]\n    # output - image randomly sheared\n    DIM = height\n    XDIM = DIM%2 #fix for size 331\n    \n    shear = shear * tf.random.uniform([1],dtype='float32')\n    shear = math.pi * shear / 180.\n        \n    # SHEAR MATRIX\n    one = tf.constant([1],dtype='float32')\n    zero = tf.constant([0],dtype='float32')\n    c2 = tf.math.cos(shear)\n    s2 = tf.math.sin(shear)\n    shear_matrix = tf.reshape(tf.concat([one,s2,zero, zero,c2,zero, zero,zero,one],axis=0),[3,3])    \n\n    # LIST DESTINATION PIXEL INDICES\n    x = tf.repeat( tf.range(DIM//2,-DIM//2,-1), DIM )\n    y = tf.tile( tf.range(-DIM//2,DIM//2),[DIM] )\n    z = tf.ones([DIM*DIM],dtype='int32')\n    idx = tf.stack( [x,y,z] )\n    \n    # ROTATE DESTINATION PIXELS ONTO ORIGIN PIXELS\n    idx2 = K.dot(shear_matrix,tf.cast(idx,dtype='float32'))\n    idx2 = K.cast(idx2,dtype='int32')\n    idx2 = K.clip(idx2,-DIM//2+XDIM+1,DIM//2)\n    \n    # FIND ORIGIN PIXEL VALUES \n    idx3 = tf.stack( [DIM//2-idx2[0,], DIM//2-1+idx2[1,]] )\n    d = tf.gather_nd(image, tf.transpose(idx3))\n        \n    return tf.reshape(d,[DIM,DIM,3])\n\ndef transform_rotation(image, height, rotation):\n    # input image - is one image of size [dim,dim,3] not a batch of [b,dim,dim,3]\n    # output - image randomly rotated\n    DIM = height\n    XDIM = DIM%2 #fix for size 331\n    \n    rotation = rotation * tf.random.uniform([1],dtype='float32')\n    # CONVERT DEGREES TO RADIANS\n    rotation = math.pi * rotation / 180.\n    \n    # ROTATION MATRIX\n    c1 = tf.math.cos(rotation)\n    s1 = tf.math.sin(rotation)\n    one = tf.constant([1],dtype='float32')\n    zero = tf.constant([0],dtype='float32')\n    rotation_matrix = tf.reshape(tf.concat([c1,s1,zero, -s1,c1,zero, zero,zero,one],axis=0),[3,3])\n\n    # LIST DESTINATION PIXEL INDICES\n    x = tf.repeat( tf.range(DIM//2,-DIM//2,-1), DIM )\n    y = tf.tile( tf.range(-DIM//2,DIM//2),[DIM] )\n    z = tf.ones([DIM*DIM],dtype='int32')\n    idx = tf.stack( [x,y,z] )\n    \n    # ROTATE DESTINATION PIXELS ONTO ORIGIN PIXELS\n    idx2 = K.dot(rotation_matrix,tf.cast(idx,dtype='float32'))\n    idx2 = K.cast(idx2,dtype='int32')\n    idx2 = K.clip(idx2,-DIM//2+XDIM+1,DIM//2)\n    \n    # FIND ORIGIN PIXEL VALUES \n    idx3 = tf.stack( [DIM//2-idx2[0,], DIM//2-1+idx2[1,]] )\n    d = tf.gather_nd(image, tf.transpose(idx3))\n        \n    return tf.reshape(d,[DIM,DIM,3])\n\n\ndef decode_image(filename, label=None, image_size=(224, 224)):\n    bits = tf.io.read_file(filename)\n    image = tf.image.decode_jpeg(bits, channels=3)\n    image = tf.cast(image, tf.float32) / 255.0\n    image = tf.image.resize(image, image_size)\n    \n    if label is None:\n        return image\n    else:\n        return image, label\n\nimport numpy as np\nimport random\nimport cv2\n\ndef Image_Augmentation(method):\n    def data_augment(image):\n        image = tf.image.random_flip_left_right(image)\n        image = tf.image.random_flip_up_down(image)\n\n        return image\n    \n    \n    def data_augment2(image):\n        p_rotation = tf.random.uniform([], 0, 1.0, dtype=tf.float32)\n        p_spatial = tf.random.uniform([], 0, 1.0, dtype=tf.float32)\n        p_rotate = tf.random.uniform([], 0, 1.0, dtype=tf.float32)\n        p_pixel_1 = tf.random.uniform([], 0, 1.0, dtype=tf.float32)\n        p_pixel_2 = tf.random.uniform([], 0, 1.0, dtype=tf.float32)\n        p_pixel_3 = tf.random.uniform([], 0, 1.0, dtype=tf.float32)\n        p_shear = tf.random.uniform([], 0, 1.0, dtype=tf.float32)\n        p_crop = tf.random.uniform([], 0, 1.0, dtype=tf.float32)\n\n        # Shear\n        if p_shear > .2:\n            if p_shear > .6:\n                image = transform_shear(image, HEIGHT, shear=20.)\n            else:\n                image = transform_shear(image, HEIGHT, shear=-20.)\n        # Rotation\n        if p_rotation > .2:\n            if p_rotation > .6:\n                image = transform_rotation(image, HEIGHT, rotation=45.)\n            else:\n                image = transform_rotation(image, HEIGHT, rotation=-45.)\n        # Flips\n        image = tf.image.random_flip_left_right(image)\n        image = tf.image.random_flip_up_down(image)\n        if p_spatial > .75:\n            image = tf.image.transpose(image)\n        # Rotates\n        if p_rotate > .75:\n            image = tf.image.rot90(image, k=3) # rotate 270º\n        elif p_rotate > .5:\n            image = tf.image.rot90(image, k=2) # rotate 180º\n        elif p_rotate > .25:\n            image = tf.image.rot90(image, k=1) # rotate 90º\n        # Pixel-level transforms\n        if p_pixel_1 >= .4:\n            image = tf.image.random_saturation(image, lower=.7, upper=1.3)\n        if p_pixel_2 >= .4:\n            image = tf.image.random_contrast(image, lower=.8, upper=1.2)\n        if p_pixel_3 >= .4:\n            image = tf.image.random_brightness(image, max_delta=.1)\n        # Crops\n        if p_crop > .7:\n            if p_crop > .9:\n                image = tf.image.central_crop(image, central_fraction=.6)\n            elif p_crop > .8:\n                image = tf.image.central_crop(image, central_fraction=.7)\n            else:\n                image = tf.image.central_crop(image, central_fraction=.8)\n        elif p_crop > .4:\n            crop_size = tf.random.uniform([], int(HEIGHT*.6), HEIGHT, dtype=tf.int32)\n            image = tf.image.random_crop(image, size=[crop_size, crop_size, CHANNELS])\n\n        return image\n\n\n\n    if method == \"preporcess1\":\n            return data_augment\n\n    if method == \"preporcess2\":\n            return data_augment2\n\n        \n        \n\n\n\n\ndata_augment = Image_Augmentation(method=\"preporcess2\")\n\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Load the Dataset and visualize augmented images"},{"metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"!mkdir dataset","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"\ndef append_path(pre):\n    return np.vectorize(lambda file: os.path.join(GCS_DS_PATH, pre, file))\n\n\n\n\nsub = pd.read_csv(path+'/sample_submission.csv')\n\nsub[\"label\"] = sub[\"label\"].astype(\"str\")\ntest_paths = append_path('test_images')(sub.image_id.values)\n\n\n\ntrain  = pd.read_csv(path+'/train.csv')\n\ntrain[\"label\"] = train[\"label\"].astype(\"str\")\n\ntrain_paths = append_path('train_images')(sub.image_id.values)\n\n\npath2 = '../input/cropped-cassava'\ntrain2 = pd.read_csv(path2 + '/cropped_cassava.csv')\ntrain2[\"label\"] = train2[\"label\"].astype(\"str\")\n\n\nframe_combined = pd.concat([train, train2], ignore_index=True)\n\nframe_combined[\"label\"] = frame_combined[\"label\"].astype(\"str\")\n\nimport shutil\nimport os\n    \nsource_dir = path2+'/train/train/'\ntarget_dir = '/kaggle/working/dataset'\n    \nfile_names = os.listdir(source_dir)\n    \nfor file_name in file_names:\n    #try:\n    shutil.copy(os.path.join(source_dir, file_name), target_dir)\n\n            \nsource_dir = path+'/train_images/'\ntarget_dir = '/kaggle/working/dataset'\n    \nfile_names = os.listdir(source_dir)\n    \nfor file_name in file_names:\n    #try:\n    shutil.copy(os.path.join(source_dir, file_name), target_dir)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"\n    \n\ntrain_df, valid_df = train_test_split(train, test_size = 0.1, random_state = 1)\n\n\ntest_dataset = (\n    tf.data.Dataset\n    .from_tensor_slices(test_paths)\n    .map(decode_image, num_parallel_calls=AUTO)\n    .batch(BATCH_SIZE)\n)\n\n\n\n\ntrain_datagen = ImageDataGenerator(\n    rescale = 1./255,\n    rotation_range = 40,\n    height_shift_range = 0.2,\n    width_shift_range = 0.2,\n    zoom_range = 0.2,\n    shear_range = 0.2,\n    horizontal_flip = True,\n    fill_mode = 'nearest',\n    #preprocessing_function = data_augment\n)\n\nvalid_datagen = ImageDataGenerator(\n    rescale = 1./255\n)\n\n\ntrain_generator = train_datagen.flow_from_dataframe(\n    dataframe = frame_combined,\n    x_col = 'image_id',\n    y_col = 'label',\n    directory = '/kaggle/working/dataset',\n    target_size = (224,224),\n    batch_size = BATCH_SIZE,\n    shuffle = True,\n    class_mode = 'categorical'\n)\n\nvalidation_generator = valid_datagen.flow_from_dataframe(\n    dataframe = valid_df,\n    x_col = 'image_id',\n    y_col = 'label',\n    directory = path+'/train_images',\n    target_size = (224,224),\n    batch_size = BATCH_SIZE,\n    shuffle = False,\n    class_mode = 'categorical'\n)\n\ndef plotImages(images_arr):\n    fig, axes = plt.subplots(1, 10, figsize=(20,20))\n    axes = axes.flatten()\n    for img, ax in zip( images_arr, axes):\n        ax.imshow(img)\n    plt.tight_layout()\n    plt.show()\n    \n    \naugmented_images = [train_generator[0][0][0] for i in range(10)]\nplotImages(augmented_images)\naugmented_images = [train_generator[0][0][1] for i in range(10)]\nplotImages(augmented_images)\naugmented_images = [train_generator[0][0][2] for i in range(10)]\nplotImages(augmented_images)\naugmented_images = [train_generator[0][0][3] for i in range(10)]\nplotImages(augmented_images)\naugmented_images = [train_generator[0][0][4] for i in range(10)]\nplotImages(augmented_images)\n\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Learning rate scheduler"},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"# Learning rate schedule for TPU, GPU and CPU.\n# Using an LR ramp up because fine-tuning a pre-trained model.\n# Starting with a high LR would break the pre-trained weights.\n\nLR_START = 0.00001\nLR_MAX = 0.00005 * strategy.num_replicas_in_sync\nLR_MIN = 0.00001\nLR_RAMPUP_EPOCHS = 5\nLR_SUSTAIN_EPOCHS = 0\nLR_EXP_DECAY = .8\n\ndef lrfn(epoch):\n    if epoch < LR_RAMPUP_EPOCHS:\n        lr = (LR_MAX - LR_START) / LR_RAMPUP_EPOCHS * epoch + LR_START\n    elif epoch < LR_RAMPUP_EPOCHS + LR_SUSTAIN_EPOCHS:\n        lr = LR_MAX\n    else:\n        lr = (LR_MAX - LR_MIN) * LR_EXP_DECAY**(epoch - LR_RAMPUP_EPOCHS - LR_SUSTAIN_EPOCHS) + LR_MIN\n    return lr\n    \nlr_callback = tf.keras.callbacks.LearningRateScheduler(lrfn, verbose = True)\n\nrng = [i for i in range(25 if EPOCHS<25 else EPOCHS)]\ny = [lrfn(x) for x in rng]\nplt.plot(rng, y)\nprint(\"Learning rate schedule: {:.3g} to {:.3g} to {:.3g}\".format(y[0], max(y), y[-1]))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Efficientnet\n\n\nNote: Since we dont have access to Internt downloading ti form local copy in kaggle dataset"},{"metadata":{"trusted":true},"cell_type":"code","source":"import tensorflow as tf\n\nfrom keras.models import Model\nfrom tensorflow import keras\n\n\n\nimport sys\nsys.path.append('/kaggle/input/efficientnet-keras-dataset/efficientnet_kaggle')\n! pip install -e /kaggle/input/efficientnet-keras-dataset/efficientnet_kaggle\nimport efficientnet.tfkeras as efn\n\n\ndef get_model_Effi():\n    with strategy.scope():    \n        pretrained_efnet= efn.EfficientNetB3(\n                            input_shape=(IMG_SIZE, IMG_SIZE, 3),\n                            weights='imagenet',\n                            include_top=False\n                            )\n\n        for layer in pretrained_efnet.layers:\n          layer.trainable = False\n\n\n        #tf.keras.layers.GlobalAveragePooling2D(),\n                    #tf.keras.layers.Dense(len(CLASSES), activation='softmax',dtype='float32')\n\n\n        x2 = pretrained_efnet.output\n        x2 = tf.keras.layers.AveragePooling2D(name=\"averagepooling2d_head\")(x2)\n        x2 = tf.keras.layers.Flatten(name=\"flatten_head\")(x2)\n        x2 = tf.keras.layers.Dense(64, activation=\"relu\", name=\"dense_head\")(x2)\n        x2 = tf.keras.layers.Dropout(0.5, name=\"dropout_head\")(x2)\n        model_out = tf.keras.layers.Dense(len(CLASSES), activation='softmax', name=\"predictions_head\")(x2)\n\n        model_efnet = Model(inputs=pretrained_efnet.input, outputs=model_out)\n        model_efnet.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.0001),loss='categorical_crossentropy',metrics=['accuracy'])\n        #model_efnet.summary()\n    return model_efnet\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# DenseNet201 \n\n### Feel free to build your own model here!!"},{"metadata":{"trusted":true},"cell_type":"code","source":"from tensorflow.keras.applications import DenseNet201\n\ndef get_model():\n    with strategy.scope():\n        rnet = DenseNet201(\n            input_shape=(IMAGE_SIZE[0], IMAGE_SIZE[1], 3),\n            weights='imagenet',\n            include_top=False\n        )\n        # trainable rnet\n        rnet.trainable = True\n        model = tf.keras.Sequential([\n            rnet,\n            tf.keras.layers.GlobalAveragePooling2D(),\n            tf.keras.layers.Dense(len(CLASSES), activation='softmax',dtype='float32')\n        ])\n    model.compile(\n        optimizer='adam',\n        loss = 'sparse_categorical_crossentropy',\n        metrics=['sparse_categorical_accuracy']\n    )\n    return model","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# SE-Resnect 101\n\n**upcoming**\n"},{"metadata":{},"cell_type":"markdown","source":"# Train and Cross-Validation with Kfold"},{"metadata":{},"cell_type":"markdown","source":"## Choose the best model!!\n### Feel free to add your metrics here"},{"metadata":{"trusted":true},"cell_type":"code","source":"def getbestmodel(models,histories):\n    valloss = []\n    for history in histories:\n        valloss.append(history.history['val_loss'][len(history.history['val_loss'])-1])\n    minpos = valloss.index(min(valloss)) \n    return models[minpos]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\ntrain_data  = pd.read_csv(path+'/train.csv')\ntrain_data[\"label\"] = train_data[\"label\"].astype(\"str\")\n\nY = train_data[['label']]  \n\ndef train_cross_validate(folds = 5,modelType = 'Dense101'):\n    histories = []\n    models = []\n    early_stopping = tf.keras.callbacks.EarlyStopping(monitor = 'val_loss', patience = 3)\n\n\n    kfold = KFold(folds, shuffle = True, random_state = SEED)\n    f = 0\n    for train_index, val_index in kfold.split(Y):\n        \n\n        training_data = train_data.iloc[train_index]\n        validation_data = train_data.iloc[val_index]\n\n\n        train_generator = train_datagen.flow_from_dataframe(\n            dataframe = frame_combined,\n            x_col = 'image_id',\n            y_col = 'label',\n            directory = '/kaggle/working/dataset',\n            target_size = (224,224),\n            batch_size = BATCH_SIZE,\n            shuffle = True,\n            class_mode = 'categorical'\n        )\n        validation_generator = valid_datagen.flow_from_dataframe(\n            dataframe = validation_data,\n            x_col = 'image_id',\n            y_col = 'label',\n            directory = path+'/train_images',\n            target_size = (224,224),\n            batch_size = BATCH_SIZE,\n            shuffle = False,\n            class_mode = 'categorical'\n        )\n\n\n\n        print(); print('#'*25)\n        print('### FOLD',f+1)\n        print('#'*25)\n        if modelType == 'Dense101':\n            model = get_model()\n        elif modelType == 'Effinet':\n            model = get_model_Effi()\n\n        history = model.fit(\n            train_generator, \n            #steps_per_epoch = STEPS_PER_EPOCH,\n            epochs = EPOCHS,\n            callbacks = [lr_callback],\n            validation_data=validation_generator,\n            #, early_stopping],\n            #validation_data = get_validation_dataset(val_dataset),\n            verbose=2\n        )\n\n        model.save(str(modelType)+'_epoch'+str(EPOCHS)+'_224x224_fold'+str(f)+'.h5')\n        models.append(model)\n        histories.append(history)\n        f += 1\n    return histories, models\n\n\ntest_images = os.listdir('/kaggle/input/cassava-leaf-disease-classification/test_images/')\nfrom PIL import Image\n\n\ndef train_and_predict(folds = 5,modelType = 'Dense101'):\n    \n    print('Start training %i folds'%folds)\n    histories, models = train_cross_validate(folds = folds, modelType = modelType)\n    print('Computing predictions...')\n    \n    \n    model = getbestmodel(models,histories)\n\n    predict = []\n\n    for i in test_images:\n        image = Image.open(f'/kaggle/input/cassava-leaf-disease-classification/test_images/{i}')\n        image = image.resize((224, 224))\n\n        image = np.asarray(image)\n        image = np.expand_dims(image, axis=0)\n\n        predict.append(np.argmax(model.predict(image)))\n        \n    submission = pd.DataFrame({'image_id': test_images, 'label': predict})\n    \n\n    submission.to_csv('submission.csv', index=None)\n\n\n    return histories, model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"histories, model = train_and_predict(folds = 2,modelType = 'Effinet')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"!rm -rf dataset","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Class Activation Mapping (CAM)"},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"def get_img_array(img_path, size):\n    # `img` is a PIL image of size 299x299\n    img = keras.preprocessing.image.load_img(img_path, target_size=size)\n    # `array` is a float32 Numpy array of shape (299, 299, 3)\n    array = keras.preprocessing.image.img_to_array(img)\n    # We add a dimension to transform our array into a \"batch\"\n    # of size (1, 299, 299, 3)\n    array = np.expand_dims(array, axis=0)\n    return array\n\n\ndef make_gradcam_heatmap(img_array, model, last_conv_layer_name, classifier_layer_names):\n    # First, we create a model that maps the input image to the activations\n    # of the last conv layer\n    last_conv_layer = model.get_layer(last_conv_layer_name)\n    last_conv_layer_model = keras.Model(model.inputs, last_conv_layer.output)\n\n    # Second, we create a model that maps the activations of the last conv\n    # layer to the final class predictions\n    classifier_input = keras.Input(shape=last_conv_layer.output.shape[1:])\n    x = classifier_input\n    for layer_name in classifier_layer_names:\n        x = model.get_layer(layer_name)(x)\n    classifier_model = keras.Model(classifier_input, x)\n\n    # Then, we compute the gradient of the top predicted class for our input image\n    # with respect to the activations of the last conv layer\n    with tf.GradientTape() as tape:\n        # Compute activations of the last conv layer and make the tape watch it\n        last_conv_layer_output = last_conv_layer_model(img_array)\n        tape.watch(last_conv_layer_output)\n        # Compute class predictions\n        preds = classifier_model(last_conv_layer_output)\n        top_pred_index = tf.argmax(preds[0])\n        top_class_channel = preds[:, top_pred_index]\n\n    # This is the gradient of the top predicted class with regard to\n    # the output feature map of the last conv layer\n    grads = tape.gradient(top_class_channel, last_conv_layer_output)\n\n    # This is a vector where each entry is the mean intensity of the gradient\n    # over a specific feature map channel\n    pooled_grads = tf.reduce_mean(grads, axis=(0, 1, 2))\n\n    # We multiply each channel in the feature map array\n    # by \"how important this channel is\" with regard to the top predicted class\n    last_conv_layer_output = last_conv_layer_output.numpy()[0]\n    pooled_grads = pooled_grads.numpy()\n    for i in range(pooled_grads.shape[-1]):\n        last_conv_layer_output[:, :, i] *= pooled_grads[i]\n\n    # The channel-wise mean of the resulting feature map\n    # is our heatmap of class activation\n    heatmap = np.mean(last_conv_layer_output, axis=-1)\n\n    # For visualization purpose, we will also normalize the heatmap between 0 & 1\n    heatmap = np.maximum(heatmap, 0) / np.max(heatmap)\n    return heatmap\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"\nlast_conv_layer_name = \"top_conv\"\nclassifier_layer_names = [\n    \"top_bn\",\n    \"top_activation\",\n    \"averagepooling2d_head\",\n    \"flatten_head\",\n    \"dense_head\",\n    \"dropout_head\",\n    \"predictions_head\"\n]\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"# Prepare image\nimg_array = '../input/cassava-leaf-disease-classification/test_images/2216849948.jpg'\n\n\nimage = Image.open(img_array)\nimage = image.resize((224, 224))\n\nimage = np.asarray(image)\nimage = np.expand_dims(image, axis=0)\n\n\n# Make model\nmodel = model\n\n# Print what the top predicted class is\npreds = model.predict(image)\nprint(\"Predicted:\", preds)\n\n# Generate class activation heatmap\nheatmap = make_gradcam_heatmap(\n    image, model, last_conv_layer_name, classifier_layer_names\n)\n\n# Display heatmap\n#plt.matshow(heatmap)\n#plt.show()\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"from IPython.display import Image\nimport matplotlib.pyplot as plt\nimport matplotlib.cm as cm\n# We load the original image\n#img = keras.preprocessing.image.load_img(img_path)\n#img = keras.preprocessing.image.img_to_array(img)\n\n# We rescale heatmap to a range 0-255\nheatmap = np.uint8(255 * heatmap)\n\n# We use jet colormap to colorize heatmap\njet = cm.get_cmap(\"jet\")\n\n# We use RGB values of the colormap\njet_colors = jet(np.arange(256))[:, :3]\njet_heatmap = jet_colors[heatmap]\n\n# We create an image with RGB colorized heatmap\njet_heatmap = keras.preprocessing.image.array_to_img(jet_heatmap)\njet_heatmap = jet_heatmap.resize((img.shape[1], img.shape[0]))\njet_heatmap = keras.preprocessing.image.img_to_array(jet_heatmap)\n\n# Superimpose the heatmap on original image\nsuperimposed_img = jet_heatmap * 0.4 + img\nsuperimposed_img = keras.preprocessing.image.array_to_img(superimposed_img)\n\n# Save the superimposed image\nsave_path = \"leaf.jpg\"\nsuperimposed_img.save(save_path)\n\n# Display Grad CAM\ndisplay(Image(save_path))\n","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}