{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.7.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":33679,"databundleVersionId":3212216,"sourceType":"competition"}],"dockerImageVersionId":30163,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# 🌿Herbarium 2022 - FGVC9 EDA with Pytorch🍀\nIdentify plant species of the Americas from herbarium specimens","metadata":{}},{"cell_type":"markdown","source":"<img src = 'https://storage.googleapis.com/kaggle-competitions/kaggle/33679/logos/header.png?t=2022-02-14-16-38-02'>\n","metadata":{}},{"cell_type":"markdown","source":"## Content\n- **Load Dataset**\n- **JSON -> DataFrame**\n- **Mapping genus**\n- **Data Visualization**\n- **Modeling**\n- **Train & Evaluate**\n- **Conclusion**\n\n<br>\n\n**If it helped about this Notebook, Please Upvote!!**\n<br>\n\n**Feedback is always appreciated!!**","metadata":{}},{"cell_type":"markdown","source":"<a id=\"top\"></a>\n\n<div class=\"list-group\" id=\"list-tab\" role=\"tablist\">\n<h3 class=\"list-group-item list-group-item-action active\" data-toggle=\"list\" style='color:white; background:green; border:0' role=\"tab\" aria-controls=\"home\">\n<center>Load Dataset</center></h3>","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport json\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport cv2\n\ntrain_dir = '../input/herbarium-2022-fgvc9/train_images/'\ntest_dir = '../input/herbarium-2022-fgvc9/test_images/'\n\nwith open(\"../input/herbarium-2022-fgvc9/train_metadata.json\") as json_file:\n    train_meta = json.load(json_file)\nwith open(\"../input/herbarium-2022-fgvc9/test_metadata.json\") as json_file:\n    test_meta = json.load(json_file)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"top\"></a>\n\n<div class=\"list-group\" id=\"list-tab\" role=\"tablist\">\n<h3 class=\"list-group-item list-group-item-action active\" data-toggle=\"list\" style='color:white; background:green; border:0' role=\"tab\" aria-controls=\"home\">\n<center>JSON -> DataFrame</center></h3>","metadata":{}},{"cell_type":"code","source":"image_ids = [image[\"image_id\"] for image in train_meta[\"images\"]]\nimage_dirs = [train_dir + image['file_name'] for image in train_meta[\"images\"]]\ncategory_ids = [annotation['category_id'] for annotation in train_meta['annotations']]\ngenus_ids = [annotation['genus_id'] for annotation in train_meta['annotations']]\n\ntest_ids = [image['image_id'] for image in test_meta]\ntest_dirs = [test_dir + image['file_name'] for image in test_meta]\n\ntrain_df = pd.DataFrame({\n    \"image_id\" : image_ids,\n    \"image_dir\" : image_dirs,\n    \"category\" : category_ids,\n    \"genus\" : genus_ids})\n\ntest_df = pd.DataFrame({\n    \"test_id\" : test_ids,\n    \"test_dir\" : test_dirs\n})\n\n\ntrain_df.head()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"top\"></a>\n\n<div class=\"list-group\" id=\"list-tab\" role=\"tablist\">\n<h3 class=\"list-group-item list-group-item-action active\" data-toggle=\"list\" style='color:white; background:green; border:0' role=\"tab\" aria-controls=\"home\">\n<center>Mapping genus</center></h3>","metadata":{}},{"cell_type":"code","source":"genus_map = {genus['genus_id'] : genus['genus'] for genus in train_meta['genera']}\ntrain_df['genus'] = train_df['genus'].map(genus_map)\ntrain_df","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print('Top 15 Genus ')\nprint(train_df['genus'].value_counts().head(15))\nprint()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"top\"></a>\n\n<div class=\"list-group\" id=\"list-tab\" role=\"tablist\">\n<h3 class=\"list-group-item list-group-item-action active\" data-toggle=\"list\" style='color:white; background:green; border:0' role=\"tab\" aria-controls=\"home\">\n<center>Data Visualization</center></h3>","metadata":{}},{"cell_type":"code","source":"data = train_df['genus'].value_counts().head(15)\ndata = pd.DataFrame({'Genus' : data.index,\n                     'values' : data.values})\nplt.figure(figsize = (20, 10))\nsns.barplot(x='values', y = 'Genus', data = data , palette='summer_r')\nplt.show()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def show_images(speices):\n    images = train_df.loc[train_df['genus'] == speices]['image_dir'][:6]\n    i = 1\n    fig = plt.figure(figsize = (18, 18))\n    plt.suptitle(speices, fontsize = '30')\n    for image in images:\n        img = cv2.imread(image)\n        ax = fig.add_subplot(2, 3, i)\n        ax.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))\n        ax.set_axis_off()\n        i += 1\n    plt.show()","metadata":{"_kg_hide-output":true,"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"show_images('Carex')","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"show_images('Astragalus')","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"show_images('Penstemon')","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"show_images('Eriogonum')","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"show_images('Erigeron')","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"top\"></a>\n\n<div class=\"list-group\" id=\"list-tab\" role=\"tablist\">\n<h3 class=\"list-group-item list-group-item-action active\" data-toggle=\"list\" style='color:white; background:green; border:0' role=\"tab\" aria-controls=\"home\">\n<center>Modeling</center></h3>","metadata":{}},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torchvision\nimport torchvision.transforms as transforms\nfrom torch.utils.data import Dataset, DataLoader\nfrom PIL import Image","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"BATCH = 128\nEPOCHS = 1\n\nLR = 0.01\nIM_SIZE = 224\n\nX_Train, Y_Train = train_df['image_dir'].values, train_df['category'].values\n\nTransform = transforms.Compose(\n    [transforms.ToTensor(),\n    transforms.Resize((IM_SIZE, IM_SIZE)),\n    transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))])","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class GetData(Dataset):\n    def __init__(self, FNames, Labels, Transform):\n        self.fnames = FNames\n        self.transform = Transform\n        self.labels = Labels         \n        \n    def __len__(self):\n        return len(self.fnames)\n\n    def __getitem__(self, index):       \n        x = Image.open(self.fnames[index])\n    \n        if \"train\" in self.fnames[index]:             \n            return self.transform(x), self.labels[index]\n        elif \"test\" in self.fnames[index]:            \n            return self.transform(x), self.fnames[index]\n                \ntrainset = GetData(X_Train, Y_Train, Transform)\ntrainloader = DataLoader(trainset, batch_size=BATCH, shuffle=True)\n\nN_Classes = train_df['category'].nunique()\nnext(iter(trainloader))[0].shape\n\ndevice = 'cuda:0' if torch.cuda.is_available() else 'cpu'\nmodel = torchvision.models.densenet169(pretrained=True)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df['category'].nunique()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(model.classifier.in_features) \nprint(model.classifier.out_features)\n\nfor param in model.parameters():\n    param.requires_grad = False\n    \nn_inputs = model.classifier.in_features\nlast_layer = nn.Linear(n_inputs, N_Classes)\nmodel.classifier = last_layer\nif torch.cuda.is_available():\n    model.cuda()\nprint(model.classifier.out_features)    \n\ncriterion = nn.CrossEntropyLoss()\noptimizer = torch.optim.Adam(model.classifier.parameters())","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"top\"></a>\n\n<div class=\"list-group\" id=\"list-tab\" role=\"tablist\">\n<h3 class=\"list-group-item list-group-item-action active\" data-toggle=\"list\" style='color:white; background:green; border:0' role=\"tab\" aria-controls=\"home\">\n<center>Train & Evaluate</center></h3>","metadata":{}},{"cell_type":"code","source":"training_history = {'accuracy':[],'loss':[]}\nvalidation_history = {'accuracy':[],'loss':[]}\n\nfrom tqdm import tqdm\n\ndef train(trainloader, model, criterion, optimizer, scaler, device=torch.device(\"cpu\")):\n    train_acc = 0.0\n    train_loss = 0.0\n    for images, labels in tqdm(trainloader):\n        images = images.to(device)\n        labels = labels.to(device)\n        optimizer.zero_grad()\n    with torch.cuda.amp.autocast(enabled=True):\n        output = model(images)\n        loss = criterion(output, labels)\n        scaler.scale(loss).backward()\n        scaler.step(optimizer)\n        scaler.update()\n        acc = ((output.argmax(dim=1) == labels).float().mean())\n        train_acc += acc\n        train_loss += loss\n    return train_acc/len(trainloader), train_loss/len(trainloader)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"## Normal Evaluation\ndef evaluate(testloader, model, criterion, device=torch.device(\"cpu\")):\n    eval_acc = 0.0\n    eval_loss = 0.0\n    for images, labels in tqdm(testloader):\n        images = images.to(device)\n        labels = labels.to(device)\n        with torch.no_grad():\n            output = model(images)\n            loss = criterion(output, labels)\n\n        acc = ((output.argmax(dim=1) == labels).float().mean())\n        eval_acc += acc\n        eval_loss += loss\n  \n    return eval_acc/len(testloader), eval_loss/len(testloader)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%time\n#%dirsrmal Training\nscaler = torch.cuda.amp.GradScaler(enabled=True)\nfor epoch in range(EPOCHS):\n    train_acc, train_loss = train(trainloader, model, criterion, optimizer, scaler, device=device)\n    eval_acc, eval_loss = evaluate(val_loader, model, criterion, device=torch.device(\"cuda\"))\n    print(\"\")\n    print(f\"Epoch {epoch + 1} | Train Acc: {train_acc*100} | Train Loss: {train_loss}\")\n    print(f\"\\t Val Acc: {eval_acc*100} | Val Loss: {eval_loss}\")\n    print(\"====\"*8)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"markdown","source":"<a id=\"top\"></a>\n\n<div class=\"list-group\" id=\"list-tab\" role=\"tablist\">\n<h3 class=\"list-group-item list-group-item-action active\" data-toggle=\"list\" style='color:white; background:green; border:0' role=\"tab\" aria-controls=\"home\">\n<center>Conclusion</center></h3>","metadata":{}},{"cell_type":"code","source":"X_Test = test_df['test_dir'].values\ntestset = GetData(X_Test, None, Transform)\ntestloader = DataLoader(testset, batch_size=1, shuffle=False)\n\ns_ls = []\n\nwith torch.no_grad():\n    model.eval()\n    for image, fname in testloader: \n        image = image.to(device)\n        \nlogits = model(image)        \nps = torch.exp(logits)        \n_, top_class = ps.topk(1, dim=1)\n        \nfor pred in top_class:\n    s_ls.append([fname[0].split('/')[-1][:-4], pred.item()])\n            \nsub = pd.DataFrame.from_records(s_ls, columns=['Id', 'Predicted'])\nsub.head()\nsub.to_csv(\"submission.csv\", index=False)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Upvote!","metadata":{}}]}