From 1abb489cdc250af52800a2101f6251755829a549 Mon Sep 17 00:00:00 2001 From: someshsingh22 Date: Tue, 24 Aug 2021 17:58:53 +0530 Subject: [PATCH 1/3] Initial Tests --- code_soup/common/__init__.py | 1 + code_soup/common/perturbations.py | 12 ++++ code_soup/common/vision/perturbations.py | 39 ++++++++++++ .../test_vision/test_perturbations.py | 60 +++++++++++++++++++ 4 files changed, 112 insertions(+) create mode 100644 code_soup/common/perturbations.py create mode 100644 code_soup/common/vision/perturbations.py create mode 100644 tests/test_common/test_vision/test_perturbations.py diff --git a/code_soup/common/__init__.py b/code_soup/common/__init__.py index e69de29..452a833 100644 --- a/code_soup/common/__init__.py +++ b/code_soup/common/__init__.py @@ -0,0 +1 @@ +from code_soup.common.vision.perturbations import VisualPerturbation diff --git a/code_soup/common/perturbations.py b/code_soup/common/perturbations.py new file mode 100644 index 0000000..cc4a7fa --- /dev/null +++ b/code_soup/common/perturbations.py @@ -0,0 +1,12 @@ +from abc import ABC, abstractmethod + + +class Perturbation(ABC): + """ + Docstring for Abstract Class Perturbation + """ + + @abstractmethod + @classmethod + def __init__(self): + pass diff --git a/code_soup/common/vision/perturbations.py b/code_soup/common/vision/perturbations.py new file mode 100644 index 0000000..35b53df --- /dev/null +++ b/code_soup/common/vision/perturbations.py @@ -0,0 +1,39 @@ +from abc import abstractmethod +from typing import Union + +import numpy as np +import torch + +from code_soup.common.perturbations import Perturbation + + +class VisualPerturbation(Perturbation): + """ + Docstring for VisualPerturbations + """ + + def __init__( + self, + original: Union[np.ndarray, torch.Tensor], + perturbed: Union[np.ndarray, torch.Tensor], + ): + """ + Docstring + #Automatically cast to Tensor using the torch.from_numpy() in the __init__ using if + """ + raise NotImplementedError + + def calculate_LPNorm(self, p: Union[int, str]): + raise NotImplementedError + + def calculate_PSNR(self): + raise NotImplementedError + + def calculate_RMSE(self): + raise NotImplementedError + + def calculate_SAM(self): + raise NotImplementedError + + def calculate_SRE(self): + raise NotImplementedError diff --git a/tests/test_common/test_vision/test_perturbations.py b/tests/test_common/test_vision/test_perturbations.py new file mode 100644 index 0000000..294b8b5 --- /dev/null +++ b/tests/test_common/test_vision/test_perturbations.py @@ -0,0 +1,60 @@ +import random +import unittest + +import numpy as np +import torch +from torchvision.datasets.fakedata import FakeData +from torchvision.transforms import ToTensor + +from code_soup.common import VisualPerturbation + + +class TestVisualPerturbation(unittest.TestCase): + @classmethod + def setUpClass(cls) -> None: + torch.manual_seed(42) + np.random.seed(42) + random.seed(42) + df = FakeData(size=2, image_size=(3, 64, 64)) + a, b = tuple(df) + a, b = ToTensor()(a[0]).unsqueeze_(0), ToTensor()(b[0]).unsqueeze_(0) + cls.obj_tensor = VisualPerturbation(original=a, perturbed=b) + cls.obj_numpy = VisualPerturbation(original=a.numpy(), perturbed=b.numpy()) + + def test_LPNorm(self): + self.assertAlmostEqual( + TestVisualPerturbation.obj_tensor.calculate_LPNorm(p=1), 4143.0249, places=3 + ) + self.assertAlmostEqual( + TestVisualPerturbation.obj_numpy.calculate_LPNorm(p="fro"), + 45.6525, + places=3, + ) + + def test_PSNR(self): + self.assertAlmostEqual( + TestVisualPerturbation.obj_tensor.calculate_PSNR(), + 33.773994480876496, + places=3, + ) + + def test_RMSE(self): + self.assertAlmostEqual( + TestVisualPerturbation.obj_tensor.calculate_RMSE(), + 0.018409499898552895, + places=3, + ) + + def test_SAM(self): + self.assertAlmostEqual( + TestVisualPerturbation.obj_tensor.calculate_SAM(), + 89.34839413786915, + places=3, + ) + + def test_SRE(self): + self.assertAlmostEqual( + TestVisualPerturbation.obj_tensor.calculate_SRE(), + 41.36633261587073, + places=3, + ) From 48e548e1bdc91c88ad198e8161542890fe919128 Mon Sep 17 00:00:00 2001 From: someshsingh22 Date: Tue, 24 Aug 2021 18:12:17 +0530 Subject: [PATCH 2/3] Added Vision Perturbation Skeleton --- code_soup/common/__init__.py | 1 - code_soup/common/{perturbations.py => perturbation.py} | 2 +- code_soup/common/vision/perturbations.py | 2 +- tests/test_common/test_vision/test_perturbations.py | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) rename code_soup/common/{perturbations.py => perturbation.py} (100%) diff --git a/code_soup/common/__init__.py b/code_soup/common/__init__.py index 452a833..e69de29 100644 --- a/code_soup/common/__init__.py +++ b/code_soup/common/__init__.py @@ -1 +0,0 @@ -from code_soup.common.vision.perturbations import VisualPerturbation diff --git a/code_soup/common/perturbations.py b/code_soup/common/perturbation.py similarity index 100% rename from code_soup/common/perturbations.py rename to code_soup/common/perturbation.py index cc4a7fa..b2e023d 100644 --- a/code_soup/common/perturbations.py +++ b/code_soup/common/perturbation.py @@ -6,7 +6,7 @@ class Perturbation(ABC): Docstring for Abstract Class Perturbation """ - @abstractmethod @classmethod + @abstractmethod def __init__(self): pass diff --git a/code_soup/common/vision/perturbations.py b/code_soup/common/vision/perturbations.py index 35b53df..c68bc3c 100644 --- a/code_soup/common/vision/perturbations.py +++ b/code_soup/common/vision/perturbations.py @@ -4,7 +4,7 @@ import numpy as np import torch -from code_soup.common.perturbations import Perturbation +from code_soup.common.perturbation import Perturbation class VisualPerturbation(Perturbation): diff --git a/tests/test_common/test_vision/test_perturbations.py b/tests/test_common/test_vision/test_perturbations.py index 294b8b5..eb71992 100644 --- a/tests/test_common/test_vision/test_perturbations.py +++ b/tests/test_common/test_vision/test_perturbations.py @@ -6,7 +6,7 @@ from torchvision.datasets.fakedata import FakeData from torchvision.transforms import ToTensor -from code_soup.common import VisualPerturbation +from code_soup.common.vision.perturbations import VisualPerturbation class TestVisualPerturbation(unittest.TestCase): From c0d6e4d6f8cb3c19e852a3bdbc710d947c38ec4a Mon Sep 17 00:00:00 2001 From: devaletanmay <56354045+devaletanmay@users.noreply.github.com> Date: Wed, 1 Sep 2021 02:06:34 +0530 Subject: [PATCH 3/3] Implemented RMSE, PSNR and LKNorm (#75) Co-authored-by: abhi-glitchhg <72816663+abhi-glitchhg@users.noreply.github.com> --- code_soup/ch5/models/gan.py | 5 ++- code_soup/common/vision/perturbations.py | 47 ++++++++++++++++++++---- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/code_soup/ch5/models/gan.py b/code_soup/ch5/models/gan.py index 71e62c0..d8236fb 100644 --- a/code_soup/ch5/models/gan.py +++ b/code_soup/ch5/models/gan.py @@ -169,6 +169,8 @@ def step(self, data: torch.Tensor) -> Tuple: Discriminator loss D_G_z2: Average discriminator outputs for the all fake batch after updating discriminator + errG: + Generator loss """ real_image, _ = data real_image = real_image.to(self.device) @@ -176,6 +178,7 @@ def step(self, data: torch.Tensor) -> Tuple: label = torch.full( (batch_size,), self.real_label, dtype=torch.float, device=self.device ) + self.discriminator.zero_grad() # Forward pass real batch through D output = self.discriminator(real_image).view(-1) # Calculate loss on all-real batch @@ -211,4 +214,4 @@ def step(self, data: torch.Tensor) -> Tuple: D_G_z2 = output.mean().item() # Update G self.generator.optimizer.step() - return D_x, D_G_z1, errD, D_G_z2 + return D_x, D_G_z1, errD, D_G_z2, errG diff --git a/code_soup/common/vision/perturbations.py b/code_soup/common/vision/perturbations.py index c68bc3c..bdc85cf 100644 --- a/code_soup/common/vision/perturbations.py +++ b/code_soup/common/vision/perturbations.py @@ -3,13 +3,19 @@ import numpy as np import torch +import torch.nn as nn + +from math import log10 from code_soup.common.perturbation import Perturbation class VisualPerturbation(Perturbation): """ - Docstring for VisualPerturbations + An abstract method for various Visual Perturbation Metrics + Methods + __init__(self, original : Union[np.ndarray, torch.Tensor], perturbed: Union[np.ndarray, torch.Tensor]) + - init method """ def __init__( @@ -21,16 +27,41 @@ def __init__( Docstring #Automatically cast to Tensor using the torch.from_numpy() in the __init__ using if """ - raise NotImplementedError - def calculate_LPNorm(self, p: Union[int, str]): - raise NotImplementedError + if type(original) == torch.Tensor: + self.original = original + else: + self.original = torch.from_numpy(original) + print(self.original.shape) - def calculate_PSNR(self): - raise NotImplementedError + if type(perturbed) == torch.Tensor: + self.perturbed = perturbed + else: + self.perturbed = torch.from_numpy(perturbed) - def calculate_RMSE(self): - raise NotImplementedError + def flatten(self, array : torch.tensor) -> torch.Tensor: + return array.flatten() + + def totensor(self, array : np.ndarray) -> torch.Tensor: + return torch.from_numpy(array) + + def subtract(self,original : torch.Tensor, perturbed : torch.Tensor) -> torch.Tensor: + return torch.sub(original, perturbed) + + def calculate_LPNorm(self, p: Union[int, str]) -> float: + if p == 'inf': + return torch.linalg.vector_norm(self.flatten(self.subtract(self.original,self.perturbed)), ord = float('inf')).item() + elif p == 'fro': + return self.calculate_LPNorm(2) + else: + return torch.linalg.norm(self.flatten(self.subtract(self.original,self.perturbed)), ord = p).item() + + def calculate_PSNR(self) -> float: + return 20 * log10(1.0/self.calculate_RMSE()) + + def calculate_RMSE(self) -> float: + loss = nn.MSELoss() + return (loss(self.original, self.perturbed)**0.5).item() def calculate_SAM(self): raise NotImplementedError