{"cells":[{"metadata":{},"cell_type":"markdown","source":"## Usual Imports"},{"metadata":{"cellView":"form","id":"JBR2E5ArxhIy","outputId":"78d4e818-edb0-440e-d736-3ff72134dc67","trusted":true},"cell_type":"code","source":"import numpy as np\nimport matplotlib.pylab as plt\nimport pandas as pd\nimport time, random, os, cv2\nimport torch\nfrom torch import nn\nfrom torch import optim\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms\nprint(torch.__version__)\nfrom torch.autograd import Variable\nimport torch.nn.functional as F\nfrom torchvision import datasets, transforms, models\nfrom torch.utils.data import Dataset, DataLoader\nimport torchvision\nfrom torchvision import transforms, utils\n\n!pip install torchsummary --quiet\n%matplotlib inline\nfrom matplotlib import pyplot as plt\nimport matplotlib\nfrom sklearn.metrics import roc_curve\nfrom sklearn.metrics import roc_auc_score\ntry:\n    from efficientnet_pytorch import EfficientNet\nexcept ModuleNotFoundError:\n    import subprocess, sys\n    subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'efficientnet_pytorch'])\n    from efficientnet_pytorch import EfficientNet\n","execution_count":null,"outputs":[]},{"metadata":{"id":"aL7XsGYBzP6-"},"cell_type":"markdown","source":"# Exploratory Data Analysis"},{"metadata":{"trusted":true},"cell_type":"code","source":"df = pd.read_csv('../input/cassava-leaf-disease-classification/train.csv')\ndf = df.sample(frac=1).reset_index(drop=True)\nprint(df.shape)\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"image_path = \"../input/cassava-leaf-disease-classification/train_images/\"\nfull_image_paths = [os.path.join(image_path, x) for x in df.image_id.values]\ndf['file_path'] = full_image_paths\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{"id":"Ebl1vkplzTnc","outputId":"d4de2ec1-af7f-40bf-f409-0e925214dbac","trusted":true},"cell_type":"code","source":"for i in range(0, len(np.unique(df.label.values))):\n    print(\"label {} - Total Count {}\".format(i,df.label[df.label==i].count()))\n\nimport seaborn as sns\nsns.countplot(df['label'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"NUM_SAMP=5\nfig = plt.figure(figsize=(25, 16))\nimport cv2\nIMG_SIZE = 512\nfor jj in range(5):\n    for i, (idx, row) in enumerate(df.sample(NUM_SAMP,random_state=123+jj).iterrows()):\n        ax = fig.add_subplot(5, NUM_SAMP, jj * NUM_SAMP + i + 1, xticks=[], yticks=[])\n        path= row['file_path']\n        label = row['label'] \n        image = plt.imread(path)\n        plt.imshow(image)\n        ax.set_title('Label - %d' % (label) )","execution_count":null,"outputs":[]},{"metadata":{"id":"heQdDb9OzVgG"},"cell_type":"markdown","source":"# Assigning folds/ (Train-Test) Split"},{"metadata":{"id":"Ifmog7IszWIF","outputId":"462afbcd-323b-4939-cd74-f57ed9ccacf5","trusted":true},"cell_type":"code","source":"from sklearn import metrics, model_selection\n\ndf_train, df_valid = model_selection.train_test_split(df, test_size=0.1, random_state=42, stratify=df.label.values)\ndf_train = df_train.sample(frac=1).reset_index(drop=True)\ndf_valid = df_valid.sample(frac=1).reset_index(drop=True)\nprint(df_train.shape, df_valid.shape)","execution_count":null,"outputs":[]},{"metadata":{"id":"cQx7Zcc3zaMB"},"cell_type":"markdown","source":"## Fact check on how many train and test split exists for each class."},{"metadata":{"id":"FAO2iht2zX6P","outputId":"c67fae6b-fc52-4a53-a3fa-5ea9f188dae9","trusted":true},"cell_type":"code","source":"print(\"Stats\\n\")\nfor i in range(0, len(np.unique(df.label.values))):\n    train = valid = 0\n    train = df_train[(df_train['label'] == i)].shape[0]\n    valid = df_valid[(df_valid['label'] == i)].shape[0]\n    print(\"For level {}, total number of training samples is {} and testing samples is {} \\n\".format(i, train, valid))\n","execution_count":null,"outputs":[]},{"metadata":{"id":"Bh9c5YP7zeMB"},"cell_type":"markdown","source":"## End of Exploratory analysis and dataframe preprocessing"},{"metadata":{"id":"dATiK0arzkSS"},"cell_type":"markdown","source":"# Pytorch Model Building"},{"metadata":{"id":"a4DN828-zmVj"},"cell_type":"markdown","source":"## Building the model as a classifier (5 output classes)"},{"metadata":{"id":"y2ZoYikLzkuf","trusted":true},"cell_type":"code","source":"classifier = True # input as False makes the model regressor.\n\n# Flag for feature extracting. When False, we finetune the whole model,\nfeature_extract = False\n\n# Number of classes in the dataset\nnum_classes = 5 # Classifier\ncriterion =  nn.CrossEntropyLoss()  \n\ndef set_parameter_requires_grad(model, feature_extracting):\n    if feature_extracting:\n        for param in model.parameters():\n            param.requires_grad = False\n\ndef initialize_model(model_name, num_classes, feature_extract, use_pretrained=True):\n    # Initialize these variables which will be seat in this if statement. Each of these\n    #   variables is model specific.\n    model_ft = None\n    input_size = 0\n\n    if model_name == \"resnet\":\n        \"\"\" Resnet18\n        \"\"\"\n        model_ft = models.resnet18(pretrained=use_pretrained)\n        set_parameter_requires_grad(model_ft, feature_extract)\n        num_ftrs = model_ft.fc.in_features\n        model_ft.avgpool = nn.AdaptiveMaxPool2d(output_size=(1, 1))\n        model_ft.fc = nn.Linear(num_ftrs, num_classes)\n        input_size = 224\n        \n\n    elif model_name == \"alexnet\":\n        \"\"\" Alexnet\n        \"\"\"\n        model_ft = models.alexnet(pretrained=use_pretrained)\n        set_parameter_requires_grad(model_ft, feature_extract)\n        num_ftrs = model_ft.classifier[6].in_features\n        model_ft.classifier[6] = nn.Linear(num_ftrs,num_classes)\n        input_size = 224\n\n    elif model_name == \"vgg\":\n        \"\"\" VGG11_bn\n        \"\"\"\n        model_ft = models.vgg11_bn(pretrained=use_pretrained)\n        set_parameter_requires_grad(model_ft, feature_extract)\n        num_ftrs = model_ft.classifier[6].in_features\n        model_ft.classifier[6] = nn.Linear(num_ftrs,num_classes)\n        input_size = 224\n\n    elif model_name == \"squeezenet\":\n        \"\"\" Squeezenet\n        \"\"\"\n        model_ft = models.squeezenet1_0(pretrained=use_pretrained)\n        set_parameter_requires_grad(model_ft, feature_extract)\n        model_ft.classifier[1] = nn.Conv2d(512, num_classes, kernel_size=(1,1), stride=(1,1))\n        model_ft.num_classes = num_classes\n        input_size = 224\n\n    elif model_name == \"densenet\":\n        \"\"\" Densenet\n        \"\"\"\n        model_ft = models.densenet121(pretrained=use_pretrained)\n        set_parameter_requires_grad(model_ft, feature_extract)\n        num_ftrs = model_ft.classifier.in_features\n        model_ft.classifier = nn.Linear(num_ftrs, num_classes)\n        input_size = 224\n\n    elif model_name == \"inception\":\n        \"\"\" Inception v3\n        Be careful, expects (299,299) sized images and has auxiliary output\n        \"\"\"\n        model_ft = models.inception_v3(pretrained=use_pretrained, aux_logits=False)\n        set_parameter_requires_grad(model_ft, feature_extract)\n        # Handle the auxilary net\n        #num_ftrs = model_ft.AuxLogits.fc.in_features\n        #model_ft.AuxLogits.fc = nn.Linear(num_ftrs, num_classes)\n        # Handle the primary net\n        num_ftrs = model_ft.fc.in_features\n        model_ft.fc = nn.Linear(num_ftrs,num_classes)\n        input_size = 299\n        \n    elif model_name == \"efficientnet-b0\":\n        \"\"\" efficientnet https://keras.io/examples/vision/image_classification_efficientnet_fine_tuning/\n        \"\"\"\n        model_ft = EfficientNet.from_pretrained('efficientnet-b0')\n        set_parameter_requires_grad(model_ft, feature_extract)\n        num_ftrs = model_ft._fc.in_features\n        model_ft._avg_pooling = nn.AdaptiveMaxPool2d(output_size=(1, 1))\n        model_ft._fc = nn.Linear(num_ftrs, num_classes)\n        input_size = 224\n        \n    elif model_name == \"efficientnet-b1\":\n        \"\"\" efficientnet\n        \"\"\"\n        model_ft = EfficientNet.from_pretrained('efficientnet-b1')\n        set_parameter_requires_grad(model_ft, feature_extract)\n        num_ftrs = model_ft._fc.in_features\n        model_ft._avg_pooling = nn.AdaptiveMaxPool2d(output_size=(1, 1))\n        model_ft._fc = nn.Linear(num_ftrs, num_classes)\n        input_size = 240\n        \n    else:\n        print(\"Invalid model name, exiting...\")\n        exit()\n\n    return model_ft, input_size","execution_count":null,"outputs":[]},{"metadata":{"id":"JOL0ExvWzqZb"},"cell_type":"markdown","source":"## Model Selection"},{"metadata":{"id":"2hDPNkm-zot7","outputId":"5b4a0caa-5479-4c40-eb3e-e4379926a164","scrolled":true,"trusted":true},"cell_type":"code","source":"# Initialize the model for this run\nmodel_name = \"efficientnet-b0\" # Models to choose [\"resnet\", \"vgg\", \"squeezenet\", \"densenet\", \"inception\", \"efficientnet-b0\", efficientnet-b1]\nmodel_ft, input_size = initialize_model(model_name, num_classes, feature_extract, use_pretrained=True)\n\n# Print the model we just instantiated\nprint(model_ft)\nprint()\nprint(\"Input image size format\",(input_size,input_size))","execution_count":null,"outputs":[]},{"metadata":{"id":"uk4mg8QRzuED","trusted":true},"cell_type":"code","source":"from torchsummary import summary\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\") # PyTorch v0.4.0\nmodel_ft = model_ft.to(device)\n\n#summary(model_ft, (3, input_size, input_size))\n","execution_count":null,"outputs":[]},{"metadata":{"id":"0gKLqEbdzuam","outputId":"d18027b4-6f65-41a0-e829-18bdbc3c3c33","trusted":true},"cell_type":"code","source":"sample_input = torch.randn(2,3,input_size,input_size)\nsample_input = sample_input.to(device)\nprint(\"Shape {} and Type {} and Data-Type {}\".format(sample_input.shape, type(sample_input), sample_input.dtype))\nout = model_ft(sample_input)\nout","execution_count":null,"outputs":[]},{"metadata":{"id":"r__WS3w0zxD7"},"cell_type":"markdown","source":"## Hyper-Parameters"},{"metadata":{"id":"M4SpqG9zzxhs","outputId":"31f62496-ac8a-44af-86b6-fd4cc2db8ad1","trusted":true},"cell_type":"code","source":"#input_size = 224\nBATCH_SIZE =  512 # Desired batch size\nimg_size = input_size # This sets the input image size based on the model's you choose\ndevice = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n\nprint(\"Running on\",device)\nif torch.cuda.device_count() > 1:\n    print(\"Let's use\", torch.cuda.device_count(), \"GPUs!\")\n    model_ft = nn.DataParallel(model_ft)\n    \nparams_to_update = model_ft.parameters()\n\nprint(\"Params to learn:\")\nif feature_extract:\n    params_to_update = []\n    for name,param in model_ft.named_parameters():\n        if param.requires_grad == True:\n            params_to_update.append(param)\n            print(\"\\t\",name)\nelse:\n    for name,param in model_ft.named_parameters():\n        if param.requires_grad == True:\n            print(\"\\t\",name)\n            \n\nlearning_rate=0.001\n\n#SGD = high dimensional optimization aka, higher batch size for SGD\noptimizer = optim.SGD(params_to_update, lr=learning_rate , momentum=0.9)\n# optimizer = optim.Adam(params_to_update, lr=learning_rate)\n\n#scheduler course corrects learning_rate\nscheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, factor=0.85, patience=2, verbose=True)","execution_count":null,"outputs":[]},{"metadata":{"id":"aXfxT_cgz1PP"},"cell_type":"markdown","source":"## DATASET and DATALOADERS for Pytorch"},{"metadata":{"id":"f6WoOUttz2YN","outputId":"56200c63-6172-46e0-e717-691e1dd0316d","trusted":true},"cell_type":"code","source":"# utility functions\n\ndef image_preprocess(file_path, img_size=input_size):\n    image = cv2.imread(file_path)\n    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n    image = cv2.resize(image, (img_size, img_size))\n    image = image.astype(np.float32)\n    image /= 255.\n    # print(\"Shape {} and Type {} and Data-Type {}\".format(image.shape, type(image), image.dtype))\n    image = np.array(image)\n    image = torch.from_numpy(image)\n    #plt.imshow(image)\n    #plt.show()\n    return image\n  \nclass Cassava_Leaf_Dataset(Dataset):\n    # Constructor\n    def __init__(self, df, img_size, transform=None, sample=0):\n        # Image directory\n        self.transform = transform\n        self.img_size = img_size\n        self.df = df\n        self.sample = sample\n        if self.sample > 0:\n            self.df = self.df.sample(self.sample, random_state=42) # sample small subset if required\n\n    # Get the length\n    def __len__(self):\n        return len(self.df)\n    \n    # Getter\n    def __getitem__(self, idx):\n        path = self.df.index[idx]\n        # print(path)\n        image = image_preprocess(path, img_size)\n        label = np.array(self.df.label[idx])\n        label = label.astype(np.uint8)\n        label = torch.from_numpy(label)\n        return image, label\n\ndf_train_to_model = df_train\ndf_train_to_model = df_train_to_model.set_index('file_path')\n\ndf_valid_to_model = df_valid\ndf_valid_to_model = df_valid_to_model.set_index('file_path')\n\nSAMPLE = 0 # Increase the sample size if you want to train only on a specific number of samples, otherwise to train on entire datset, set sample = 0\n\ntransformed_datasets = {}\ntransformed_datasets['train'] = Cassava_Leaf_Dataset(df = df_train_to_model, img_size = img_size, sample=SAMPLE)\ntransformed_datasets['valid'] = Cassava_Leaf_Dataset(df = df_valid_to_model, img_size = img_size, sample=SAMPLE)\n\ndataloaders = {}\ndataloaders['train'] = torch.utils.data.DataLoader(transformed_datasets['train'],batch_size=BATCH_SIZE,shuffle=True,num_workers=8)\ndataloaders['valid'] = torch.utils.data.DataLoader(transformed_datasets['valid'],batch_size=BATCH_SIZE,shuffle=True,num_workers=8)  \n\nprint()\nprint(\"Total images in the training loop is {}, divided by a batchsize of {} , that is {} total sets\".format(len(transformed_datasets['train']), BATCH_SIZE, len(dataloaders['train'])))\nprint(\"Total images in the testing loop is {}, divided by a batchsize of {} , that is {} total sets\".format(len(transformed_datasets['valid']), BATCH_SIZE, len(dataloaders['valid'])))\n","execution_count":null,"outputs":[]},{"metadata":{"id":"obWd3481z55s"},"cell_type":"markdown","source":"## Excerpts from the validation samples"},{"metadata":{"id":"l5ky2UYaz6RO","outputId":"ae64c6c1-69ed-4960-c031-0c8d9f177653","trusted":true},"cell_type":"code","source":"for data in dataloaders['valid']:\n    images, labels = data\n    images = images.to('cpu')\n    print(labels, len(labels))\n    break\n    \nplt.figure(figsize=(20,10)) \nfor i in range(16):\n    plt.subplot(4,4, i+1)\n    plt.imshow(images[i,:,:,:])\n","execution_count":null,"outputs":[]},{"metadata":{"id":"6gHVXDIuz8pN"},"cell_type":"markdown","source":"## Training Process"},{"metadata":{"cellView":"code","id":"Sqkx3xoJz9D2","trusted":true},"cell_type":"code","source":"#@title Training Loop Codes\nfrom IPython.display import HTML, display\n \nclass ProgressMonitor(object):\n    \"\"\"\n    Custom IPython progress bar for training\n    \"\"\"\n    \n    tmpl = \"\"\"\n        <p>Loss: {loss:0.4f}   {value} / {length}</p>\n        <progress value='{value}' max='{length}', style='width: 100%'>{value}</progress>\n    \"\"\"\n \n    def __init__(self, length):\n        self.length = length\n        self.count = 0\n        self.display = display(self.html(0, 0), display_id=True)\n        \n    def html(self, count, loss):\n        return HTML(self.tmpl.format(length=self.length, value=count, loss=loss))\n        \n    def update(self, count, loss):\n        self.count += count\n        self.display.update(self.html(self.count, loss))\n\ndef checkpoint_and_save(model, best_loss, epoch, optimizer, epoch_valid_loss, model_save_name):\n    print('saving')\n    print()\n    state = {'model': model,'best_loss': best_loss,'epoch': epoch,'rng_state': torch.get_rng_state(), 'optimizer': optimizer.state_dict(),}\n    torch.save(model, './{}-CL.pt'.format(model_save_name))\n    torch.save(model.state_dict(),'./{}-statedict-CL.pt'.format(model_save_name))\n    \ndef train_new(model,criterion,optimizer,num_epochs,dataloaders,dataset_sizes, model_save_name,first_epoch=1):\n    since = time.time() \n    best_loss = 999999\n    best_epoch = -1\n    last_train_loss = -1\n    plot_train_loss = []\n    plot_valid_loss = []\n    plot_train_acc = []\n    plot_valid_acc = []\n \n \n    for epoch in range(first_epoch, first_epoch + num_epochs):\n        print()\n        print('Epoch', epoch)\n        running_loss = 0.0\n        valid_loss = 0.0\n        training_accuracy = 0\n        validation_accuracy = 0\n      \n        # train phase\n        model.train(True)\n \n      # create a progress bar\n        progress = ProgressMonitor(length=dataset_sizes[\"train\"])\n \n        for data in dataloaders[\"train\"]:\n            inputs, labels  = data # (Batch_size, width, height, channels)\n            batch_size = inputs.shape[0]\n            inputs = inputs.permute(0,3,1,2) # Batch_size, channels, width, height\n            inputs = inputs.to(device)\n            labels = labels.to(device,dtype=torch.long)\n            inputs = Variable(inputs)\n            labels = Variable(labels)\n            optimizer.zero_grad() \n            outputs = model(inputs) # batch, 2, 240, 240\n\n            loss = criterion(outputs, labels) # comparing outputs with the actual labels\n \n            loss.backward() \n            optimizer.step() \n                      \n            running_loss += loss.data * batch_size\n            training_accuracy += (outputs.argmax(1) == labels).sum().item() # if(0 ==0, or 1 == 1)\n            # update progress bar\n            progress.update(batch_size, running_loss)\n \n        epoch_loss = running_loss / dataset_sizes[\"train\"]\n        \n        print('Training Accuracy is {:.2f} and Training loss {:.2f}'.format(training_accuracy / dataset_sizes[\"train\"],epoch_loss.item()))\n        print('Correctly predicted {} Training samples out of {}'.format(training_accuracy, dataset_sizes[\"train\"]))\n        print()\n        plot_train_loss.append(epoch_loss)\n        plot_train_acc.append(training_accuracy / dataset_sizes[\"train\"])\n \n \n      # validation phase\n        model.eval()\n      # no_grad to save memory\n        with torch.no_grad():\n            for data in dataloaders[\"valid\"]:\n                inputs, labels  = data\n                batch_size = inputs.shape[0]\n                inputs = inputs.permute(0,3,1,2)\n                inputs = inputs.to(device)\n                labels = labels.to(device,dtype=torch.long)\n                inputs = Variable(inputs)\n                labels = Variable(labels)\n                \n                outputs = model(inputs)\n \n            # calculate the loss\n                optimizer.zero_grad()\n                loss = criterion(outputs, labels)\n            \n            # update running loss value\n                valid_loss += loss.data * batch_size\n                validation_accuracy += (outputs.argmax(1) == labels).sum().item()\n                    \n \n        epoch_valid_loss = valid_loss / dataset_sizes[\"valid\"]\n        scheduler.step(epoch_valid_loss)\n        print('Validation Accuracy is {:.2f} and Validation loss {:.2f}'.format(validation_accuracy / dataset_sizes[\"valid\"],epoch_valid_loss.item()))\n        print('Correctly predicted {} Validation samples out of {}'.format(validation_accuracy, dataset_sizes[\"valid\"]))\n        print()\n        plot_valid_loss.append(epoch_valid_loss)\n        plot_valid_acc.append(validation_accuracy / dataset_sizes[\"valid\"])\n          \n        if epoch_valid_loss < best_loss:\n            best_loss = epoch_valid_loss\n            best_epoch = epoch\n            checkpoint_and_save(model, best_loss, epoch, optimizer, epoch_valid_loss.item(), model_save_name)\n\n        if ((epoch - best_epoch) >= 10):\n            print(\"no improvement in 10 epochs, break\")\n            break\n \n    time_elapsed = time.time() - since\n    print('Training complete in {:.0f}m {:.0f}s'.format(time_elapsed // 60, time_elapsed % 60))\n \n    return plot_train_loss, plot_valid_loss, plot_train_acc, plot_valid_acc, model","execution_count":null,"outputs":[]},{"metadata":{"id":"cffFjW0Y0Ab2"},"cell_type":"markdown","source":"## Training Loop"},{"metadata":{"id":"FypxE1230A7N","outputId":"ce04abd8-924a-4ac6-96a3-c5afdcb0dc02","trusted":true},"cell_type":"code","source":"dataset_sizes = {x: len(transformed_datasets[x]) for x in ['train', 'valid']}\nepochs = 20\nif __name__==\"__main__\":\n    train_losses, valid_losses, train_accuracy, valid_accuracy, model = train_new(model = model_ft ,criterion = criterion,optimizer = optimizer,\n                                                                                  num_epochs=epochs,dataloaders = dataloaders,\n                                                                                  dataset_sizes = dataset_sizes, model_save_name = model_name)","execution_count":null,"outputs":[]},{"metadata":{"id":"haDxg3o10FkF"},"cell_type":"markdown","source":"# Model's Metrics ~ Accuracy, F1 Score, Confusion Matrix"},{"metadata":{"id":"3forXqii0C2R","outputId":"dbdf12ec-16c4-4a95-c2ae-117723d2d0ff","trusted":true},"cell_type":"code","source":"# Plot Accuracy\nplt.title('Training and Validation Accuracy')\nplt.plot(train_accuracy)\nplt.plot(valid_accuracy)\nplt.legend(['Training_Accuracy','Validation_Accuracy'])","execution_count":null,"outputs":[]},{"metadata":{"id":"RKSPHl710HPQ","outputId":"2d46b18d-b182-4d50-e508-4192ea64acb0","trusted":true},"cell_type":"code","source":"plt.title('Training and Validation Loss')\nplt.plot(train_losses)\nplt.plot(valid_losses)\nplt.legend(['Training_loss','Validation_loss'])","execution_count":null,"outputs":[]},{"metadata":{"id":"AvQq_DWy0IoB","outputId":"b52a039c-9df2-41d2-b23f-4e93dc7e0eac","trusted":true},"cell_type":"code","source":"plt.figure(figsize=(12,8))\nplt.title('Training & Validation Accuracy and Loss')\nplt.plot(train_accuracy)\nplt.plot(valid_accuracy)\nplt.plot(train_losses)\nplt.plot(valid_losses)\nplt.legend(['Training_Accuracy','Validation_Accuracy','Training_loss','Validation_loss'])","execution_count":null,"outputs":[]},{"metadata":{"id":"pmUta1dX0Lo7"},"cell_type":"markdown","source":"## F1 - Score, Confusion Matrix"},{"metadata":{"id":"1MLkzcFz0MAs","outputId":"5b35692d-e62c-401f-8e03-225f08b5336b","trusted":true},"cell_type":"code","source":"from sklearn.metrics import f1_score\nwith torch.no_grad():\n  complete_outputs = []\n  complete_labels = []\n  for data in dataloaders[\"valid\"]:\n    inputs, labels  = data\n    inputs = inputs.permute(0,3,1,2)\n    inputs = inputs.to(device)\n    labels = labels.to(device,dtype=torch.long)\n    inputs = Variable(inputs)\n    labels = Variable(labels)\n    outputs = model(inputs)\n    complete_outputs.extend(list(outputs.argmax(1).cpu().data.numpy()))\n    complete_labels.extend(list(labels.cpu().data.numpy()))\n\nassert len(complete_outputs) == len(complete_labels)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.metrics import confusion_matrix\nimport seaborn as sns\n\ncf_matrix = confusion_matrix(complete_outputs, complete_labels)\nsns.heatmap(cf_matrix, annot=True, fmt=\"d\", cmap=\"YlGnBu\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.metrics import classification_report\ntarget_names = ['Class_1', 'Class_2', 'Class_3', 'Class_4', 'Class_5']\nprint(classification_report(complete_outputs, complete_labels, target_names=target_names))","execution_count":null,"outputs":[]},{"metadata":{"id":"W7bNm0j10PEe"},"cell_type":"markdown","source":"# Inference"},{"metadata":{"id":"iT8fcSKH0PZu","outputId":"fa50e2ac-55da-4cfb-b291-b477289ae2e5","trusted":true},"cell_type":"code","source":"def tester(image, model):\n    img = (image).to(device)\n    img = img.unsqueeze(0)\n    img = img.permute(0,3,1,2) # (bs, width, height, channels) --> (bs, channels, width, height)\n    output = model(img)\n    return output.argmax(1).item()\n\nNUM_SAMP=10\nfig = plt.figure(figsize=(25, 16))\ncount = 0\nfor jj in range(5):\n    for i, (idx, row) in enumerate(df_valid.sample(NUM_SAMP,random_state=123+jj).iterrows()):\n        ax = fig.add_subplot(5, NUM_SAMP, jj * NUM_SAMP + i + 1, xticks=[], yticks=[])\n        path= row['file_path']\n        orig_label = int(row['label'] )\n        image = image_preprocess(path, img_size=input_size) #224,224,3\n        pred_label = tester(image, model)\n        if (orig_label == pred_label):\n            count +=1\n        plt.imshow(image)\n        ax.set_title('%d - %d' % (orig_label, pred_label))\nprint()\nprint(\"Out of {} samples, model predicted {} samples correctly\".format((NUM_SAMP*5), count))\nprint()\nprint(\"Legends : Original Label Vs Predicted Label\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def Load_Models_Dynamic():\n    num_gpus = torch.cuda.device_count()\n    device, model = {}, {}\n    models = []\n    device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n    model = torch.load(\"./efficientnet-b0-TS.pt\", map_location=device).eval()\n    models.append(model)\n    return models\n\nmodels = Load_Models_Dynamic()\nmodels","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import os\ntry:\n    os.mkdir(\"./deps\")\nexcept FileExistsError:\n    pass\n!pip install efficientnet_pytorch -t \"./deps\" --no-deps","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import shutil\nshutil.make_archive(\"./deps\",'zip','./')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"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}