{"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":"code","source":"import os\nimport pandas as pd\nimport numpy as np\nfrom torch.utils.data import Dataset,Subset\nfrom torchvision import transforms,models,datasets\nimport torch\nfrom PIL import Image\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom datetime import datetime\nimport matplotlib.pyplot as plt\nfrom torch.utils.data.dataloader import DataLoader\nfrom torch.utils.data import random_split,WeightedRandomSampler\nfrom torchvision.utils import make_grid\nfrom sklearn.metrics import confusion_matrix\nimport cv2\nimport plotly.express as px\nimport plotly.graph_objects as go\nimport plotly.figure_factory as ff\nfrom plotly.subplots import make_subplots\nfrom plotly.offline import init_notebook_mode, iplot\nimport seaborn as sns\nimport itertools\nimport tensorflow as tf\nimport tensorflow_hub as hub\nimport shutil\nfrom sklearn.model_selection import StratifiedShuffleSplit\n#from torchsummary import summary","metadata":{"execution":{"iopub.status.busy":"2022-06-22T20:36:52.270754Z","iopub.execute_input":"2022-06-22T20:36:52.271158Z","iopub.status.idle":"2022-06-22T20:37:03.246692Z","shell.execute_reply.started":"2022-06-22T20:36:52.271072Z","shell.execute_reply":"2022-06-22T20:37:03.245744Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"select_machine = int(input(\"1 : local machine\\n2 : colab\\n3 : kaggle\\n\"))","metadata":{"execution":{"iopub.status.busy":"2022-06-22T20:37:03.248630Z","iopub.execute_input":"2022-06-22T20:37:03.248916Z","iopub.status.idle":"2022-06-22T20:37:05.177099Z","shell.execute_reply.started":"2022-06-22T20:37:03.248890Z","shell.execute_reply":"2022-06-22T20:37:05.176094Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if select_machine == 1:\n    train_image_path = '../input/plant-pathology-fgvc8-resized-images/train_images/train_images'\n    test_image_path = '../input/plant-pathology-fgvc8-resized-images/test_images'\n    train_df_path = '../input/plant-pathology-fgvc8-resized-images/train.csv'\n    test_df_path = '../input/plant-pathology-fgvc8-resized-images/sample_submission.csv'\nif select_machine == 2:\n    train_image_path = '../input/plant-pathology-fgvc8-resized-images/train_images/train_images'\n    test_image_path = '../input/plant-pathology-fgvc8-resized-images/test_images'\n    train_df_path = '../input/plant-pathology-fgvc8-resized-images/train.csv'\n    test_df_path = '../input/plant-pathology-fgvc8-resized-images/sample_submission.csv'\nif select_machine == 3:\n    train_image_path = '../input/plant-pathology-fgvc8-resized-images/train_images/train_images'\n    test_image_path = '../input/plant-pathology-fgvc8-resized-images/test_images'\n    train_df_path = '../input/plant-pathology-fgvc8-resized-images/train.csv'\n    test_df_path = '../input/plant-pathology-fgvc8-resized-images/sample_submission.csv'","metadata":{"execution":{"iopub.status.busy":"2022-06-22T20:37:05.180206Z","iopub.execute_input":"2022-06-22T20:37:05.181084Z","iopub.status.idle":"2022-06-22T20:37:05.187657Z","shell.execute_reply.started":"2022-06-22T20:37:05.181045Z","shell.execute_reply":"2022-06-22T20:37:05.186619Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train = pd.read_csv(train_df_path)\nprint(df_train.head())\nprint('-----------------------')\nsource = df_train['labels'].value_counts()\nprint(source)\n\n\"\"\"\nforbid_label_list = ['frog_eye_leaf_spot complex','powdery_mildew complex','rust complex','rust frog_eye_leaf_spot','scab frog_eye_leaf_spot','cab frog_eye_leaf_spot complex','scab frog_eye_leaf_spot complex']\nfor i in forbid_label_list:    \n    df_train = df_train.loc[df_train['labels']!=i]\n\nprint(\"-----------------------\")\nprint(df_train.head())\nprint('-----------------------')\nsource = df_train['labels'].value_counts()\nprint(source)\n\"\"\"","metadata":{"execution":{"iopub.status.busy":"2022-06-22T20:37:05.191103Z","iopub.execute_input":"2022-06-22T20:37:05.191466Z","iopub.status.idle":"2022-06-22T20:37:05.247485Z","shell.execute_reply.started":"2022-06-22T20:37:05.191429Z","shell.execute_reply":"2022-06-22T20:37:05.246575Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(15,12))\nlabels = sns.barplot(df_train.labels.value_counts().index,df_train.labels.value_counts())\nfor item in labels.get_xticklabels():\n    item.set_rotation(45)","metadata":{"execution":{"iopub.status.busy":"2022-06-22T20:37:05.249072Z","iopub.execute_input":"2022-06-22T20:37:05.249414Z","iopub.status.idle":"2022-06-22T20:37:05.601562Z","shell.execute_reply.started":"2022-06-22T20:37:05.249372Z","shell.execute_reply":"2022-06-22T20:37:05.600542Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"code_dict = {'scab':0,'healthy':1,'frog_eye_leaf_spot':2,'rust':3,'complex':4,'powdery_mildew':5,'scab frog_eye_leaf_spot':6,'scab frog_eye_leaf_spot complex':7,'frog_eye_leaf_spot complex':8,'rust frog_eye_leaf_spot':9,'rust complex':10,'powdery_mildew complex':11}\nlabel_list = list(code_dict)\ndf_train['codes'] = df_train['labels'].map(code_dict)\nprint(df_train.head())\nprint('__________________________')\nprint(label_list)\nprint('__________________________')\nfor i in zip(list(code_dict.keys()),list(code_dict.values())):\n    print(str(i[1])+' ----> '+i[0])","metadata":{"execution":{"iopub.status.busy":"2022-06-22T20:37:05.604810Z","iopub.execute_input":"2022-06-22T20:37:05.605703Z","iopub.status.idle":"2022-06-22T20:37:05.619281Z","shell.execute_reply.started":"2022-06-22T20:37:05.605662Z","shell.execute_reply":"2022-06-22T20:37:05.618068Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = go.Figure(data=[go.Pie(labels=source.index,values=source.values)])\nfig.update_layout(title='Label distribution')\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-06-22T20:37:05.621075Z","iopub.execute_input":"2022-06-22T20:37:05.621373Z","iopub.status.idle":"2022-06-22T20:37:05.683090Z","shell.execute_reply.started":"2022-06-22T20:37:05.621343Z","shell.execute_reply":"2022-06-22T20:37:05.682068Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class PathologyPlantsDataset(Dataset):  #  <--- جنس پارامتر ورودی از نوع دیتاست برگرفته از کتابخانه دیتاست پایتورچ می باشد\n  \"\"\"\n  The Class will act as the container for our dataset. It will take your dataframe, the root path, and also the transform function for transforming the dataset.\n  \"\"\"\n  def __init__(self, data_frame, root_dir, transform=None):\n        self.data_frame = data_frame\n        self.root_dir = root_dir\n        self.transform = transform\n    \n  def __len__(self):\n        # Return the length of the dataset\n        return len(self.data_frame)\n    \n  def __getitem__(self, idx):\n        # Return the observation based on an index. Ex. dataset[0] will return the first element from the dataset, in this case the image and the label.\n        if torch.is_tensor(idx):\n            idx = idx.tolist()\n        \n        img_name = os.path.join(self.root_dir, self.data_frame.iloc[idx, 0])\n        image = Image.open(img_name)\n        label = int(self.data_frame.iloc[idx, 2])\n        \n        if self.transform:\n            image = self.transform(image)\n    \n        return (image, label)","metadata":{"execution":{"iopub.status.busy":"2022-06-22T20:37:05.684779Z","iopub.execute_input":"2022-06-22T20:37:05.685285Z","iopub.status.idle":"2022-06-22T20:37:05.696586Z","shell.execute_reply.started":"2022-06-22T20:37:05.685241Z","shell.execute_reply":"2022-06-22T20:37:05.695701Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"transform = transforms.Compose([transforms.RandomHorizontalFlip(),transforms.RandomVerticalFlip(),\n                                #transforms.ColorJitter(brightness=.2, hue=.1),\n                                #transforms.RandomAdjustSharpness(sharpness_factor=2),\n                                #transforms.RandomPerspective(distortion_scale=0.3,p=0.2),\n                                #transforms.RandomRotation(degrees=(0,180)),\n                                #transforms.RandomAffine(),\n                                #transforms.RandomResizedCrop(size=(224,224)),\n                                transforms.Resize(size=(299,299)),\n                                transforms.ToTensor(),\n                                #transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),\n                                ])\npathology_train = PathologyPlantsDataset(data_frame=df_train,root_dir=train_image_path,transform=transform)\nprint(pathology_train)","metadata":{"execution":{"iopub.status.busy":"2022-06-22T20:37:05.698232Z","iopub.execute_input":"2022-06-22T20:37:05.698500Z","iopub.status.idle":"2022-06-22T20:37:05.708149Z","shell.execute_reply.started":"2022-06-22T20:37:05.698476Z","shell.execute_reply":"2022-06-22T20:37:05.706994Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"temp_img, temp_label = pathology_train[3]\nplt.imshow(temp_img.numpy().transpose((1, 2, 0)))\nplt.title(label_list[temp_label])\n#plt.title(temp_lab)\n#plt.axis('off')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-06-22T20:37:05.712732Z","iopub.execute_input":"2022-06-22T20:37:05.713025Z","iopub.status.idle":"2022-06-22T20:37:05.951582Z","shell.execute_reply.started":"2022-06-22T20:37:05.712985Z","shell.execute_reply":"2022-06-22T20:37:05.950610Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch_size = 64   #  <------------------\nsplit_ratio = 0.8\ntrain_size = int(len(pathology_train)*split_ratio)\nvalidation_size = len(pathology_train) - train_size\n#sampler_weight = 1/source\n#sampler = WeightedRandomSampler(sampler_weight, train_size)\n\ntrain_dataset, valid_dataset = random_split(pathology_train, [train_size, validation_size] )\n#load the train and validation into batches.\n#train_dl = DataLoader(train_dataset, batch_size = batch_size, shuffle = True, sampler = sampler, pin_memory = True)  # , pin_memory = True num_workers = 1, shuffle = True\ntrain_dl = DataLoader(train_dataset, batch_size = batch_size, shuffle = True, pin_memory = True)  # , pin_memory = True num_workers = 1, shuffle = True\nval_dl = DataLoader(valid_dataset, batch_size = batch_size, shuffle = True, pin_memory = True)  # , pin_memory = True num_workers = 1, shuffle = True\n\nprint(f\"Length of Dataset : {len(pathology_train)}\")\nprint(f\"Length of Train Data : {len(train_dataset)}\")\nprint(f\"Length of Validation Data : {len(valid_dataset)}\")","metadata":{"execution":{"iopub.status.busy":"2022-06-22T20:37:05.952585Z","iopub.execute_input":"2022-06-22T20:37:05.952923Z","iopub.status.idle":"2022-06-22T20:37:05.965216Z","shell.execute_reply.started":"2022-06-22T20:37:05.952889Z","shell.execute_reply":"2022-06-22T20:37:05.963685Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def show_batch(dl):\n    \"\"\"Plot images grid of single batch\"\"\"\n    for images, labels in dl:\n        fig,ax = plt.subplots(figsize = (16,12))\n        ax.set_xticks([])\n        ax.set_yticks([])\n        ax.imshow(make_grid(images,nrow=16).permute(1,2,0))\n        break\n\n  \nshow_batch(train_dl)","metadata":{"execution":{"iopub.status.busy":"2022-06-22T20:37:05.966950Z","iopub.execute_input":"2022-06-22T20:37:05.967752Z","iopub.status.idle":"2022-06-22T20:37:15.079383Z","shell.execute_reply.started":"2022-06-22T20:37:05.967713Z","shell.execute_reply":"2022-06-22T20:37:15.078443Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"targets_size=12\nmodel = models.inception_v3(pretrained=True)\nfor param in model.parameters():\n            param.requires_grad = True\nprint(model)\nmodel.fc = nn.Linear(2048, targets_size) \nmodel.AuxLogits.fc = nn.Linear(768, targets_size)     #Auxilary layer: For Inception_v3\nprint(model.fc)","metadata":{"execution":{"iopub.status.busy":"2022-06-22T20:37:15.080963Z","iopub.execute_input":"2022-06-22T20:37:15.081575Z","iopub.status.idle":"2022-06-22T20:37:21.159336Z","shell.execute_reply.started":"2022-06-22T20:37:15.081532Z","shell.execute_reply":"2022-06-22T20:37:21.158287Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nprint(device)\ndevice = \"cuda\"\nmodel.to(device)","metadata":{"execution":{"iopub.status.busy":"2022-06-22T20:37:21.160820Z","iopub.execute_input":"2022-06-22T20:37:21.161165Z","iopub.status.idle":"2022-06-22T20:37:21.224158Z","shell.execute_reply.started":"2022-06-22T20:37:21.161129Z","shell.execute_reply":"2022-06-22T20:37:21.223220Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#criterion = nn.MultiLabelSoftMarginLoss()\ncriterion = nn.CrossEntropyLoss()\noptimizer = torch.optim.Adam(model.parameters(),lr=0.0005)","metadata":{"execution":{"iopub.status.busy":"2022-06-22T20:37:21.225558Z","iopub.execute_input":"2022-06-22T20:37:21.226396Z","iopub.status.idle":"2022-06-22T20:37:21.233732Z","shell.execute_reply.started":"2022-06-22T20:37:21.226349Z","shell.execute_reply":"2022-06-22T20:37:21.232768Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_losses = []\nvalidation_losses = []","metadata":{"execution":{"iopub.status.busy":"2022-06-22T20:37:21.235220Z","iopub.execute_input":"2022-06-22T20:37:21.235585Z","iopub.status.idle":"2022-06-22T20:37:21.243832Z","shell.execute_reply.started":"2022-06-22T20:37:21.235549Z","shell.execute_reply":"2022-06-22T20:37:21.242897Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def batch_gd(model, criterion, train_loader, validation_loader, epochs):\n       \n    prev_accuracy = 86.0\n    #weights.to(device)\n    for e in range(epochs):\n        t0 = datetime.now()\n        train_n_correct = 0\n        train_n_total = 0\n        validation_n_correct = 0\n        validation_n_total = 0\n        train_cm = torch.zeros(targets_size,targets_size,dtype=torch.int64)\n        validation_cm = torch.zeros(targets_size,targets_size,dtype=torch.int64)\n        \n        train_loss = []\n        for inputs, targets in train_loader:\n            inputs, targets = inputs.to(device), targets.to(device)\n            optimizer.zero_grad()\n\n            #output = model(inputs)\n            output, aux_output = model(inputs)  #for Inception_v3\n            loss1 = criterion(output, targets)      #for Inception_v3\n            loss2 = criterion(aux_output, targets)     #for Inception_v3\n            if loss1<loss2 :\n                loss = loss1\n            else :\n                loss = loss2\n            train_loss.append(loss.item())\n            \n            _, predictions = torch.max(output, 1)\n            train_n_correct += (predictions == targets).sum().item()\n            train_n_total += targets.shape[0]\n            \n            for t, p in zip(targets.view(-1), predictions.view(-1)):\n                train_cm[t.long(), p.long()] += 1\n                \n            loss.backward()\n            optimizer.step()\n\n        train_loss = np.mean(train_loss)\n        train_accuracy = train_n_correct/train_n_total\n        \n\n        validation_loss = []\n        for inputs, targets in validation_loader:\n\n            inputs, targets = inputs.to(device), targets.to(device)\n\n            #output = model(inputs)\n            output, aux_output = model(inputs)  #for Inception_v3 \n            loss = criterion(output, targets)\n            \n            validation_loss.append(loss.item())\n\n            _, predictions = torch.max(output, 1)\n            validation_n_correct += (predictions == targets).sum().item()\n            validation_n_total += targets.shape[0]\n            \n            for t, p in zip(targets.view(-1), predictions.view(-1)):\n                validation_cm[t.long(), p.long()] += 1\n\n        validation_loss = np.mean(validation_loss)\n        validation_accuracy = validation_n_correct/validation_n_total\n\n        \n        train_losses.append(train_loss)\n        validation_losses.append(validation_loss)\n        dt = datetime.now() - t0\n        print('----------------------------------------------------------------------------------------')\n        print(f\"Epoch : {e+1}/{epochs} Train_loss:{train_loss:.3f} Validation_loss:{validation_loss:.3f} Duration:{dt} Train_Acc:{train_accuracy*100:.2f} Validation_Acc:{validation_accuracy*100:.2f}\")\n        print(train_cm)\n        print(validation_cm)\n\n        if validation_accuracy > prev_accuracy:\n          prev_accuracy = validation_accuracy\n          if select_machine == 2 : #colab\n            os.chdir('/content/drive/MyDrive') \n          if select_machine == 3 : #kaggle\n            os.chdir('/kaggle/working')  \n          if select_machine == 1 : #local\n            os.chdir('C:/Local Machine/Cassava plant disease detection/...saves1')\n          torch.save(model.state_dict() , 'plant_disease_model_1.pt')\n          torch.save(train_dl , 'train_dl1.pth')\n          torch.save(val_dl , 'val_dl1.pth')\n          print(\"model saved !\")\n\n    return train_losses, validation_losses","metadata":{"execution":{"iopub.status.busy":"2022-06-22T20:37:21.245485Z","iopub.execute_input":"2022-06-22T20:37:21.246127Z","iopub.status.idle":"2022-06-22T20:37:21.266013Z","shell.execute_reply.started":"2022-06-22T20:37:21.246089Z","shell.execute_reply":"2022-06-22T20:37:21.264904Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.train()\ntrain_losses, validation_losses = batch_gd(model, criterion, train_dl, val_dl, 1)","metadata":{"execution":{"iopub.status.busy":"2022-06-22T20:37:21.269077Z","iopub.execute_input":"2022-06-22T20:37:21.269978Z","iopub.status.idle":"2022-06-22T20:53:29.035688Z","shell.execute_reply.started":"2022-06-22T20:37:21.269940Z","shell.execute_reply":"2022-06-22T20:53:29.034661Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.train()\ntrain_losses, validation_losses = batch_gd(model, criterion, train_dl, val_dl, 10)","metadata":{"execution":{"iopub.status.busy":"2022-06-19T06:54:48.438664Z","iopub.execute_input":"2022-06-19T06:54:48.439087Z","iopub.status.idle":"2022-06-19T07:46:08.540979Z","shell.execute_reply.started":"2022-06-19T06:54:48.439049Z","shell.execute_reply":"2022-06-19T07:46:08.540246Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.train()\ntrain_losses, validation_losses = batch_gd(model, criterion, train_dl, val_dl, 19)","metadata":{"execution":{"iopub.status.busy":"2022-06-19T07:48:32.589287Z","iopub.execute_input":"2022-06-19T07:48:32.590026Z","iopub.status.idle":"2022-06-19T09:25:27.136494Z","shell.execute_reply.started":"2022-06-19T07:48:32.589989Z","shell.execute_reply":"2022-06-19T09:25:27.135743Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.plot(train_losses , label = 'train_loss')\nplt.plot(validation_losses , label = 'validation_loss')\nplt.xlabel('No of Epochs')\nplt.ylabel('Loss')\nplt.legend()\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_confusion_matrix(cm, classes, normalize=False, title='Confusion matrix', cmap=plt.cm.Blues):\n    if normalize:\n        cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]\n        print(\"Normalized confusion matrix\")\n    else:\n        print('Confusion matrix, without normalization')\n\n    print(cm)\n    plt.imshow(cm, interpolation='nearest', cmap=cmap)\n    plt.title(title)\n    plt.colorbar()\n    tick_marks = np.arange(len(classes))\n    plt.xticks(tick_marks, classes, rotation=45)\n    plt.yticks(tick_marks, classes)\n\n    fmt = '.2f' if normalize else 'd'\n    thresh = cm.max() / 2.\n    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):\n        plt.text(j, i, format(cm[i, j], fmt), horizontalalignment=\"center\", color=\"white\" if cm[i, j] > thresh else \"black\")\n\n    plt.tight_layout()\n    plt.ylabel('True label')\n    plt.xlabel('Predicted label')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(10,10))\nplot_confusion_matrix(train_cm, label_names)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(10,10))\nplot_confusion_matrix(validation_cm, label_names)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Save Model, Data Loaders**","metadata":{}},{"cell_type":"code","source":"if select_machine == 1: os.chdir('C:/Local Machine/plant-pathology-fgvc8-resized-images/saves')   #local\nif select_machine == 2: os.chdir('/content/drive/MyDrive')   #colab\nif select_machine == 3: os.chdir('/kaggle/working')   #kaggle\ntorch.save(model.state_dict() , 'plant_disease_model_1.pt')\ntorch.save(train_dl , 'train_dl1.pth')\ntorch.save(val_dl , 'val_dl1.pth')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Load Model, Data Loaders**","metadata":{}},{"cell_type":"code","source":"if select_machine == 1: os.chdir('C:/Local Machine/plant-pathology-fgvc8-resized-images/saves')   #local\nif select_machine == 2: os.chdir('/content/drive/MyDrive')   #colab\nif select_machine == 3: os.chdir('/kaggle/working')   #kaggle\ntargets_size = 12\nmodel.load_state_dict(torch.load(\"plant_disease_model_1.pt\"))\ntrain_dl = torch.load(\"train_dl1.pth\")\nval_dl = torch.load(\"val_dl1.pth\")","metadata":{},"execution_count":null,"outputs":[]}]}