How to add noise to inputs as a function of input

I am using torchvision.transforms.Lambda to apply noise to each input in my dataset:

torchvision.transforms.Lambda(lambda x: x + torch.rand(x.shape))

The problem is that each time a particular image is sampled, the noise that is added is different. I would like to apply the noise up front (not during training) so that every time I sample a particular image the noise is the same.

Thanks!

If you would like to apply the same random noise to the corresponding image tensor, you could initialize a noise tensor in your Dataset's __init__ function with the same length as the number of images, and add it to each tensor after the transformation.

class MyDataset(Dataset):
    def __init__(self, image_paths, targets, transform=None):
        self.image_paths = image_paths
        self.targets = targets
        self.transform = transform
        self.noise = torch.randn(len(self.image_paths), 3, 224, 224)
        
    def __getitem__(self, index):
        x = Image.open(self.image_paths[index])
        y = self.targets[index]
        if transform is not None:
            x = self.transform(x)
        x = x + self.noise[index]
        return x, y
    
    def __len__(self):
        return len(self.image_paths)
1 Like

Thanks for the tip. Ended up going with:

class NoiseDataset(datasets.MNIST):
    def __init__(self, *args, percent_noise=1, **kwargs):
        super().__init__(*args, **kwargs)
        self.percent_noise = percent_noise
        self.noise = torch.randn(self.data.shape)

    def __getitem__(self, index):
        x, y = super().__getitem__(index)
        noise = self.noise[index]
        x = noise * self.percent_noise + x * (1 - self.percent_noise)
        return x, y
2 Likes

That’s really an elegant approach to derive this class from the parent dataset. :slight_smile:
Thanks for sharing!

1 Like