{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"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","execution":{"iopub.status.busy":"2022-02-16T07:34:25.60162Z","iopub.execute_input":"2022-02-16T07:34:25.601916Z","iopub.status.idle":"2022-02-16T07:34:35.036018Z","shell.execute_reply.started":"2022-02-16T07:34:25.601884Z","shell.execute_reply":"2022-02-16T07:34:35.035298Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2022-02-16T07:34:35.037524Z","iopub.execute_input":"2022-02-16T07:34:35.037782Z","iopub.status.idle":"2022-02-16T07:34:36.400209Z","shell.execute_reply.started":"2022-02-16T07:34:35.037736Z","shell.execute_reply":"2022-02-16T07:34:36.399537Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2022-02-16T07:34:36.401487Z","iopub.execute_input":"2022-02-16T07:34:36.401875Z","iopub.status.idle":"2022-02-16T07:34:36.432919Z","shell.execute_reply.started":"2022-02-16T07:34:36.401837Z","shell.execute_reply":"2022-02-16T07:34:36.432206Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('Top 15 Genus ')\nprint(train_df['genus'].value_counts().head(15))\nprint()","metadata":{"execution":{"iopub.status.busy":"2022-02-16T07:34:36.434962Z","iopub.execute_input":"2022-02-16T07:34:36.435345Z","iopub.status.idle":"2022-02-16T07:34:36.524594Z","shell.execute_reply.started":"2022-02-16T07:34:36.435287Z","shell.execute_reply":"2022-02-16T07:34:36.523872Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2022-02-16T07:34:36.525911Z","iopub.execute_input":"2022-02-16T07:34:36.526708Z","iopub.status.idle":"2022-02-16T07:34:37.011788Z","shell.execute_reply.started":"2022-02-16T07:34:36.526668Z","shell.execute_reply":"2022-02-16T07:34:37.011092Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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,"execution":{"iopub.status.busy":"2022-02-16T07:34:37.013417Z","iopub.execute_input":"2022-02-16T07:34:37.013812Z","iopub.status.idle":"2022-02-16T07:34:37.021786Z","shell.execute_reply.started":"2022-02-16T07:34:37.01376Z","shell.execute_reply":"2022-02-16T07:34:37.020961Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_images('Carex')","metadata":{"execution":{"iopub.status.busy":"2022-02-16T07:34:37.023172Z","iopub.execute_input":"2022-02-16T07:34:37.023508Z","iopub.status.idle":"2022-02-16T07:34:38.450687Z","shell.execute_reply.started":"2022-02-16T07:34:37.023472Z","shell.execute_reply":"2022-02-16T07:34:38.446873Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_images('Astragalus')","metadata":{"execution":{"iopub.status.busy":"2022-02-16T07:34:38.452011Z","iopub.execute_input":"2022-02-16T07:34:38.452484Z","iopub.status.idle":"2022-02-16T07:34:40.23562Z","shell.execute_reply.started":"2022-02-16T07:34:38.452439Z","shell.execute_reply":"2022-02-16T07:34:40.234848Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_images('Penstemon')","metadata":{"execution":{"iopub.status.busy":"2022-02-16T07:34:40.236896Z","iopub.execute_input":"2022-02-16T07:34:40.237246Z","iopub.status.idle":"2022-02-16T07:34:41.29945Z","shell.execute_reply.started":"2022-02-16T07:34:40.237212Z","shell.execute_reply":"2022-02-16T07:34:41.29882Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_images('Eriogonum')","metadata":{"execution":{"iopub.status.busy":"2022-02-16T07:34:41.30185Z","iopub.execute_input":"2022-02-16T07:34:41.303715Z","iopub.status.idle":"2022-02-16T07:34:42.64334Z","shell.execute_reply.started":"2022-02-16T07:34:41.303676Z","shell.execute_reply":"2022-02-16T07:34:42.642698Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_images('Erigeron')","metadata":{"execution":{"iopub.status.busy":"2022-02-16T07:34:42.644571Z","iopub.execute_input":"2022-02-16T07:34:42.644929Z","iopub.status.idle":"2022-02-16T07:34:43.665848Z","shell.execute_reply.started":"2022-02-16T07:34:42.644893Z","shell.execute_reply":"2022-02-16T07:34:43.665225Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2022-02-16T07:34:43.667076Z","iopub.execute_input":"2022-02-16T07:34:43.667473Z","iopub.status.idle":"2022-02-16T07:34:43.67294Z","shell.execute_reply.started":"2022-02-16T07:34:43.667433Z","shell.execute_reply":"2022-02-16T07:34:43.672303Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"BATCH = 128\nEPOCHS = 5\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":{"execution":{"iopub.status.busy":"2022-02-16T07:34:43.674119Z","iopub.execute_input":"2022-02-16T07:34:43.674998Z","iopub.status.idle":"2022-02-16T07:34:43.685528Z","shell.execute_reply.started":"2022-02-16T07:34:43.674957Z","shell.execute_reply":"2022-02-16T07:34:43.684534Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2022-02-16T07:34:43.686977Z","iopub.execute_input":"2022-02-16T07:34:43.687793Z","iopub.status.idle":"2022-02-16T07:34:48.018613Z","shell.execute_reply.started":"2022-02-16T07:34:43.687745Z","shell.execute_reply":"2022-02-16T07:34:48.017758Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df['category'].nunique()","metadata":{"execution":{"iopub.status.busy":"2022-02-16T07:34:48.019914Z","iopub.execute_input":"2022-02-16T07:34:48.020145Z","iopub.status.idle":"2022-02-16T07:34:48.034833Z","shell.execute_reply.started":"2022-02-16T07:34:48.020114Z","shell.execute_reply":"2022-02-16T07:34:48.03409Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2022-02-16T07:34:48.03626Z","iopub.execute_input":"2022-02-16T07:34:48.036577Z","iopub.status.idle":"2022-02-16T07:34:48.360099Z","shell.execute_reply.started":"2022-02-16T07:34:48.036497Z","shell.execute_reply":"2022-02-16T07:34:48.358928Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2022-02-16T07:34:48.361798Z","iopub.execute_input":"2022-02-16T07:34:48.36214Z","iopub.status.idle":"2022-02-16T07:34:48.372805Z","shell.execute_reply.started":"2022-02-16T07:34:48.362071Z","shell.execute_reply":"2022-02-16T07:34:48.371812Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2022-02-16T07:34:48.374081Z","iopub.execute_input":"2022-02-16T07:34:48.374876Z","iopub.status.idle":"2022-02-16T07:34:48.384667Z","shell.execute_reply.started":"2022-02-16T07:34:48.374839Z","shell.execute_reply":"2022-02-16T07:34:48.383903Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# %%time\n# ##%dirsrmal Training\n# scaler = torch.cuda.amp.GradScaler(enabled=True)\n# for 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":{"execution":{"iopub.status.busy":"2022-02-16T07:34:48.387639Z","iopub.execute_input":"2022-02-16T07:34:48.387845Z","iopub.status.idle":"2022-02-16T07:34:48.393364Z","shell.execute_reply.started":"2022-02-16T07:34:48.387822Z","shell.execute_reply":"2022-02-16T07:34:48.392508Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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\n# testset = GetData(X_Test, None, Transform)\n# testloader = DataLoader(testset, batch_size=1, shuffle=False)\n\n# s_ls = []\n\n# with torch.no_grad():\n#     model.eval()\n#     for image, fname in testloader: \n#         image = image.to(device)\n        \n#         logits = model(image)        \n#         ps = torch.exp(logits)        \n#         _, top_class = ps.topk(1, dim=1)\n        \n#         for pred in top_class:\n#             s_ls.append([fname[0].split('/')[-1][:-4], pred.item()])\n            \n# sub = pd.DataFrame.from_records(s_ls, columns=['Id', 'Predicted'])\n# sub.head()\n# sub.to_csv(\"submission.csv\", index=False)","metadata":{"execution":{"iopub.status.busy":"2022-02-16T07:34:48.394927Z","iopub.execute_input":"2022-02-16T07:34:48.3952Z","iopub.status.idle":"2022-02-16T07:34:48.404541Z","shell.execute_reply.started":"2022-02-16T07:34:48.395165Z","shell.execute_reply":"2022-02-16T07:34:48.403737Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Upvote!","metadata":{}}]}