{"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":"**Author:** Salo Elia and Nadav Shaoulian  \n**Date**: 7/6/2021 - 1/8/2021 ","metadata":{"id":"qPrdDHlL6Roe"}},{"cell_type":"markdown","source":"### **Overview**\nApples are one of the most important temperate fruit crops in the world. Foliar (leaf) diseases pose a major threat to the overall productivity and quality of apple orchards. The current process for disease diagnosis in apple orchards is based on manual scouting by humans, which is time-consuming and expensive.\n\nAlthough computer vision-based models have shown promise for plant disease identification, there are some limitations that need to be addressed. Large variations in visual symptoms of a single disease across different apple cultivars, or new varieties that originated under cultivation, are major challenges for computer vision-based disease identification. These variations arise from differences in natural and image capturing environments, for example, leaf color and leaf morphology, the age of infected tissues, non-uniform image background, and different light illumination during imaging etc.  ","metadata":{"id":"42NLhOvi2dIo"}},{"cell_type":"markdown","source":"### **Objectives** \nOn this notebook we will try to develop machine learning-based models to accurately classify a given leaf image from the test dataset to a particular disease category, and to identify an individual disease from multiple disease symptoms on a single leaf image.    \n\nWe will be using the tools that we learned from the 'Introduction to Computer Vision' Course we did in Afeka College.","metadata":{"id":"bdxcOmyA2TuL"}},{"cell_type":"markdown","source":"### **Plan and Goals** \n*   Data Analysis\n*   Data pre processing\n*   Using Different Augmentations\n*   Using Different Optimizers\n*   Testing Scores with Different Pre-trained Neural Networks\n*   Finding the ideal Hyper-parameters on each Neural Network tested\n*   Meassure results with Different Classification Metrics \n \n\n\n\nLet`s Start!\n\n\n\n\n\n\n\n\n\n","metadata":{"id":"uET_Vn3Y7lRY"}},{"cell_type":"markdown","source":"The dataset is not the original competition 1000X1000 sized dataset. It is a resized dataset , included multiple resized version of the dataset. There are four different sizes of the dataset: 256, 384, 512, 640.  \nFirst, we will start to build and train models using the 256 sized photos and afterwards we will consider to move to the larger ones.","metadata":{"id":"lCbGthZkmAeK"}},{"cell_type":"markdown","source":"# Data Analysis","metadata":{"id":"ZrsS39uD-8aV"}},{"cell_type":"markdown","source":"Let`s start analyzing our data using the Pandas library.","metadata":{"id":"oalE2OksXwPt"}},{"cell_type":"code","source":"import pandas as pd","metadata":{"id":"KR9AgkUpOVEs","execution":{"iopub.status.busy":"2021-07-26T07:56:31.734580Z","iopub.execute_input":"2021-07-26T07:56:31.734947Z","iopub.status.idle":"2021-07-26T07:56:31.739203Z","shell.execute_reply.started":"2021-07-26T07:56:31.734911Z","shell.execute_reply":"2021-07-26T07:56:31.737913Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Train data CSV Reading:","metadata":{"id":"dZOgeIfga09x"}},{"cell_type":"code","source":"train_df = pd.read_csv(\"../input/plant-pathology-2021-fgvc8/train.csv\")\ntrain_df","metadata":{"id":"xMh5g_fPUvtx","outputId":"d7889944-59a0-4157-d41b-e82dad3ec4d6","execution":{"iopub.status.busy":"2021-07-26T07:56:31.808722Z","iopub.execute_input":"2021-07-26T07:56:31.809065Z","iopub.status.idle":"2021-07-26T07:56:31.839621Z","shell.execute_reply.started":"2021-07-26T07:56:31.809036Z","shell.execute_reply":"2021-07-26T07:56:31.838667Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Null and Missing values check:","metadata":{"id":"GJs7qCDo0tea"}},{"cell_type":"code","source":"train_df.info()","metadata":{"id":"qO5A8TSq0nh3","outputId":"54681125-a373-4fba-b212-4a4247841dd1","execution":{"iopub.status.busy":"2021-07-26T07:56:31.906845Z","iopub.execute_input":"2021-07-26T07:56:31.907101Z","iopub.status.idle":"2021-07-26T07:56:31.921210Z","shell.execute_reply.started":"2021-07-26T07:56:31.907076Z","shell.execute_reply":"2021-07-26T07:56:31.920141Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"There are no label missing values in the dataset.","metadata":{"id":"e-TxjS6W04-j"}},{"cell_type":"markdown","source":"### Unique Label values (number of catagories):","metadata":{"id":"jZVG0kkZ1nEU"}},{"cell_type":"code","source":"train_df['labels'].value_counts()","metadata":{"id":"l0v_08eL1SVO","outputId":"56f3a83e-3f12-40ee-9256-5c9924047b5b","execution":{"iopub.status.busy":"2021-07-26T07:56:31.973028Z","iopub.execute_input":"2021-07-26T07:56:31.973344Z","iopub.status.idle":"2021-07-26T07:56:31.983737Z","shell.execute_reply.started":"2021-07-26T07:56:31.973315Z","shell.execute_reply":"2021-07-26T07:56:31.982875Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We have 6 label catagories in our dataset. ","metadata":{"id":"Hh1dwOdO74Io"}},{"cell_type":"markdown","source":"### Data histogram and Distribution","metadata":{"id":"i72Hgjht7_Uy"}},{"cell_type":"code","source":"import os\nimport cv2\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport plotly.graph_objects as go","metadata":{"id":"uI9pUUjL7StD","execution":{"iopub.status.busy":"2021-07-26T07:56:32.037882Z","iopub.execute_input":"2021-07-26T07:56:32.038157Z","iopub.status.idle":"2021-07-26T07:56:32.042245Z","shell.execute_reply.started":"2021-07-26T07:56:32.038131Z","shell.execute_reply":"2021-07-26T07:56:32.041152Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(15,12))\nlabels_hist = sns.barplot(train_df.labels.value_counts().index,train_df.labels.value_counts())\nfor item in labels_hist.get_xticklabels():\n    item.set_rotation(45)","metadata":{"id":"OaaYS5f77WMu","outputId":"330b0193-fc2d-46d7-d6c3-b86dadf8fba8","execution":{"iopub.status.busy":"2021-07-26T07:56:32.133791Z","iopub.execute_input":"2021-07-26T07:56:32.134104Z","iopub.status.idle":"2021-07-26T07:56:32.377734Z","shell.execute_reply.started":"2021-07-26T07:56:32.134074Z","shell.execute_reply":"2021-07-26T07:56:32.376736Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = go.Figure(data=[go.Pie(labels=train_df['labels'].value_counts().index,values=train_df['labels'].value_counts().values)])\nfig.update_layout(title='Label distribution')\nfig.show()","metadata":{"id":"4skpU0z9-BkD","outputId":"bec4ff16-41b2-4b45-af94-f8447c2f967f","execution":{"iopub.status.busy":"2021-07-26T07:56:32.379361Z","iopub.execute_input":"2021-07-26T07:56:32.379728Z","iopub.status.idle":"2021-07-26T07:56:32.403782Z","shell.execute_reply.started":"2021-07-26T07:56:32.379691Z","shell.execute_reply":"2021-07-26T07:56:32.402849Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Plant Categories Visualisation","metadata":{"id":"CoJAmM2dCvEt"}},{"cell_type":"code","source":"train_image_path = \"../input/resized-plant2021/img_sz_256\"","metadata":{"id":"oQ22TWhpPwgZ","execution":{"iopub.status.busy":"2021-07-26T07:56:32.405569Z","iopub.execute_input":"2021-07-26T07:56:32.405929Z","iopub.status.idle":"2021-07-26T07:56:32.410206Z","shell.execute_reply.started":"2021-07-26T07:56:32.405894Z","shell.execute_reply":"2021-07-26T07:56:32.409226Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Image Display Method","metadata":{"id":"Kv2BXrpkq1yT"}},{"cell_type":"code","source":"def display_images(train_path,labels,rows,cols):\n  fig = plt.figure(figsize=(20, 40))\n  idx = 1\n\n  for i in range(rows):\n    df = list(train_df.loc[train_df['labels'] == labels[i]]['image'])\n    for j in range(cols):\n      img_path = df[j]\n      img = cv2.imread(os.path.join(train_path,img_path))\n      image = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n      plt.subplot(rows,cols,idx)\n      plt.imshow(image)\n      plt.title(\"Class:\" + str(labels[i]) + \",Image:\"+ str(j+1))\n      idx += 1\n","metadata":{"id":"tLG5at8EDspm","execution":{"iopub.status.busy":"2021-07-26T07:56:32.412168Z","iopub.execute_input":"2021-07-26T07:56:32.412526Z","iopub.status.idle":"2021-07-26T07:56:32.420934Z","shell.execute_reply.started":"2021-07-26T07:56:32.412490Z","shell.execute_reply":"2021-07-26T07:56:32.419954Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels_arr = train_df['labels'].unique()\ndisplay_images(train_image_path,labels_arr,12,5)","metadata":{"id":"0AYsIp5RvcDF","outputId":"bf47f96d-e076-490d-e73c-07c5114ba475","execution":{"iopub.status.busy":"2021-07-26T07:56:32.422176Z","iopub.execute_input":"2021-07-26T07:56:32.422699Z","iopub.status.idle":"2021-07-26T07:56:39.793108Z","shell.execute_reply.started":"2021-07-26T07:56:32.422663Z","shell.execute_reply":"2021-07-26T07:56:39.789761Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Conclusions from the Data Analysis\nWe can see that some of the leaves may have couple of diseases. It means that the models output will be a vector that contains 1s and 0s , depending on the leaf diseases respectively. Therefore , we will need to encode the data frame in accordance.  ","metadata":{"id":"A181PddeH0NU"}},{"cell_type":"markdown","source":"# Data Pre-Processing","metadata":{"id":"FGyiagYH_zme"}},{"cell_type":"markdown","source":"The Data Pre-process includes:\n\n*   The Plant Dataset Class\n*   Data Train and Validation Split\n*   Focal Loss Class\n*   Train and Validation methods\n*   Model Save/Load methods\n*   Plot Graphs Method\n*   Data frame Encoding\n*   Test and Submission methods\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{"id":"edXlBeuwmhvW"}},{"cell_type":"markdown","source":"### Imports and Installations","metadata":{"id":"CKhb2IxqsFOU"}},{"cell_type":"code","source":"from torch.utils.data import Dataset, DataLoader\nfrom sklearn.model_selection import train_test_split","metadata":{"id":"A1l9vsT0Vesx","execution":{"iopub.status.busy":"2021-07-26T07:56:39.794520Z","iopub.execute_input":"2021-07-26T07:56:39.794865Z","iopub.status.idle":"2021-07-26T07:56:39.799004Z","shell.execute_reply.started":"2021-07-26T07:56:39.794830Z","shell.execute_reply":"2021-07-26T07:56:39.798122Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\n#import torch_optimizer as optimizer\nimport torch.optim as optim","metadata":{"id":"UAmzR9nyimZr","execution":{"iopub.status.busy":"2021-07-26T07:56:39.800407Z","iopub.execute_input":"2021-07-26T07:56:39.801000Z","iopub.status.idle":"2021-07-26T07:56:39.809100Z","shell.execute_reply.started":"2021-07-26T07:56:39.800965Z","shell.execute_reply":"2021-07-26T07:56:39.807887Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Folder path setting","metadata":{"id":"EcyTUifCsNdw"}},{"cell_type":"code","source":"folder_path_256 = \"../input/resized-plant2021/img_sz_256\"\ndata_paths_256 = os.listdir(folder_path_256)","metadata":{"id":"u6vgMUU1X6NA","execution":{"iopub.status.busy":"2021-07-26T07:56:39.812612Z","iopub.execute_input":"2021-07-26T07:56:39.812933Z","iopub.status.idle":"2021-07-26T07:56:39.830394Z","shell.execute_reply.started":"2021-07-26T07:56:39.812902Z","shell.execute_reply":"2021-07-26T07:56:39.829501Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Data Frame Encoding\n","metadata":{"id":"x_vPHrbBY9N_"}},{"cell_type":"code","source":"train_df_cp = train_df.copy()","metadata":{"id":"mOljxHJpyfM2","execution":{"iopub.status.busy":"2021-07-26T07:56:39.832292Z","iopub.execute_input":"2021-07-26T07:56:39.832617Z","iopub.status.idle":"2021-07-26T07:56:39.836861Z","shell.execute_reply.started":"2021-07-26T07:56:39.832573Z","shell.execute_reply":"2021-07-26T07:56:39.835962Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df_cp['label_list'] = train_df_cp['labels'].str.split(' ')","metadata":{"execution":{"iopub.status.busy":"2021-07-26T07:56:39.838261Z","iopub.execute_input":"2021-07-26T07:56:39.838872Z","iopub.status.idle":"2021-07-26T07:56:40.121987Z","shell.execute_reply.started":"2021-07-26T07:56:39.838838Z","shell.execute_reply":"2021-07-26T07:56:40.121151Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def lbl_lgc(col,lbl_list):\n    if col in lbl_list:\n        res = 1 \n    else:\n        res = 0\n    return res","metadata":{"execution":{"iopub.status.busy":"2021-07-26T07:56:40.123945Z","iopub.execute_input":"2021-07-26T07:56:40.124205Z","iopub.status.idle":"2021-07-26T07:56:40.131079Z","shell.execute_reply.started":"2021-07-26T07:56:40.124179Z","shell.execute_reply":"2021-07-26T07:56:40.130260Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"lbls = ['healthy','complex','rust','frog_eye_leaf_spot','powdery_mildew','scab']\nfor x in lbls:\n    train_df_cp[x]=0\n\n\nfor x in lbls:\n    train_df_cp[x] = np.vectorize(lbl_lgc)(x,train_df_cp['label_list'])","metadata":{"execution":{"iopub.status.busy":"2021-07-26T07:56:40.132385Z","iopub.execute_input":"2021-07-26T07:56:40.132731Z","iopub.status.idle":"2021-07-26T07:56:40.170248Z","shell.execute_reply.started":"2021-07-26T07:56:40.132702Z","shell.execute_reply":"2021-07-26T07:56:40.169565Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df_cp.head()","metadata":{"execution":{"iopub.status.busy":"2021-07-26T07:56:40.171299Z","iopub.execute_input":"2021-07-26T07:56:40.171641Z","iopub.status.idle":"2021-07-26T07:56:40.184793Z","shell.execute_reply.started":"2021-07-26T07:56:40.171600Z","shell.execute_reply":"2021-07-26T07:56:40.183768Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### The Train-Validation split","metadata":{"id":"ESOaADGboxxK"}},{"cell_type":"code","source":"train_path , val_path = train_test_split(data_paths_256, test_size =0.2 , random_state= 2021)","metadata":{"id":"5Dj0hyXbSi3q","execution":{"iopub.status.busy":"2021-07-26T07:56:40.186202Z","iopub.execute_input":"2021-07-26T07:56:40.186584Z","iopub.status.idle":"2021-07-26T07:56:40.199688Z","shell.execute_reply.started":"2021-07-26T07:56:40.186549Z","shell.execute_reply":"2021-07-26T07:56:40.198742Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Note:** The ideal train-validation split is by using Cross Validation methods like K-Fold for example , but it may take us some time to use them. For now, we will split the Data into 80% Train and 20% Validation. Later on, related the time left, we will consider in using some split Cross validation methods like the K-Fold.","metadata":{}},{"cell_type":"markdown","source":"### The Plant Dataset Class","metadata":{"id":"0KU_ZYs1pEge"}},{"cell_type":"code","source":"class Plant_Dataset(Dataset):\n  def __init__(self,folder_path,data_paths,data_df=train_df_cp,size=224,transforms=None, train=True):\n    self.folder_path = folder_path\n    self.data_paths = data_paths\n    self.data_df = data_df\n    self.transforms = transforms\n    self.train = train\n    self.size = size\n\n  def __getitem__(self, idx):\n    img_path = os.path.join(self.folder_path,self.data_paths[idx])\n    image = cv2.imread(img_path)\n    image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)\n    image = cv2.resize(image, (self.size, self.size), interpolation=cv2.INTER_AREA)\n    image = np.asarray(image)\n\n    if self.train: #for train or validation data\n     #label = self.data_df.loc[self.data_df['image']==self.data_paths[idx]].values[0][1]\n      j = 0\n      vector = [0]*6\n      values = self.data_df.loc[self.data_df['image']==self.data_paths[idx]].values\n      for i in range(3,9):\n        num = values[0][i]\n        vector[j] = num\n        j = j+1\n     \n      vector=np.asarray(vector)\n      \n    \n    if self.transforms:\n       image = self.transforms(image=image)['image']\n\n    if self.train:\n     return image,vector #train or validation data\n    else:\n      return image,self.data_paths[idx] #test data\n\n\n  def __len__(self):\n    return len(self.data_paths)  \n\n","metadata":{"id":"e-nODUR9_y7Z","execution":{"iopub.status.busy":"2021-07-26T07:56:40.200684Z","iopub.execute_input":"2021-07-26T07:56:40.200922Z","iopub.status.idle":"2021-07-26T07:56:40.216810Z","shell.execute_reply.started":"2021-07-26T07:56:40.200893Z","shell.execute_reply":"2021-07-26T07:56:40.215138Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Focal Loss Class","metadata":{"id":"7tc4BNfgVswd"}},{"cell_type":"code","source":"class FocalLoss(nn.Module):\n    def __init__(self, alpha=0.2, gamma=2, logist=False, reduce='mean'):\n        super(FocalLoss, self).__init__()\n        self.alpha = alpha # the scalar factor between 0 and 1 \n        self.gamma = gamma # focusing parameter(always positive) that reduces the relative loss for well-classified examples and puts more focus on hard misclassified examples\n        self.cross_entropy_loss = nn.CrossEntropyLoss()\n        #self.logist = logist # log probabilities \n        self.reduce = reduce # Specifies the reduction to apply to the output - none/mean/sum. ‘none’: no reduction will be applied, ‘mean’: the sum of the output will be divided by the number of elements in the output, ‘sum’: the output will be summed.\n\n    def forward(self, inputs, targets):\n        BCE_loss = self.cross_entropy_loss(inputs, targets)\n        pt = torch.exp(-BCE_loss)\n        F_loss = self.alpha * (1-pt)**self.gamma * BCE_loss\n\n        if self.reduce:\n            return torch.mean(F_loss)\n        else:\n            return F_loss","metadata":{"id":"VJgFO64QfL5C","execution":{"iopub.status.busy":"2021-07-26T07:56:40.218844Z","iopub.execute_input":"2021-07-26T07:56:40.219396Z","iopub.status.idle":"2021-07-26T07:56:40.236547Z","shell.execute_reply.started":"2021-07-26T07:56:40.219323Z","shell.execute_reply":"2021-07-26T07:56:40.235688Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Train and Validation Methods","metadata":{"id":"QTLNO3Yho1VB"}},{"cell_type":"code","source":"from tqdm.auto import tqdm","metadata":{"id":"qolcSiwri9go","execution":{"iopub.status.busy":"2021-07-26T07:56:40.238054Z","iopub.execute_input":"2021-07-26T07:56:40.238638Z","iopub.status.idle":"2021-07-26T07:56:40.250189Z","shell.execute_reply.started":"2021-07-26T07:56:40.238586Z","shell.execute_reply":"2021-07-26T07:56:40.249264Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Train Validation General Method","metadata":{"id":"py0GZfE28uqz"}},{"cell_type":"code","source":"def train_val(model,loader_train,loader_val,opt,criterion,epoch):\n  train_loss = []\n  train_acc = []\n  val_loss = []\n  val_acc = []\n  for e in range(epoch):\n    loss_t, acc_t = train(e,model,loader_train,opt,criterion)\n    train_loss.append(loss_t)\n    train_acc.append(acc_t)\n    loss_v , acc_v = validation(e, model, loader_val)\n    val_loss.append(loss_v)\n    val_acc.append(acc_v)\n     \n    gc.collect()\n    \n    torch.cuda.empty_cache()\n\n  return model,train_loss,train_acc,val_loss,val_acc","metadata":{"id":"vwHV3qNrjK8S","execution":{"iopub.status.busy":"2021-07-26T07:56:40.251662Z","iopub.execute_input":"2021-07-26T07:56:40.252042Z","iopub.status.idle":"2021-07-26T07:56:40.277711Z","shell.execute_reply.started":"2021-07-26T07:56:40.252005Z","shell.execute_reply":"2021-07-26T07:56:40.268828Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Train Method","metadata":{"id":"dhThNZ4t82-Z"}},{"cell_type":"code","source":"def train(e,model,loader,opt,criterion):\n  model.train()\n  treshold = 0.5\n  acc_loss = 0 \n  correct = 0\n  target_sum = 0\n # tqdm_loader = tqdm(loader)\n  for i, (img, target) in enumerate(loader):\n    \n    img = img.float()\n   # img = img.permute(0,3,1,2).float()\n    target = target.float()\n    img = img.cuda()\n    target = target.cuda()\n    \n    opt.zero_grad()\n    output = torch.sigmoid(model(img)).float()\n    loss = criterion(output, target)\n    loss.backward()\n    opt.step()\n    \n    acc_loss += loss.item()\n    avg_loss = acc_loss/(i+1)\n    \n    output = torch.where(output > treshold, 1,0)\n    \n    #correct += output.eq(target.view_as(output)).sum().item()/(6*len(target))\n    \n    res = output==target\n    \n    for tensor in res:\n        if False in tensor:\n            continue\n        else:\n            correct += 1\n    \n    target_sum += len(target)\n    avg_acc = correct/((target_sum))\n    \n    #tqdm_loader.set_description(\"Epoch {}, train_loss={:4} , acc={:4}\".format(e,round(avg_loss,4), round(avg_acc ,4)))\n    \n    del img\n    del target\n    del output\n    del loss\n    del res\n    \n    gc.collect() \n    torch.cuda.empty_cache()\n  \n  del acc_loss\n  \n  del target_sum\n  del correct\n\n    \n  return avg_loss, avg_acc\n\n\n","metadata":{"id":"s-GBZtNJpRC7","execution":{"iopub.status.busy":"2021-07-26T07:56:40.281557Z","iopub.execute_input":"2021-07-26T07:56:40.281916Z","iopub.status.idle":"2021-07-26T07:56:40.301181Z","shell.execute_reply.started":"2021-07-26T07:56:40.281879Z","shell.execute_reply":"2021-07-26T07:56:40.300406Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Validation Method","metadata":{"id":"_DdtW7X-HGFE"}},{"cell_type":"code","source":"def validation(e, model, loader):\n  model.eval()\n  #tqdm_loader = tqdm(loader_val)\n  treshold = 0.5\n  acc_loss = 0\n  correct =0\n  target_sum=0\n  for i, (img,target) in enumerate(loader):\n    img = img.float()\n #   img = img.permute(0,3,1,2).float()\n    target = target.float()\n\n    img = img.cuda()\n    target = target.cuda()\n\n    with torch.no_grad():\n      output = torch.sigmoid(model(img)).float()\n      loss = criterion(output, target)\n        \n    acc_loss += loss.item()\n    avg_loss = acc_loss/(i+1)\n    \n    output = torch.where(output > treshold, 1,0)\n    \n   # correct += output.eq(target.view_as(output)).sum().item()/(6*len(target))\n    res = output==target\n    \n    for tensor in res:\n        if False in tensor:\n            continue\n        else:\n            correct += 1\n    \n    \n    target_sum += len(target)\n    avg_acc = correct/((target_sum))\n    \n    \n   # tqdm_loader.set_description(\"Epoch {}, val_loss={:4} , val_acc={:4}\".format(e,round(avg_loss,4), round(avg_acc ,4)))\n    \n    del img\n    del target\n    del output\n    del res\n    \n    \n    gc.collect() \n    torch.cuda.empty_cache()\n  \n\n  del target_sum\n  del acc_loss\n  del correct\n\n    \n  return avg_loss, avg_acc\n","metadata":{"id":"rXJH-rCQ8VDC","execution":{"iopub.status.busy":"2021-07-26T07:56:40.306169Z","iopub.execute_input":"2021-07-26T07:56:40.309739Z","iopub.status.idle":"2021-07-26T07:56:40.322608Z","shell.execute_reply.started":"2021-07-26T07:56:40.309693Z","shell.execute_reply":"2021-07-26T07:56:40.321474Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Test Mehtod","metadata":{}},{"cell_type":"code","source":"def model_test(model,test_loader):\n model.eval()\n images = []\n predictions = []   \n treshold = 0.5\n for i ,(img,img_name) in enumerate(test_loader):\n    images.append(img_name)\n    img = img.float()\n    img = img.cuda()\n    \n    with torch.no_grad():\n      output = torch.sigmoid(model(img)).float()\n    \n    output = torch.where(output > treshold, 1,0)\n    predictions.append(output)\n    \n    del img\n    del output\n    \n    gc.collect() \n    torch.cuda.empty_cache()\n    \n    \n return images,predictions","metadata":{"execution":{"iopub.status.busy":"2021-07-26T07:56:40.326913Z","iopub.execute_input":"2021-07-26T07:56:40.327252Z","iopub.status.idle":"2021-07-26T07:56:40.339280Z","shell.execute_reply.started":"2021-07-26T07:56:40.327217Z","shell.execute_reply":"2021-07-26T07:56:40.337964Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Submission method","metadata":{}},{"cell_type":"code","source":"def submission(images,predictions):\n  str_preds = []\n  img_names = []\n  j=0  \n  for vec in predictions:\n    labels = []\n    for i in range(len(vec[0])):\n      if vec[0][i]==1:\n       labels.append(lbls[i])\n         \n    l = ' '.join(labels)\n    str_preds.append(l) \n    img_names.append(images[j][0])\n    j += 1\n    \n  output = pd.DataFrame({'image': img_names, 'labels': str_preds})\n  output.to_csv('submission.csv',index=False)             \n            \n    ","metadata":{"execution":{"iopub.status.busy":"2021-07-26T07:56:40.343349Z","iopub.execute_input":"2021-07-26T07:56:40.343824Z","iopub.status.idle":"2021-07-26T07:56:40.355252Z","shell.execute_reply.started":"2021-07-26T07:56:40.343787Z","shell.execute_reply":"2021-07-26T07:56:40.354093Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Model Save method","metadata":{"id":"ckyJms3RZkZ8"}},{"cell_type":"code","source":"def save_model(model,optimizer,epoch,train_loss,val_loss,train_acc,val_acc,path):\n  torch.save({\n            'epoch': epoch,\n            'model_state_dict': model.state_dict(),\n            'optimizer_state_dict': optimizer.state_dict(),\n            'train_loss': train_loss,\n            'val_loss': val_loss,\n            'train_acc': train_acc,\n            'val_acc': val_acc\n            }, path)","metadata":{"id":"pUK40nWTZpha","execution":{"iopub.status.busy":"2021-07-26T07:56:40.365317Z","iopub.execute_input":"2021-07-26T07:56:40.365792Z","iopub.status.idle":"2021-07-26T07:56:40.375416Z","shell.execute_reply.started":"2021-07-26T07:56:40.365755Z","shell.execute_reply":"2021-07-26T07:56:40.374471Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Model Load method","metadata":{"id":"HC9zQXEvLwK0"}},{"cell_type":"code","source":"def load_model(path,model,optimizer):\n  checkpoint = torch.load(path)\n  model.load_state_dict(checkpoint['model_state_dict'])\n  optimizer.load_state_dict(checkpoint['optimizer_state_dict'])\n  epoch = checkpoint['epoch']\n  train_loss = checkpoint['train_loss']\n  val_loss = checkpoint['val_loss']\n  train_acc = checkpoint['train_acc']\n  val_acc = checkpoint['val_acc']\n  return train_loss,val_loss,train_acc,val_acc,epoch","metadata":{"id":"yeVWnGuTLvf_","execution":{"iopub.status.busy":"2021-07-26T07:56:40.380544Z","iopub.execute_input":"2021-07-26T07:56:40.381282Z","iopub.status.idle":"2021-07-26T07:56:40.392142Z","shell.execute_reply.started":"2021-07-26T07:56:40.381238Z","shell.execute_reply":"2021-07-26T07:56:40.390451Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Plot Graphs Method","metadata":{"id":"5XHl94oE7OUo"}},{"cell_type":"code","source":"def plot_graphs(train_loss,val_loss,train_acc,val_acc,epcohs):\n  plt.figure(figsize=(30,10))\n\n  plt.subplot(1,2,1)\n  plt.title(\"Loss\")\n  plt.plot(list(range(0,epcohs)),train_loss, label='Train')\n  plt.plot(list(range(0,epcohs)), val_loss, label='Validation')\n  plt.xlabel('Epochs')\n  plt.ylabel('Rate')\n  plt.legend()\n    \n  plt.subplot(1,2,2)\n  plt.title(\"Accuracy\")\n  plt.plot(list(range(0,epcohs)),train_acc, label='Train')\n  plt.plot(list(range(0,epcohs)), val_acc, label='Validation')\n  plt.xlabel('Epochs')\n  plt.ylabel('Rate')\n  plt.legend()\n  ","metadata":{"id":"W3zuPntm7Rhn","execution":{"iopub.status.busy":"2021-07-26T07:56:40.394175Z","iopub.execute_input":"2021-07-26T07:56:40.394864Z","iopub.status.idle":"2021-07-26T07:56:40.407271Z","shell.execute_reply.started":"2021-07-26T07:56:40.394827Z","shell.execute_reply":"2021-07-26T07:56:40.406401Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Models and Tests","metadata":{"id":"fWzwCGt3Ta7T"}},{"cell_type":"markdown","source":"Due to the competition and submission rules, we decided to write a notebook for each model in order to reduce problems and time wasting.  \nThe first model will be relatively simple. The models development and complexity will be gradual and we will use more complex tools from submission to submission. ","metadata":{"id":"W8ng_dset14U"}},{"cell_type":"markdown","source":"### Imports","metadata":{}},{"cell_type":"code","source":"import torchvision.models as models\n#!pip install albumentations==0.4.6\n#!pip install -U git+https://github.com/albu/albumentations > /dev/null\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2\nfrom torchvision import transforms as T\nimport gc ","metadata":{"id":"ei-WRlNIdPwc","outputId":"decf1638-ed71-409c-d5d5-d670772a09da","execution":{"iopub.status.busy":"2021-07-26T07:56:40.409990Z","iopub.execute_input":"2021-07-26T07:56:40.410698Z","iopub.status.idle":"2021-07-26T07:56:40.417409Z","shell.execute_reply.started":"2021-07-26T07:56:40.410659Z","shell.execute_reply":"2021-07-26T07:56:40.416289Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gc.collect() \ntorch.cuda.empty_cache()","metadata":{"execution":{"iopub.status.busy":"2021-07-26T07:56:40.419152Z","iopub.execute_input":"2021-07-26T07:56:40.420002Z","iopub.status.idle":"2021-07-26T07:56:40.617761Z","shell.execute_reply.started":"2021-07-26T07:56:40.419814Z","shell.execute_reply":"2021-07-26T07:56:40.616750Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 1st Model","metadata":{"id":"yEQYukyMHu-H"}},{"cell_type":"markdown","source":"\n\n*   **Architecture**: Resnext50 (Not Pre-Trained)\n*   **Transforms**: Normalize\n*   **Batch Size**: 25\n*   **Epochs** : 20\n*   **Learning Rate**: 0.0001\n*   **Learning Rate Scheduler**: None\n\n\n\n\n\n\n\n\n","metadata":{"id":"jk0jm6vmt7ua"}},{"cell_type":"code","source":"BS = 25\nEPOCHS = 20\ntransforms = A.Compose([A.Normalize(),ToTensorV2()])","metadata":{"id":"0tNhxk-KZLBe","execution":{"iopub.status.busy":"2021-07-26T07:56:40.619301Z","iopub.execute_input":"2021-07-26T07:56:40.619893Z","iopub.status.idle":"2021-07-26T07:56:40.624664Z","shell.execute_reply.started":"2021-07-26T07:56:40.619855Z","shell.execute_reply":"2021-07-26T07:56:40.623789Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Train and Validation Data Loading using Dataloader","metadata":{"id":"oprp3iFUbbMs"}},{"cell_type":"code","source":"train_data = Plant_Dataset(folder_path_256,train_path,transforms=transforms,train=True)\nloader_train = DataLoader(train_data, batch_size=BS, shuffle=True,num_workers=4)\nval_data = Plant_Dataset(folder_path_256,val_path,transforms=transforms,train=True) \nloader_val = DataLoader(val_data,batch_size=BS, shuffle=False,num_workers=4)","metadata":{"id":"VXU29BP2ZH70","outputId":"15aa59cc-9e53-4e7e-8c00-ceed8fc9a694","execution":{"iopub.status.busy":"2021-07-26T07:56:40.626448Z","iopub.execute_input":"2021-07-26T07:56:40.627382Z","iopub.status.idle":"2021-07-26T07:56:40.634108Z","shell.execute_reply.started":"2021-07-26T07:56:40.627340Z","shell.execute_reply":"2021-07-26T07:56:40.633077Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = models.resnext50_32x4d(pretrained=False)\n\nin_features = model.fc.in_features\nmodel.fc = torch.nn.Linear(in_features,6)","metadata":{"id":"K8a3cn3rbG_7","execution":{"iopub.status.busy":"2021-07-26T07:56:40.635948Z","iopub.execute_input":"2021-07-26T07:56:40.636601Z","iopub.status.idle":"2021-07-26T07:56:41.153752Z","shell.execute_reply.started":"2021-07-26T07:56:40.636551Z","shell.execute_reply":"2021-07-26T07:56:41.152834Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.cuda()\ncriterion = torch.nn.BCELoss()\ncriterion.cuda()\noptimi = optim.Adam(model.parameters(), lr=1e-4)","metadata":{"id":"SzIOWdeRfDpW","execution":{"iopub.status.busy":"2021-07-26T07:56:41.155068Z","iopub.execute_input":"2021-07-26T07:56:41.155461Z","iopub.status.idle":"2021-07-26T07:56:41.201605Z","shell.execute_reply.started":"2021-07-26T07:56:41.155426Z","shell.execute_reply":"2021-07-26T07:56:41.200721Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Model Training and Validation","metadata":{"id":"y6-k1qfIbNyF"}},{"cell_type":"code","source":"model,train_loss,train_acc,val_loss,val_acc = train_val(model,loader_train,loader_val,optimi,criterion,EPOCHS)","metadata":{"id":"4wFdsGDfgu_J","execution":{"iopub.status.busy":"2021-07-26T07:56:41.202822Z","iopub.execute_input":"2021-07-26T07:56:41.203246Z","iopub.status.idle":"2021-07-26T10:25:35.341800Z","shell.execute_reply.started":"2021-07-26T07:56:41.203131Z","shell.execute_reply":"2021-07-26T10:25:35.340875Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Train/Validation Loss and Accuracy Graphs","metadata":{"id":"-AgbMo8IOIkV"}},{"cell_type":"code","source":"plot_graphs(train_loss,val_loss,train_acc,val_acc,EPOCHS)","metadata":{"execution":{"iopub.status.busy":"2021-07-26T10:25:35.343214Z","iopub.execute_input":"2021-07-26T10:25:35.343558Z","iopub.status.idle":"2021-07-26T10:25:35.704787Z","shell.execute_reply.started":"2021-07-26T10:25:35.343522Z","shell.execute_reply":"2021-07-26T10:25:35.703795Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Model Test and Submission","metadata":{"id":"A7AsR8_bOUsf"}},{"cell_type":"code","source":"test_path = \"../input/plant-pathology-2021-fgvc8/test_images\"\ntest_data_paths = os.listdir(test_path)","metadata":{"execution":{"iopub.status.busy":"2021-07-26T10:25:35.706085Z","iopub.execute_input":"2021-07-26T10:25:35.706442Z","iopub.status.idle":"2021-07-26T10:25:35.718999Z","shell.execute_reply.started":"2021-07-26T10:25:35.706404Z","shell.execute_reply":"2021-07-26T10:25:35.718028Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gc.collect() \ntorch.cuda.empty_cache()","metadata":{"execution":{"iopub.status.busy":"2021-07-26T10:25:35.720296Z","iopub.execute_input":"2021-07-26T10:25:35.720681Z","iopub.status.idle":"2021-07-26T10:25:35.854445Z","shell.execute_reply.started":"2021-07-26T10:25:35.720634Z","shell.execute_reply":"2021-07-26T10:25:35.853406Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_data = Plant_Dataset(test_path,test_data_paths,transforms=transforms,train=False)\ntest_loader = DataLoader(test_data, batch_size=1, shuffle=False,num_workers=0)","metadata":{"execution":{"iopub.status.busy":"2021-07-26T10:25:35.855887Z","iopub.execute_input":"2021-07-26T10:25:35.856254Z","iopub.status.idle":"2021-07-26T10:25:35.864237Z","shell.execute_reply.started":"2021-07-26T10:25:35.856217Z","shell.execute_reply":"2021-07-26T10:25:35.863401Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"images,predictions = model_test(model,test_loader)\nsubmission(images,predictions)","metadata":{"execution":{"iopub.status.busy":"2021-07-26T11:18:42.078414Z","iopub.execute_input":"2021-07-26T11:18:42.078796Z","iopub.status.idle":"2021-07-26T11:18:42.144747Z","shell.execute_reply.started":"2021-07-26T11:18:42.078716Z","shell.execute_reply":"2021-07-26T11:18:42.143105Z"},"trusted":true},"execution_count":null,"outputs":[]}]}