{"cells":[{"metadata":{},"cell_type":"markdown","source":"# About this Competition \n\nAfter Melanoma , once again this year we have been treated with a classic computer vision classification problem . Its a great oppurtunity for anyone who has just started with CV to try their hands on this Live Competition and make it their first . On top of everything the metric for this competition is classification accuracy , how often does that happen . \n\nIn normal terms what is actually required of you is to become a Leaf doctor and help the farmers identify the infectious leaves and cure them at an affordable rate 😛\n \n# About this Notebook\n\n* As always this is a beginner Friendly Notebook in which I tell you , how you can efficiently become a leaf doctor with specialization in Cassava Leaf Diseases 😛 and with primary methodology being deep learning\n\n* I will cover everything you need to know , from the specialization knowledge to methodologies with baseline examples of different ideas that I suggest for solving the problem\n\n* Without much confusion , you can follow this notebook and make this your first Live CV competition\n\n* If you are completely new to machine learning and kaggle have a look at this [guide](https://www.kaggle.com/tanulsingh077/tackling-any-kaggle-competition-the-noob-s-way) I have written\n\n# Step 1 : Analyzing the Patient\n\n* What would be a first step that a Leaf doctor should do before anything considering the fact that his client can't speak ?\nThe answer is simple right , analyze what's wrong by looking at the patient\n\n* But how does a doctor understands if something is wrong by just looking at it? \nFor this as a doctor , he should know what a normal Patient/Leaf looks like and observe deviations (in pattern ,color, texture,etc) from the normal behavior to separate the healthy patients from infected ones . Now to further classify the infected ones into specific class of diseases doctor should also know how the patient/leaf condition looks like in different diseases\n\nWith these pointers in mind let's start with basic familarity"},{"metadata":{"trusted":true},"cell_type":"code","source":"import sys\nsys.path.append('../input/pytorch-image-models/pytorch-image-models-master')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# Preliminaries\nimport os\nfrom pathlib import Path\nimport glob\nfrom tqdm import tqdm\ntqdm.pandas()\nimport json\nimport pandas as pd\nimport numpy as np\n\n## Image hash\nimport imagehash\n\n# Visuals and CV2\nimport seaborn as sn\nimport matplotlib.pyplot as plt\nimport cv2\nfrom PIL import Image\n\n\n# albumentations for augs\nimport albumentations\nfrom albumentations.pytorch.transforms import ToTensorV2\n\n# clustering and dimension reduction\nfrom sklearn.cluster import KMeans\nfrom sklearn.decomposition import PCA\nfrom sklearn.model_selection import StratifiedKFold\nfrom sklearn.metrics import accuracy_score\n\n# Keras and TensorFlow\nfrom keras.preprocessing.image import load_img\nfrom keras.preprocessing.image import img_to_array \nfrom keras.applications.resnet50 import preprocess_input \n\n# models \nfrom keras.applications.resnet50 import ResNet50\nfrom keras.models import Model\n\n#torch\nimport torch\nimport timm\nimport torch\nimport torch.nn as nn\nfrom torch.nn import functional as F\nfrom torch.utils.data import Dataset,DataLoader","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Utils\n\nSection for Utility Functions"},{"metadata":{"trusted":true},"cell_type":"code","source":"def plot_images(class_id, label, images_number,verbose=0):\n    '''\n    Courtesy of https://www.kaggle.com/isaienkov/cassava-leaf-disease-classification-data-analysis\n    '''\n    plot_list = train[train[\"label\"] == class_id].sample(images_number)['image_id'].tolist()\n    \n    # Printing list of images\n    if verbose:\n        print(plot_list)\n        \n    labels = [label for i in range(len(plot_list))]\n    size = np.sqrt(images_number)\n    if int(size)*int(size) < images_number:\n        size = int(size) + 1\n        \n    plt.figure(figsize=(20, 20))\n    \n    for ind, (image_id, label) in enumerate(zip(plot_list, labels)):\n        plt.subplot(size, size, ind + 1)\n        image = cv2.imread(str(BASE_DIR/'train_images'/image_id))\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n\n        plt.imshow(image)\n        plt.title(label, fontsize=12)\n        plt.axis(\"off\")\n    \n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"BASE_DIR = Path('../input/cassava-leaf-disease-classification')\n\n## Reading DataFrame having Labels\ntrain = pd.read_csv(BASE_DIR/'train.csv')\n\n## Label Mappings\nwith open(BASE_DIR/'label_num_to_disease_map.json') as f:\n    mapping = json.loads(f.read())\n    mapping = {int(k): v for k,v in mapping.items()}\n\nprint(mapping)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<b>As we can see we have 4 diseases about which we will have to learn in this doctoe's course , we will dive deeper into each of them one by one framing our understanding about the characteristics and other things but before that lets map these disease names to labels in our dataset </b>"},{"metadata":{"trusted":true},"cell_type":"code","source":"train['label_names'] = train['label'].map(mapping)\ntrain.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Step 1.1 Learning about the Healthy ones\n\nNow we have everything in one place we can start looking at the healthy images and form our understanding of characteristic of healthy cassava leaves . `Below is the image of a healthy cassava leaf from Google` \n\n![](https://cdn.shortpixel.ai/client/to_avif,q_lossless,ret_img,w_795,h_532/https://organic.ng/wp-content/uploads/2017/02/CASSAVA-LEAF.jpg)\n\n* From the above image we can say that one of the characteristic of a Healthy Cassava Leaf is that it should be fairly green and upright without much cuts,texture change , yellowish gradient ,etc\n\nLet's now look at the healthy ones in the dataset and see if they are in close mix with the above image"},{"metadata":{"trusted":true},"cell_type":"code","source":"train[train['label_names']=='Healthy']['image_id'].count()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* Out of 21k images only 2577 are the healthy ones , the imbalance in labels is clearly visible"},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_images(class_id=4, \n    label='Healthy',\n    images_number=6,verbose=1)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Now if you run the above function three-four times and carefully observe the different images you see new images everytime , you will realize the following :\n* Not all the images have leaves close-up , some images might have the whole tree with leaves barely visible to human eye , some show more stem than leaves i.e to say the image set is fairly noisy\n* What's more surprising though is some of the images of healthy leaves look like they are infected and show a yellow or yellowish gradient type of color , which should be highly unlikely (we will have to investigate that)\n\n### Investigating Outliers :  \nTo investigate on point 2 , I have the following Idea :\n\n* The Idea here is to cluster the healthy Images and have a look at respective clusters to see if we can find the outlier cluster and damaged cluster.\n* We will use Resnet18 to generate features for clustering "},{"metadata":{"trusted":true},"cell_type":"code","source":"def extract_features(image_id, model):\n    file = BASE_DIR/'train_images'/image_id\n    # load the image as a 224x224 array\n    img = load_img(file, target_size=(224,224))\n    # convert from 'PIL.Image.Image' to numpy array\n    img = np.array(img) \n    # reshape the data for the model reshape(num_of_samples, dim 1, dim 2, channels)\n    reshaped_img = img.reshape(1,224,224,3) \n    # prepare image for model\n    imgx = preprocess_input(reshaped_img)\n    # get the feature vector\n    features = model.predict(imgx, use_multiprocessing=True)\n    \n    return features","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = ResNet50()\nmodel = Model(inputs = model.inputs, outputs = model.layers[-2].output)\n\nhealthy = train[train['label']==4]\nhealthy['features'] = healthy['image_id'].progress_apply(lambda x:extract_features(x,model))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"features = np.array(healthy['features'].values.tolist()).reshape(-1,2048)\nimage_ids = np.array(healthy['image_id'].values.tolist())\n\n# Clustering\nkmeans = KMeans(n_clusters=5,n_jobs=-1, random_state=22)\nkmeans.fit(features)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"groups = {}\nfor file, cluster in zip(image_ids,kmeans.labels_):\n    if cluster not in groups.keys():\n        groups[cluster] = []\n        groups[cluster].append(file)\n    else:\n        groups[cluster].append(file)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def view_cluster(cluster):\n    plt.figure(figsize = (25,25));\n    # gets the list of filenames for a cluster\n    files = groups[cluster]\n    # only allow up to 30 images to be shown at a time\n    if len(files) > 30:\n        print(f\"Clipping cluster size from {len(files)} to 25\")\n        start = np.random.randint(0,len(files))\n        files = files[start:start+25]\n    # plot each image in the cluster\n    for index, file in enumerate(files):\n        plt.subplot(5,5,index+1);\n        img = load_img(BASE_DIR/'train_images'/file)\n        img = np.array(img)\n        plt.imshow(img)\n        plt.title(file)\n        plt.axis('off')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"view_cluster(3)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* We have been able to cluster most of the outliers in cluster 3 and we can easily visualize them \n\n* We can see that there are quite some leaves which seem to be damaged , have brown spots etc and seem not to be healthy\n\nThere are numerous dicussion threads addressing the same topic :\n* https://www.kaggle.com/c/cassava-leaf-disease-classification/discussion/198363 -- Wrong Labels\n* https://www.kaggle.com/c/cassava-leaf-disease-classification/discussion/199606 --  Quality of Labels\n\nNow we should not be worried about the noise in the training set , but what if the noise is contained in the test set and the labelling is done similarly , then it might be a problem , we can't remove anything from training set untill we are sure\n\n\nSo Now let's summarize this sectionn\n\n` Characteristics of Healthy Cassava Leaves`:\n* Mostly green in color , upright with few or no brown spots\n* A uniform texture throughout the leave be it yellow or green"},{"metadata":{},"cell_type":"markdown","source":"### Learning about Disease 1 : Cassava Bacterial Blight (CBB)\n\nNow that we know how healthy cassava leaf looks like , let's move on to learn about the first disease . First things first , `Symptoms of CBB`:\n\n* black leaf spots and blights, angular leaf spots, and premature drying and shedding of leaves due to the wilting of young leaves\nand severe attack.\n\n* At first, angular, water-soaked spots occur on the leaves which are restricted by the veins; the spots are more clearly seen on the lower leaf surface. The spots expand rapidly, join together, especially along the margins of the leaves, and turn brown with yellow borders (Fig. 1)\n\n* Droplets of a creamy-white ooze occur at the centre of the spots; later, they turn yellow. \n\n![](https://www.pestnet.org/fact_sheets/assets/image/cassava_bacterial_blight_173/thumbs/cassavabb_sml.jpg)\n![](https://www.pestnet.org/fact_sheets/assets/image/cassava_bacterial_blight_173/thumbs/cassavabb2_sml.jpg)\n\n\nTo know more visit [here](https://www.pestnet.org/fact_sheets/cassava_bacterial_blight_173.htm)"},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_images(class_id=0, \n    label='CBB',\n    images_number=6,verbose=1)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* So From our knowledge of symptoms we can say that these are having CBB disease for sure and we also now know that getting the image of stem instead of the leaf itself might not be that wrong because some diseases can be judged through stem as well , so the images having stem might not be noise afterall, After viewing 6-7 different sets , there seems to be no outliers in the this category\n\n* In some of the image like IMG - '1926670152.jpg' , the brown spot is very very small and the leaf looks more like a healthy one and a lot of healthy images also have such small brown and might be tough to identify\n\n* From my understanding of Disease in this category , I can say RandomCropping, Contrast change , color change of any kind might not be a good idea"},{"metadata":{},"cell_type":"markdown","source":"### Learning about Disease 2 : Cassava Green Mottle (CGM)\n\nMoving onto the next disease , `Symptoms of CGM`:\n\n* This disease causes white spotting of leaves, which increase from the initial small spots to cover the entire leaf causing\nloss of chlorophyll. Young leaves are puckered with faint to distinct yellow spots (Fig 1)\n\n* Leaves with this disease show mottled symptoms which can be confused with symptoms of cassava mosaic disease (CMD). Severely damaged\nleaves shrink, dry out and fall off, which can cause a characteristic candle-stick appearance. (fig 2)\n\n![](https://www.pestnet.org/fact_sheets/assets/image/cassava_green_mottle_068/thumbs/cgmv2_sml.jpg)\n![](https://www.pestnet.org/fact_sheets/assets/image/cassava_green_mottle_068/thumbs/cgmv_sml.jpg)\n\nTo know more visit [here](https://www.pestnet.org/fact_sheets/cassava_green_mottle_068.htm)"},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_images(class_id=2, \n    label='CGM',\n    images_number=12,verbose=1)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Inferences\n\n* After reading the symptoms of CGM and viewing the images from the dataset we can clearly tell the difference between CGM leaves , CBB leaves and healthy leaves\n* CGM leaves have faint to yellow spots on the leaves along the viens , CBB leaves have brown spots , and healthy leaves are either totally green or totally yellow\n* Also there are not much outliers in this class as well\n\n\n### Learning about Disease 3 : Cassava mosaic disease (CMD)\n\n`Symptoms of CMD`:\n\n* CMD produces a variety of foliar symptoms that include mosaic, mottling, misshapen and twisted leaflets, and\nan overall reduction in size of leaves and plants\n\n* Leaves affected by this disease have patches of normal green color mixed with different proportions of yellow and white depending on the severity"},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_images(class_id=3, \n    label='CMD',\n    images_number=6,verbose=1)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Inferences\n\n* We can see that CGM and CMD have very close symptoms and also have pretty similar images , often experts might get confused labelling these , we could only imagine how big a challenge it will be for the model\n\n* There seems to be no or very less outliers in this category as well"},{"metadata":{},"cell_type":"markdown","source":"### Learning about Disease 4 : Cassava Brown Streak Disease\n\nNow the reason I have chosen this for the last , is because we have two different kind of images for this category :\n\n* One is the Image of Leaves/plant off course\n* Another is the image of Tuburous Roots which can be easily misunderstood with potato or some kind of noise , because of the fact that dataset has noises kind of make us bias towards this assupmtion . Hence just to be clear those brown awkward looking things in the dataset are Tuburous Roots of Cassave Plant and This disease can also be identified through them\n\nNow let's quickly look at `Symptoms of CBSD`:\n\n* CBSD leaf symptoms consist of a characteristic yellow or necrotic vein banding which may enlarge and coalesce to form comparatively large yellow patches.\n* Tuberous root symptoms consist of dark-brown necrotic areas within the tuber and reduction in root size\n\nSo now we have a clear understanding of the two types of images present in this category and also the symptoms found in those two different images , lets look at the data"},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_images(class_id=1, \n    label='CBSD',\n    images_number=12,verbose=1)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* Let's try and see if we can get the cluster of Tubular Root Images out of the data"},{"metadata":{"trusted":true},"cell_type":"code","source":"CBSD = train[train['label']==1]\nCBSD['features'] = CBSD['image_id'].progress_apply(lambda x:extract_features(x,model))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"features_cbsd = np.array(CBSD['features'].values.tolist()).reshape(-1,2048)\nimage_ids_cbsd = np.array(CBSD['image_id'].values.tolist())\n\n# Clustering\nkmeans_cbsd = KMeans(n_clusters=5,n_jobs=-1, random_state=22)\nkmeans_cbsd.fit(features_cbsd)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"groups_cbsd = {}\nfor file, cluster in zip(image_ids_cbsd,kmeans_cbsd.labels_):\n    if cluster not in groups_cbsd.keys():\n        groups_cbsd[cluster] = []\n        groups_cbsd[cluster].append(file)\n    else:\n        groups_cbsd[cluster].append(file)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def view_cluster(cluster):\n    plt.figure(figsize = (25,25))\n    # gets the list of filenames for a cluster\n    files = groups_cbsd[cluster]\n    # only allow up to 30 images to be shown at a time\n    if len(files) > 30:\n        print(f\"Clipping cluster size from {len(files)} to 25\")\n        start = np.random.randint(0,len(files))\n        files = files[start:start+25]\n    # plot each image in the cluster\n    for index, file in enumerate(files):\n        plt.subplot(5,5,index+1);\n        img = load_img(BASE_DIR/'train_images'/file)\n        img = np.array(img)\n        plt.imshow(img)\n        plt.title(file)\n        plt.axis('off')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"view_cluster(4)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* We were successfully able to cluster the Tubular Root Images into one cluster of 80 Images and hence now we can get all the IDS and might think of Various Ideas on how to use this information"},{"metadata":{},"cell_type":"markdown","source":"# Summary of Our Findings : End of Step 1\n\nLet's summarize our findings of our Initial EDA :\n\n* Healthy Images Might not be correctly labelled , the wrongly labelled images can be found in cluster 3 of our 5 cluster.\n* Completely Yellow Leaves might not always indicate that the leaf has potential Disease\n* Brown Spots on leaves is indicative of Cassava Bacterial Blight \n* All the Image have variety of different background and scales \n* Images have been captured during different times of the day and thus they have different lighting and exposure\n* Cassava Green Mottle (CGM) and Cassava mosaic disease (CMD) have very similar symptoms as well as Images and might be easily mislabelled as one another . Also since there are 13k examples from Cassava Mosiac Disease , its highly likely that the most mistakes are done by model in labelling CGM as CGM\n* One Image/Cassava Plant Might contain multiple co-occurring diseases . Model would find it confusing to Label\n* CBSD have two kind of Images in the dataset , one is of the plant/leaves and the other is of roots which can be easily misunderstood as potato or some random noise , we are able to cluster all such images into cluster number 4\n\n\nFirst step in becoming a Leaf Doctor is Completed , we have successfully understood our patient and various diseases that might occur. This step will help us device unique solutions/plans to build a better solution .\n\n<b>NOTE : I will keep on adding more such findings in this section as I keep finding more</b>"},{"metadata":{},"cell_type":"markdown","source":"## Duplicates in Data : Thing we missed\n\nAfter going through discussion forum I found [this](https://www.kaggle.com/c/cassava-leaf-disease-classification/discussion/198202) thread which talks about the possibility of duplicate Images in the dataset. It's really interesting when we talk about duplicates in an Image dataset, because there can be two meanings to this :\n\n* We are talking about the exact copy of an Image\n* We are talking about an Image which is similar to a particular Image . For Eg: Image 1 was cropped or rotated and stores as Image 2\n\nNow there are several ways to find and identify Duplicate (Exact Copy) and similar Images in an Image dataset . I will use the method of Image Hashing and follow the notebook that I found [here](https://www.kaggle.com/appian/let-s-find-out-duplicate-images-with-imagehash)"},{"metadata":{"trusted":true},"cell_type":"code","source":"funcs = [\n        imagehash.average_hash,\n        imagehash.phash,\n        imagehash.dhash,\n        imagehash.whash,\n    ]\n\nimage_ids = []\nhashes = []\n\nfor path in tqdm(glob.glob(str(BASE_DIR/'train_images'/'*.jpg' ))):\n    image = Image.open(path)\n    image_id = os.path.basename(path)\n    image_ids.append(image_id)\n    hashes.append(np.array([f(image).hash for f in funcs]).reshape(256))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"hashes_all = np.array(hashes)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Convert numpy array into torch tensor to speed up similarity calculation."},{"metadata":{"trusted":true},"cell_type":"code","source":"hashes_all = torch.Tensor(hashes_all.astype(int)).cuda()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Calculate similarities among all image pairs. Divide the value by 256 to normalize (0-1)."},{"metadata":{"trusted":true},"cell_type":"code","source":"%time sims = np.array([(hashes_all[i] == hashes_all).sum(dim=1).cpu().numpy()/256 for i in range(hashes_all.shape[0])])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Thresholding"},{"metadata":{"trusted":true},"cell_type":"code","source":"indices1 = np.where(sims > 0.9)\nindices2 = np.where(indices1[0] != indices1[1])\nimage_ids1 = [image_ids[i] for i in indices1[0][indices2]]\nimage_ids2 = [image_ids[i] for i in indices1[1][indices2]]\ndups = {tuple(sorted([image_ids1,image_ids2])):True for image_ids1, image_ids2 in zip(image_ids1, image_ids2)}\nprint('found %d duplicates' % len(dups))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Plotting the duplicate Images"},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\ncode taken from https://www.kaggle.com/nakajima/duplicate-train-images?scriptVersionId=47295222\n'''\n\nduplicate_image_ids = sorted(list(dups))\n\nfig, axs = plt.subplots(2, 2, figsize=(15,15))\n\nfor row in range(2):\n        for col in range(2):\n            img_id = duplicate_image_ids[row][col]\n            img = Image.open(str(BASE_DIR/'train_images'/img_id))\n            label =str(train.loc[train['image_id'] == img_id].label.values[0])\n            axs[row, col].imshow(img)\n            axs[row, col].set_title(\"image_id : \"+ img_id + \"  label : \" + label)\n            axs[row, col].axis('off')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We have other methods to find duplicates that will help us in identifying more soft duplicates if any in the dataset , that will come in later versions of this kernel"},{"metadata":{},"cell_type":"markdown","source":"# Step 2 : Learning About the Methodology\n\nHello Doctors welcome to your second year ,in order to complete your final assignment , you now need to understand the tools you have at your disposal and how to use them , below is a step by step guide to be followed in order to learn the tools\n\n* [Beginner Article](https://adeshpande3.github.io/adeshpande3.github.io/A-Beginner's-Guide-To-Understanding-Convolutional-Neural-Networks/)\n* [Course By Andrew NG](https://www.coursera.org/learn/convolutional-neural-networks)\n* [Applying CNNS using Keras and tensorflow](https://www.coursera.org/learn/convolutional-neural-networks-tensorflow)\n* [Course from Fast.ai](https://course.fast.ai/videos/?lesson=1)"},{"metadata":{},"cell_type":"markdown","source":"# Step 3: Building Final Project\n\n\nOhk now Docs , its time for you to build the final project . Since this is the final project it is meant for everyone to be built by themselves , here I will just write the summary of what I have used and also suggest ways that can improve the project further.\n\nAt Last I also add things to try out / look out for in the entire course of the competition\n\n`Summary of Baseline Model`:\n\nThis model is based on the winning solution of Cassava 2019 competition and I will try to replicate it as close as possible:\n\n* SE-ResNext50\n* Dimension = (384,384)\n* Epochs = 10\n* Custom LR scheduler \n* Weights saved on best loss : Categorical CrossEntropy\n* Basic Augs : HorizontalFlip,VerticalFlip,Rotate,RandomBrightness,ShiftScaleRotate,cutout,centercrop,zoom,randomscale\n* No TTA\n\n<font color ='red' >Note : As I am limited to kaggle for GPU's my five folds model is still running and hence for now I just use the pretrained weights of SeResNext50 , This notebook will be updated several times with different configs /ideas so keep tuning in</color>"},{"metadata":{},"cell_type":"markdown","source":"## Configuration and utility Functions"},{"metadata":{"trusted":true},"cell_type":"code","source":"DIM = (384,384)\n\nNUM_WORKERS = 12\nTEST_BATCH_SIZE = 16\nSEED = 2020\n\nDEVICE = \"cuda\"\n\nMEAN = [0.485, 0.456, 0.406]\nSTD = [0.229, 0.224, 0.225]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Augmentations"},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_test_transforms():\n\n    return albumentations.Compose(\n        [albumentations.Normalize(MEAN, STD, max_pixel_value=255.0, always_apply=True),\n        ToTensorV2(p=1.0)\n        ]\n    )","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Cassava Dataset"},{"metadata":{"trusted":true},"cell_type":"code","source":"class CassavaDataset(Dataset):\n    def __init__(self,image_ids,labels,dimension=None,augmentations=None):\n        super().__init__()\n        self.image_ids = image_ids\n        self.labels = labels\n        self.dim = dimension\n        self.augmentations = augmentations\n        \n    def __len__(self):\n        return len(self.image_ids)\n    \n    def __getitem__(self,idx):\n        \n        img = cv2.imread(str(BASE_DIR/'test_images'/self.image_ids[idx]))\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n                         \n        if self.dim:\n            img = cv2.resize(img,self.dim)\n        \n        if self.augmentations:\n            augmented = self.augmentations(image=img)\n            image = augmented['image']\n                         \n        return {\n            'image': image,\n            'target': torch.tensor(self.labels[idx],dtype=torch.float)\n        }","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Model : SE_Resnext50"},{"metadata":{"trusted":true},"cell_type":"code","source":"class CassavaModel(nn.Module):\n    def __init__(self, model_name='seresnext50_32x4d',out_features=5,pretrained=True):\n        super().__init__()\n        self.model = timm.create_model(model_name, pretrained=pretrained)\n        \n        n_features = self.model.last_linear.in_features\n        self.model.last_linear = nn.Linear(n_features, out_features)\n\n    def forward(self, x):\n        x = self.model(x)\n        return x","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Prediction Function Single Model"},{"metadata":{"trusted":true},"cell_type":"code","source":"def predict_single_model(data_loader,model,device):\n    model.eval()\n    tk0 = tqdm(enumerate(data_loader), total=len(data_loader))\n    fin_out = []\n    \n    with torch.no_grad():\n        \n        for bi, d in tk0:\n            images = d['image']\n            targets = d['target']\n            \n            images = images.to(device)\n            targets = targets.to(device)\n            \n            batch_size = images.shape[0]\n            \n            outputs = model(images)\n            \n            fin_out.append(F.softmax(outputs, dim=1).detach().cpu().numpy())\n            \n    return np.concatenate(fin_out)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Engine"},{"metadata":{"trusted":true},"cell_type":"code","source":"sample_sub = pd.read_csv('../input/cassava-leaf-disease-classification/sample_submission.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def predict(weights):\n    '''\n    weights : List of paths in case of K fold model inference\n    '''\n    pred = np.zeros((len(sample_sub),5,5))\n    \n    # Defining DataSet\n    test_dataset = CassavaDataset(\n        image_ids=sample_sub['image_id'].values,\n        labels=sample_sub['label'].values,\n        augmentations=get_test_transforms(),\n        dimension = DIM\n    )\n    \n    test_loader = torch.utils.data.DataLoader(\n        test_dataset,\n        batch_size=TEST_BATCH_SIZE,\n        num_workers=NUM_WORKERS,\n        shuffle=False,\n        pin_memory=True,\n        drop_last=False,\n    )\n    \n    # Defining Device\n    device = torch.device(\"cpu\")\n    \n    for i,weight in enumerate(weights):\n        # Defining Model for specific fold\n        model = CassavaModel(out_features=5,pretrained=True)\n        \n        # loading weights\n        #model.load_state_dict(torch.load(weight))\n        model.to(device)\n        \n        #predicting\n        pred[:,:,i] = predict_single_model(test_loader,model,device)\n    \n    return pred","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Preparing Final Submission"},{"metadata":{"trusted":true},"cell_type":"code","source":"pred = predict([1])\nprint(pred)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"pred = pred.mean(axis=-1)\nprint('Prediction Before Argmax',pred)\npred = pred.argmax(axis=1)\nprint('Final Prediction',pred)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sample_sub['label'] = pred\nsample_sub.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sample_sub.to_csv('submission.csv',index=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Conclusion\n\nThere is a lot to try as the competition is just starting , I will try to keep this notebook updated\n\nThanks for reading my notebook , I hope you got something helpful out of it"}],"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}