Add noise to initially binary input while keeping the data between 0 and 1

username: Joshua_Clancy
cooked: <p>I’m sure I am missing something obvious, so perhaps one of you can get me past this current idiocy.</p>
<p>I have binary (or close to binary actually a float) image data (batch, channel, x, y) and I want to add noise to the input… with the catch that it still has to remain between 0 and 1. So I am imagining simply if a pixel is 1 then minus the noise, and if the pixel is 0 then add the noise. But I do not know how to do that efficiently. without going through some slow loops. Any ideas??</p>
<pre><code class="lang-auto">class noiseLayer(nn.Module):
    def __init__(self, x_in, y_in, noisePercentage):
        super(noiseLayer, self).__init__()
        self.n_p = noisePercentage
        self.x_in = x_in
        self.y_in = y_in
    def forward(self, x, v):
        noise_tensor = torch.rand((self.x_in, self.y_in))*(self.n_p)
        if v = 1 print ("noise_tensor", noise_tensor)
        x = x + noise_tensor
        if v = 1 print ("after adding noise", x)
        # doesn't work because I get values over 1. 

        return x
</code></pre>

username: beaupreda
cooked: <p>Hello,</p>
<p>Here’s what I would do (assuming I understood your problem correctly):</p>
<pre><code class="lang-auto">class NoiseLayer(nn.Module):
    # I do not think you need the x and y dimensions here
    def __init__(self, noise_percentage):
        super(NoiseLayer, self).__init__()
        self.n_p = noise_percentage

    def forward(self, x):
        # shape of noise_tensor is the same as input x
        noise_tensor = torch.rand(size=(x.size(0), x.size(1), x.size(2), x.size(3))) * self.n_p
        print(noise_tensor)
        '''
        tensor([[[[0.0683, 0.2465, 0.2814, 0.4447],
          [0.2304, 0.1329, 0.3671, 0.3631],
          [0.1392, 0.0553, 0.1882, 0.1521],
          [0.0744, 0.4937, 0.3658, 0.1365]]],


        [[[0.4729, 0.4658, 0.2843, 0.4314],
          [0.1264, 0.4564, 0.2930, 0.2984],
          [0.0604, 0.1626, 0.0920, 0.2806],
          [0.3901, 0.0894, 0.3852, 0.1959]]]])
        '''
        mask_ones = (x == 1.0)
        mask_zeros = (x == 0.0)
        x[mask_ones] = x[mask_ones] - noise_tensor[mask_ones]
        x[mask_zeros] = x[mask_zeros] + noise_tensor[mask_zeros]
        return x

# small example
nl = NoiseLayer(0.5)
x = torch.empty(size=(2, 1, 4, 4), dtype=torch.float32).random_(0, 2)
print(x)
'''
tensor([[[[1., 0., 0., 0.],
          [1., 1., 1., 0.],
          [1., 0., 1., 0.],
          [0., 1., 0., 1.]]],


        [[[1., 0., 0., 1.],
          [1., 0., 0., 1.],
          [1., 0., 0., 0.],
          [1., 0., 1., 1.]]]])
'''
o = nl(x)
print(o)
'''
tensor([[[[0.9317, 0.2465, 0.2814, 0.4447],
          [0.7696, 0.8671, 0.6329, 0.3631],
          [0.8608, 0.0553, 0.8118, 0.1521],
          [0.0744, 0.5063, 0.3658, 0.8635]]],


        [[[0.5271, 0.4658, 0.2843, 0.5686],
          [0.8736, 0.4564, 0.2930, 0.7016],
          [0.9396, 0.1626, 0.0920, 0.2806],
          [0.6099, 0.0894, 0.6148, 0.8041]]]])
'''
</code></pre>
<p>Basically, you mask out the 1.0 and 0.0 values in your <code>x</code> tensor and subtract or add noise to only those values. Your <code>x</code> tensor will therefore always be in the <code>[0, 1]</code> range.</p>
<p>Let me know if this is not what you wanted!</p>

username: Joshua_Clancy
cooked: <p>Yes, that is exactly what I wanted!</p>
<p>I’m going to go look into masks now, as I am unfamiliar with that technique.</p>
<p>Thank you!</p>