Spaces:
Sleeping
Sleeping
| import torch | |
| import torch.nn as nn | |
| import torch.nn.functional as F | |
| import torchvision | |
| import matplotlib.pyplot as plt | |
| from tqdm import tqdm | |
| import numpy as np | |
| from torch_lr_finder import LRFinder | |
| from pytorch_grad_cam import GradCAM | |
| from pytorch_grad_cam.utils.model_targets import ClassifierOutputTarget | |
| from pytorch_grad_cam.utils.image import show_cam_on_image | |
| import albumentations as A | |
| from albumentations.pytorch import ToTensorV2 | |
| # Train data transformations | |
| means = [0.4914, 0.4822, 0.4465] | |
| stds = [0.2470, 0.2435, 0.2616] | |
| train_transforms = A.Compose( | |
| [ | |
| A.Normalize(mean=means, std=stds, always_apply=True), | |
| A.PadIfNeeded(min_height=36, min_width=36, always_apply=True), | |
| A.RandomCrop(height=32, width=32, always_apply=True), | |
| A.HorizontalFlip(), | |
| A.CoarseDropout(max_holes=1, max_height=16, max_width=16, min_holes=1, min_height=8, min_width=8, fill_value=means), | |
| ToTensorV2(), | |
| ] | |
| ) | |
| test_transforms = A.Compose( | |
| [ | |
| A.Normalize(mean=means, std=stds, always_apply=True), | |
| ToTensorV2(), | |
| ] | |
| ) | |
| class Cifar10SearchDataset(torchvision.datasets.CIFAR10): | |
| def __init__(self, root="~/data", train=True, download=True, transform=None): | |
| super().__init__(root=root, train=train, download=download, transform=transform) | |
| def __getitem__(self, index): | |
| image, label = self.data[index], self.targets[index] | |
| if self.transform is not None: | |
| transformed = self.transform(image=image) | |
| image = transformed["image"] | |
| return image, label | |
| def dataloader(data_path,batch_size):#,train_transforms,test_transforms): | |
| trainset = Cifar10SearchDataset(root=data_path, train=True,download=True, transform=train_transforms) | |
| trainloader = torch.utils.data.DataLoader(trainset, batch_size=batch_size,shuffle=True) | |
| testset = Cifar10SearchDataset(root=data_path, train=False, download=True, transform=test_transforms) | |
| testloader = torch.utils.data.DataLoader(testset, batch_size=batch_size,shuffle=False) | |
| classes = trainset.classes | |
| return trainloader, testloader, classes | |
| def plot_sample_data(dataloader): | |
| batch_data, batch_label = next(iter(dataloader)) | |
| fig = plt.figure() | |
| for i in range(12): | |
| plt.subplot(3, 4, i + 1) | |
| plt.tight_layout() | |
| plt.imshow(torch.permute(batch_data[i], (1, 2, 0))) | |
| plt.title(batch_label[i].item()) | |
| plt.xticks([]) | |
| plt.yticks([]) | |
| class trainer: | |
| def __init__(self,model,device,optimizer,scheduler): | |
| self.model = model | |
| self.device = device | |
| self.optimizer = optimizer | |
| self.scheduler = scheduler | |
| self.device = device | |
| self.train_losses = [] | |
| self.test_losses = [] | |
| self.train_acc = [] | |
| self.test_acc = [] | |
| def getcorrectpredcount(self,prediction, labels): | |
| return prediction.argmax(dim=1).eq(labels).sum().item() | |
| def train(self,train_loader): | |
| self.model.train() | |
| pbar = tqdm(train_loader) | |
| train_loss = 0 | |
| correct = 0 | |
| processed = 0 | |
| criterion = nn.CrossEntropyLoss() | |
| for batch_idx, (data, target) in enumerate(pbar): | |
| data, target = data.to(self.device), target.to(self.device) | |
| self.optimizer.zero_grad() | |
| # Predict | |
| pred = self.model(data) | |
| # Calculate loss | |
| loss = criterion(pred, target) | |
| train_loss += loss.item() | |
| # Backpropagation | |
| loss.backward() | |
| self.optimizer.step() | |
| correct += self.getcorrectpredcount(pred, target) | |
| processed += len(data) | |
| pbar.set_description( | |
| desc=f'Train: Loss={loss.item():0.4f} Batch_id={batch_idx} Accuracy={100 * correct / processed:0.2f}') | |
| self.train_acc.append(100 * correct / processed) | |
| self.train_losses.append(train_loss / len(train_loader)) | |
| return self.train_acc, self.train_losses | |
| def test(self,test_loader): | |
| self.model.eval() | |
| test_loss = 0 | |
| correct = 0 | |
| with torch.no_grad(): | |
| for batch_idx, (data, target) in enumerate(test_loader): | |
| data, target = data.to(self.device), target.to(self.device) | |
| output = self.model(data) | |
| test_loss += F.cross_entropy(output, target, reduction='sum').item() # sum up batch loss | |
| correct += self.getcorrectpredcount(output, target) | |
| test_loss /= len(test_loader.dataset) | |
| self.test_acc.append(100. * correct / len(test_loader.dataset)) | |
| self.test_losses.append(test_loss) | |
| print('Test set: Average loss: {:.4f}, Accuracy: {}/{} ({:.2f}%)\n'.format( | |
| test_loss, correct, len(test_loader.dataset), | |
| 100. * correct / len(test_loader.dataset))) | |
| return self.test_acc, self.test_losses | |
| def visualize_graphs(self): | |
| t = [t_items.item() for t_items in self.train_losses] | |
| fig, axs = plt.subplots(2,2,figsize=(15,10)) | |
| axs[0, 0].plot(t) | |
| axs[0, 0].set_title("Training Loss") | |
| axs[1, 0].plot(self.train_acc[4000:]) | |
| axs[1, 0].set_title("Training Accuracy") | |
| axs[0, 1].plot(self.test_losses) | |
| axs[0, 1].set_title("Test Loss") | |
| axs[1, 1].plot(self.test_acc) | |
| axs[1, 1].set_title("Test Accuracy") | |
| def evaluate_all_class(self,classes,test_loader): | |
| # prepare to count predictions for each class | |
| correct_pred = {classname: 0 for classname in classes} | |
| total_pred = {classname: 0 for classname in classes} | |
| # again no gradients needed | |
| with torch.no_grad(): | |
| for data in test_loader: | |
| images, labels = data | |
| outputs = self.model(images) | |
| _, predictions = torch.max(outputs, 1) | |
| # collect the correct predictions for each class | |
| for label, prediction in zip(labels, predictions): | |
| if label == prediction: | |
| correct_pred[classes[label]] += 1 | |
| total_pred[classes[label]] += 1 | |
| # print accuracy for each class | |
| for classname, correct_count in correct_pred.items(): | |
| accuracy = 100 * float(correct_count) / total_pred[classname] | |
| print(f'Accuracy for class: {classname:5s} is {accuracy:.1f} %') | |
| def evaluate_model(model, loader, device): | |
| cols, rows = 4, 6 | |
| figure = plt.figure(figsize=(20, 20)) | |
| for index in range(1, cols * rows + 1): | |
| k = np.random.randint(0, len(loader.dataset)) # random points from test dataset | |
| img, label = loader.dataset[k] # separate the image and label | |
| img = img.unsqueeze(0) # adding one dimention | |
| pred = model(img.to(device)) # Prediction | |
| figure.add_subplot(rows, cols, index) # making the figure | |
| plt.title(f"Predcited label {pred.argmax().item()}\n True Label: {label}") # title of plot | |
| plt.axis("off") # hiding the axis | |
| plt.imshow(img.squeeze(), cmap="gray") # showing the plot | |
| plt.show() | |
| def get_lr(optimizer): | |
| """" | |
| for tracking how your learning rate is changing throughout training | |
| """ | |
| for param_group in optimizer.param_groups: | |
| return param_group['lr'] | |
| def lr_calc(model, train_loader, optimizer, criterion): | |
| # model = Net().to(device) | |
| # optimizer = optim.Adam(model.parameters(), lr=0.03, weight_decay=1e-4) | |
| # criterion = nn.CrossEntropyLoss() | |
| lr_finder = LRFinder(model, optimizer, criterion, device="cuda") | |
| lr_finder.range_test(train_loader, end_lr=10, num_iter=200, step_mode="exp") | |
| lr_finder.plot() # to inspect the loss-learning rate graph | |
| lr_finder.reset() # to reset the model and optimizer to their initial state | |
| def unnormalize(img): | |
| channel_means = (0.4914, 0.4822, 0.4465) | |
| channel_stdevs = (0.2470, 0.2435, 0.2616) | |
| img = img.numpy().astype(dtype=np.float32) | |
| for i in range(img.shape[0]): | |
| img[i] = (img[i]*channel_stdevs[i])+channel_means[i] | |
| return np.transpose(img, (1,2,0)) | |
| def plot_grad_cam_images(model, test_loader, classes, device): | |
| # set model to evaluation mode | |
| model.eval() | |
| target_layers = [model.layer4[-1]] | |
| # Construct the CAM object once, and then re-use it on many images: | |
| cam = GradCAM(model=model, target_layers=target_layers) | |
| misclassified_images = [] | |
| actual_labels = [] | |
| actual_targets = [] | |
| predicted_labels = [] | |
| with torch.no_grad(): | |
| for data, target in test_loader: | |
| data, target = data.to(device), target.to(device) | |
| output = model(data) | |
| _, pred = torch.max(output, 1) | |
| for i in range(len(pred)): | |
| if pred[i] != target[i]: | |
| actual_targets.append(target[i]) | |
| misclassified_images.append(data[i]) | |
| actual_labels.append(classes[target[i]]) | |
| predicted_labels.append(classes[pred[i]]) | |
| # Plot the misclassified images | |
| fig = plt.figure(figsize=(12, 5)) | |
| for i in range(10): | |
| sub = fig.add_subplot(2, 5, i+1) | |
| input_tensor = misclassified_images[i].unsqueeze(dim=0) | |
| targets = [ClassifierOutputTarget(actual_targets[i])] | |
| grayscale_cam = cam(input_tensor=input_tensor, targets=targets) | |
| grayscale_cam = grayscale_cam[0, :] | |
| visualization = show_cam_on_image(unnormalize(misclassified_images[i].cpu()), grayscale_cam, use_rgb=True,image_weight=0.7) | |
| plt.imshow(visualization) | |
| sub.set_title("Actual: {}, Pred: {}".format(actual_labels[i], predicted_labels[i]), color='red') | |
| plt.tight_layout() | |
| plt.show() | |
| def plot_misclassified_images(model, test_loader, classes, device): | |
| # set model to evaluation mode | |
| model.eval() | |
| misclassified_images = [] | |
| actual_labels = [] | |
| predicted_labels = [] | |
| with torch.no_grad(): | |
| for data, target in test_loader: | |
| data, target = data.to(device), target.to(device) | |
| output = model(data) | |
| _, pred = torch.max(output, 1) | |
| for i in range(len(pred)): | |
| if pred[i] != target[i]: | |
| misclassified_images.append(data[i]) | |
| actual_labels.append(classes[target[i]]) | |
| predicted_labels.append(classes[pred[i]]) | |
| # Plot the misclassified images | |
| fig = plt.figure(figsize=(12, 5)) | |
| for i in range(10): | |
| sub = fig.add_subplot(2, 5, i+1) | |
| npimg = unnormalize(misclassified_images[i].cpu()) | |
| plt.imshow(npimg, cmap='gray', interpolation='none') | |
| sub.set_title("Actual: {}, Pred: {}".format(actual_labels[i], predicted_labels[i]),color='red') | |
| plt.tight_layout() | |
| plt.show() |