code: import seaborn as sns
  import matplotlib.pyplot as plt
  import torch
  import numpy as np
  import cv2
  from .cam import GradCAM
  
  
  # def load_gradcam(images, labels, model, device, target_layers):
  def load_gradcam(test, model, device, target_layers,size = 25,classified = True):
  
      _images = []
      _target = []
      _pred = []
  
      # model, device = self.trainer.model, self.trainer.device
  
      # set the model to evaluation mode
      model.eval()
  
      # turn off gradients
      with torch.no_grad():
          for data, target in test:
              # move them to respective device
              data, target = data.to(device), target.to(device)
  
              # do inferencing
              output = model(data)
              # print("output:",output[0])
              # get the predicted output
              pred = output.argmax(dim=1, keepdim=True)
              # print(pred,pred.view_as(target))
  
              # get the current misclassified in this batch
              list_images = (target.eq(pred.view_as(target)) == classified)
              batch_misclassified = data[list_images]
              batch_mis_pred = pred[list_images]
              batch_mis_target = target[list_images]
  
              # batch_misclassified =
  
              _images.append(batch_misclassified)
              _pred.append(batch_mis_pred)
              _target.append(batch_mis_target)
  
      # group all the batched together
      img = torch.cat(_images)
      pred = torch.cat(_pred)
      tar = torch.cat(_target)
      # move the model to device
  
      images = img[:size]
      labels = tar[:size]
  
      model.to(device)
  
      # set the model in evaluation mode
      model.eval()
  
      # get the grad cam
      gcam = GradCAM(model=model, candidate_layers=target_layers)
  
      # images = torch.stack(images).to(device)
  
      # predicted probabilities and class ids
      pred_probs, pred_ids = gcam.forward(images)
  
      # actual class ids
      # target_ids = torch.LongTensor(labels).view(len(images), -1).to(device)
      target_ids = labels.view(len(images), -1).to(device)
  
      # backward pass wrt to the actual ids
      gcam.backward(ids=target_ids)
  
      # we will store the layers and correspondings images activations here
      layers_region = {}
  
      # fetch the grad cam layers of all the images
      for target_layer in target_layers:
  
          # Grad-CAM
          regions = gcam.generate(target_layer=target_layer)
  
          layers_region[target_layer] = regions
  
      # we are done here, remove the hooks
      gcam.remove_hook()
  
      return layers_region, pred_probs, pred_ids,images, labels
  
  
  sns.set()
  # plt.style.use("dark_background")
  
  
  def plot_gradcam(gcam_layers, images, target_labels, predicted_labels, class_labels, denormalize):
  
      images = images.cpu()
      # convert BCHW to BHWC for plotting stufffff
      images = images.permute(0, 2, 3, 1)
      target_labels = target_labels.cpu()
  
      fig, axs = plt.subplots(nrows=len(images), ncols=len(
          gcam_layers.keys())+1, figsize=((len(gcam_layers.keys()) + 2)*3, len(images)*3))
      fig.suptitle("Grad-CAM", fontsize=16)
  
      for image_idx, image in enumerate(images):
  
          # denormalize the imaeg
          denorm_img = denormalize(image.permute(2, 0, 1)).permute(1, 2, 0)
  
          # axs[image_idx, 0].text(
          #     0.5, 0.5, f'predicted: {class_labels[predicted_labels[image_idx][0] ]}\nactual: {class_labels[target_labels[image_idx]] }', horizontalalignment='center', verticalalignment='center', fontsize=14, )
          # axs[image_idx, 0].axis('off')
  
          axs[image_idx, 0].imshow(
              (denorm_img.numpy() * 255).astype(np.uint8),  interpolation='bilinear')
          axs[image_idx, 0].axis('off')
  
          for layer_idx, layer_name in enumerate(gcam_layers.keys()):
              # gets H X W of the cam layer
              _layer = gcam_layers[layer_name][image_idx].cpu().numpy()[0]
              heatmap = 1 - _layer
              heatmap = np.uint8(255 * heatmap)
              heatmap_img = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)
  
              superimposed_img = cv2.addWeighted(
                  (denorm_img.numpy() * 255).astype(np.uint8), 0.6, heatmap_img, 0.4, 0)
  
              axs[image_idx, layer_idx +
                  1].imshow(superimposed_img, interpolation='bilinear')
              axs[image_idx, layer_idx+1].set_title(f'layer: {layer_name}')
              axs[image_idx, layer_idx+1].axis('off')
          axs[image_idx, 0].set_title(f'Predicted: {class_labels[predicted_labels[image_idx][0] ]}\nTarget: {class_labels[target_labels[image_idx]] }')
  
      plt.tight_layout()
      plt.subplots_adjust(top=0.95, wspace=0.2, hspace=0.2)
      plt.show() from torch.utils.data import DataLoader, Dataset
  from torchvision import datasets
  from .util import download_and_extract_archive
  import os, glob
  from PIL import Image
  class DatasetMnist:
      """
          This class loads MNIST dataset with applied transformations
  
          # Functions:
  
              __repr__:
  
                  This is a representation function, It returns the printable representation of the object.
  
              __str__:
  
                  It returns useful string representation of the object.
  
              __init__:
  
                  This is the constructor of DataMnist class< It initializes dataset and applied transformations over it.
              
              load_data:
  
                  This function returns the generated datasaet.
      """
      def __repr__(self):
          return "Loading MNIST Dataset"
  
      def __str__(self):
          return "Loading MNIST Dataset"
  
      def __init__(self, data_path:str, *, batch_size = 32, shuffle = True,transformations, sampler=None, batch_sampler=None, num_workers=0, collate_fn=None, pin_memory=False, drop_last=False, timeout=0, worker_init_fn=None, multiprocessing_context=None, generator=None):
          """
              This function initializes the dataset based on the values provided as parameters
  
              # Param:
  
                  data_path: Root directory of dataset where MNIST/processed/training.pt and MNIST/processed/testing.pt exist.
  
                  batch_size (int, optional): how many samples per batch to load (default: ``1``).
  
                  shuffle (bool, optional): set to ``True`` to have the data reshuffled at every epoch (default: ``False``).
  
                  transformations:  A function/transform that takes in an PIL image and returns a transformed version. E.g, transforms.RandomCrop                
          
                  sampler (Sampler, optional): defines the strategy to draw samples from the dataset. If specified, ``shuffle`` must be False.
                  
                  batch_sampler (Sampler, optional): like sampler, but returns a batch ofindices at a time. Mutually exclusive with :attr:`batch_size`,:attr:`shuffle`, :attr:`sampler`, and :attr:`drop_last`.
          
                  num_workers (int, optional): how many subprocesses to use for dataloading. 0 means that the data will be loaded in the main process.(default: ``0``)
                  
                  collate_fn (callable, optional): merges a list of samples to form a mini-batch.
                  
                  pin_memory (bool, optional): If ``True``, the data loader will copy tensors into CUDA pinned memory before returning them.  If your data elements are a custom type, or your ``collate_fn`` returns a batch that is a custom type
                                               see the example below.
                  
                  drop_last (bool, optional): set to ``True`` to drop the last incomplete batch, if the dataset size is not divisible by the batch size. If ``False`` and the size of dataset is not divisible by the batch size, then the last batch
                                              will be smaller. (default: ``False``)
  
                  timeout (numeric, optional): if positive, the timeout value for collecting a batch from workers. Should always be non-negative. (default: ``0``)
                  
                  worker_init_fn (callable, optional): If not ``None``, this will be called on each worker subprocess with the worker id (an int in ``[0, num_workers - 1]``) as input, after seeding and before data loading. (default: ``None``)
          """
          self.data_path = data_path
          self.train_set = datasets.MNIST(root = self.data_path,train = True,download = True, transform = transformations.apply_transforms(train = True))
          self.test_set = datasets.MNIST(root = self.data_path,train = False,download = True, transform = transformations.apply_transforms(train = False))
          self.params = {
              'shuffle': shuffle,
              'batch_size': batch_size,
              'sampler': sampler,
              'batch_sampler':batch_sampler,
              'collate_fn':collate_fn,
              'drop_last':drop_last,
              'timeout':timeout,
              'worker_init_fn':worker_init_fn,
              'multiprocessing_context':multiprocessing_context,
              'generator':generator,
              'num_workers': num_workers,
              'pin_memory': pin_memory
          }
  
      def load_data(self):
          """
              This function returns the generated dataset
  
              # Returns:
  
                  Dataset,Dataset : Generated test and train dataset
          """
          return DataLoader(self.train_set,**self.params),DataLoader(self.test_set,**self.params)
      
  class DatasetCifar10:
  
      def __repr__(self):
          return "Loading CIFAR 10 Dataset"
  
      def __str__(self):
          return "Loading CIFAR 10 Dataset"
  
      def __init__(self, data_path,transformations,*, batch_size = 32 , shuffle = True, sampler=None, batch_sampler=None, num_workers=0, collate_fn=None, pin_memory=False, drop_last=False, timeout=0, worker_init_fn=None, multiprocessing_context=None, generator=None):
          """
              This function initializes the dataset based on the values provided as parameters
  
              # Param:
  
                  data_path: Root directory of dataset where CIFAR10/processed/train.pt and CIFAR10/processed/test.pt exist.
  
                  batch_size (int, optional): how many samples per batch to load (default: ``1``).
  
                  shuffle (bool, optional): set to ``True`` to have the data reshuffled at every epoch (default: ``False``).
  
                  transformations:  A function/transform that takes in an PIL image and returns a transformed version. E.g, transforms.RandomCrop                
          
                  sampler (Sampler, optional): defines the strategy to draw samples from the dataset. If specified, ``shuffle`` must be False.
                  
                  batch_sampler (Sampler, optional): like sampler, but returns a batch ofindices at a time. Mutually exclusive with :attr:`batch_size`,:attr:`shuffle`, :attr:`sampler`, and :attr:`drop_last`.
          
                  num_workers (int, optional): how many subprocesses to use for dataloading. 0 means that the data will be loaded in the main process.(default: ``0``)
                  
                  collate_fn (callable, optional): merges a list of samples to form a mini-batch.
                  
                  pin_memory (bool, optional): If ``True``, the data loader will copy tensors into CUDA pinned memory before returning them.  If your data elements are a custom type, or your ``collate_fn`` returns a batch that is a custom type
                                               see the example below.
                  
                  drop_last (bool, optional): set to ``True`` to drop the last incomplete batch, if the dataset size is not divisible by the batch size. If ``False`` and the size of dataset is not divisible by the batch size, then the last batch
                                              will be smaller. (default: ``False``)
  
                  timeout (numeric, optional): if positive, the timeout value for collecting a batch from workers. Should always be non-negative. (default: ``0``)
                  
                  worker_init_fn (callable, optional): If not ``None``, this will be called on each worker subprocess with the worker id (an int in ``[0, num_workers - 1]``) as input, after seeding and before data loading. (default: ``None``)
          """
          self.data_path = data_path
          self.train_set = datasets.CIFAR10(root = self.data_path,train = True,download = True, transform = transformations.apply_transforms(train = True))
          self.test_set = datasets.CIFAR10(root = self.data_path,train = False,download = True, transform = transformations.apply_transforms(train = False))
          self.params = {
              'shuffle': shuffle,
              'batch_size': batch_size,
              'sampler': sampler,
              'batch_sampler':batch_sampler,
              'collate_fn':collate_fn,
              'drop_last':drop_last,
              'timeout':timeout,
              'worker_init_fn':worker_init_fn,
              'multiprocessing_context':multiprocessing_context,
              'generator':generator,
              'num_workers': num_workers,
              'pin_memory': pin_memory
          }
  
      def load_data(self):
          """
              This function returns the generated dataset
  
              # Returns:
  
                  Dataset,Dataset : Generated test and train dataset
          """
          return DataLoader(self.train_set,**self.params),DataLoader(self.test_set,**self.params)
  
  class TINYIMAGENET:
      url = 'http://cs231n.stanford.edu/tiny-imagenet-200.zip'
      filename = 'tiny-imagenet-200.zip'
      dataset_folder_name = 'tiny-imagenet-200'
  
      EXTENSION = 'JPEG'
      NUM_IMAGES_PER_CLASS = 500
      CLASS_LIST_FILE = 'wnids.txt'
      VAL_ANNOTATION_FILE = 'val_annotations.txt'
  
      def __init__(self, root, train=True, transform=None, target_transform=None, download=False):
          self.root = root
          self.transform = transform
          self.target_transform = target_transform
  
          if download and (not os.path.isdir(os.path.join(self.root, self.dataset_folder_name))):
              self.download()
  
          self.split_dir = 'train' if train else 'val'
          self.split_dir = os.path.join(
              self.root, self.dataset_folder_name, self.split_dir)
          self.image_paths = sorted(glob.iglob(os.path.join(
              self.split_dir, '**', '*.%s' % self.EXTENSION), recursive=True))
  
          self.target = []
          self.labels = {}
  
          # build class label - number mapping
          with open(os.path.join(self.root, self.dataset_folder_name, self.CLASS_LIST_FILE), 'r') as fp:
              self.label_texts = sorted([text.strip()
                                         for text in fp.readlines()])
          self.label_text_to_number = {
              text: i for i, text in enumerate(self.label_texts)}
  
          # build labels for NUM_IMAGES_PER_CLASS images
          if train:
              for label_text, i in self.label_text_to_number.items():
                  for cnt in range(self.NUM_IMAGES_PER_CLASS):
                      self.labels[f'{label_text}_{cnt}.{self.EXTENSION}'] = i
  
          # build the validation dataset
          else:
              with open(os.path.join(self.split_dir, self.VAL_ANNOTATION_FILE), 'r') as fp:
                  for line in fp.readlines():
                      terms = line.split('\t')
                      file_name, label_text = terms[0], terms[1]
                      self.labels[file_name] = self.label_text_to_number[label_text]
  
          self.target = [self.labels[os.path.basename(
              filename)] for filename in self.image_paths]
  
      def download(self):
          download_and_extract_archive(
              self.url, self.root, filename=self.filename)
  
      def __getitem__(self, index):
          filepath = self.image_paths[index]
          img = Image.open(filepath)
          img = img.convert("RGB")
          target = self.target[index]
  
          if self.transform is not None:
              img = self.transform(img)
  
          if self.target_transform is not None:
              target = self.target_transform(target)
  
          return img, target
      
      def __len__(self):
          return len(self.image_paths)
  
  class DatasetTinyImageNet:
  
      def __repr__(self):
          return "Loading TinyImageNet Dataset"
  
      def __str__(self):
          return "Loading TinyImageNet Dataset"
  
      def __init__(self, data_path,transformations,*, batch_size = 32 , shuffle = True, sampler=None, batch_sampler=None, num_workers=0, collate_fn=None, pin_memory=False, drop_last=False, timeout=0, worker_init_fn=None, multiprocessing_context=None, generator=None):
          """
              This function initializes the dataset based on the values provided as parameters
  
              # Param:
  
                  data_path: Root directory of dataset where TinyImageNet/processed/train.pt and TinyImageNet/processed/test.pt exist.
  
                  batch_size (int, optional): how many samples per batch to load (default: ``1``).
  
                  shuffle (bool, optional): set to ``True`` to have the data reshuffled at every epoch (default: ``False``).
  
                  transformations:  A function/transform that takes in an PIL image and returns a transformed version. E.g, transforms.RandomCrop                
          
                  sampler (Sampler, optional): defines the strategy to draw samples from the dataset. If specified, ``shuffle`` must be False.
                  
                  batch_sampler (Sampler, optional): like sampler, but returns a batch ofindices at a time. Mutually exclusive with :attr:`batch_size`,:attr:`shuffle`, :attr:`sampler`, and :attr:`drop_last`.
          
                  num_workers (int, optional): how many subprocesses to use for dataloading. 0 means that the data will be loaded in the main process.(default: ``0``)
                  
                  collate_fn (callable, optional): merges a list of samples to form a mini-batch.
                  
                  pin_memory (bool, optional): If ``True``, the data loader will copy tensors into CUDA pinned memory before returning them.  If your data elements are a custom type, or your ``collate_fn`` returns a batch that is a custom type
                                               see the example below.
                  
                  drop_last (bool, optional): set to ``True`` to drop the last incomplete batch, if the dataset size is not divisible by the batch size. If ``False`` and the size of dataset is not divisible by the batch size, then the last batch
                                              will be smaller. (default: ``False``)
  
                  timeout (numeric, optional): if positive, the timeout value for collecting a batch from workers. Should always be non-negative. (default: ``0``)
                  
                  worker_init_fn (callable, optional): If not ``None``, this will be called on each worker subprocess with the worker id (an int in ``[0, num_workers - 1]``) as input, after seeding and before data loading. (default: ``None``)
          """
          self.data_path = data_path
          self.train_set = TINYIMAGENET(root = self.data_path,train = True,download = True, transform = transformations.apply_transforms(train = True))
          self.test_set = TINYIMAGENET(root = self.data_path,train = False,download = True, transform = transformations.apply_transforms(train = False))
          self.params = {
              'shuffle': shuffle,
              'batch_size': batch_size,
              'sampler': sampler,
              'batch_sampler':batch_sampler,
              'collate_fn':collate_fn,
              'drop_last':drop_last,
              'timeout':timeout,
              'worker_init_fn':worker_init_fn,
              'multiprocessing_context':multiprocessing_context,
              'generator':generator,
              'num_workers': num_workers,
              'pin_memory': pin_memory
          }
  
      def load_data(self):
          """
              This function returns the generated dataset
  
              # Returns:
  
                  Dataset,Dataset : Generated test and train dataset  
          """
          return DataLoader(self.train_set,**self.params),DataLoader(self.test_set,**self.params)
apis: matplotlib.pyplot.tight_layout torch.no_grad matplotlib.pyplot.subplots_adjust matplotlib.pyplot.show torch.cat numpy.uint8
apis: torch.utils.data.DataLoader