FiReTiTi
FiReTiTi

Reputation: 5878

Modify Tensor Values

I wanted to create my own Keras noise layer, so I started from the Keras GaussianNoise code. The call method is:

def call(self, inputs, training=None):
    def noised():
        return inputs + K.random_normal(shape=K.shape(inputs), mean=0., stddev=self.stddev)
    return K.in_train_phase(noised, inputs, training=training)

I wanted the random noise to be applied only to X% of the pixels, not all of them. So I need to generate an other random binary tensor (with random 0 and 1). Following this discussion, the solution seems to use a constant tensor and do something like that:

randomtensor = K.random_uniform(shape=K.shape(inputs), minval=0.0, maxval=100.0)
constensor = K.constant(0.0, shape=K.shape(inputs))
cond = K.less(randomvalues, constensor)
randomtensor = K.switch(cond, 1, randomtensor)
cond = K.greater_equal(randomvalues, constensor)
randomtensor = K.switch(cond, 0, randomtensor)

Unfortunately, there is an issue with the constant tensor, and I get the following error:

  File "/Users/firetiti/NN/Keras/Contributions_Noise.py", line 50, in noised
    constensor = K.constant(0.0, shape=K.shape(inputs))
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/keras/backend/tensorflow_backend.py", line 358, in constant
    return tf.constant(value, dtype=dtype, shape=shape, name=name)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/tensorflow/python/framework/constant_op.py", line 102, in constant
    tensor_util.make_tensor_proto(value, dtype=dtype, shape=shape, verify_shape=verify_shape))
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/tensorflow/python/framework/tensor_util.py", line 416, in make_tensor_proto
    shape = [int(dim) for dim in shape]
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/tensorflow/python/framework/ops.py", line 541, in iter
    raise TypeError("'Tensor' object is not iterable.")
TypeError: 'Tensor' object is not iterable.

What am I doing wrong?

Is there a better way to generate a random binary tensor?

Upvotes: 2

Views: 1683

Answers (1)

Andre Holzner
Andre Holzner

Reputation: 18675

K.switch() takes a zero dimension expression (i.e. is not an element-wise if)

Does the following do what you want ?

from keras import backend as K
import numpy as np

a = np.asarray([[3,4,2,44,22,4,5,6,77,86,3,2,3,23,44,21],
                [3,4,22,44,2,4,54,6,77,8,3,2,36,23,4,2]], dtype=np.float)
inputs = K.variable(a)

# probability per pixel to add noise
prob_noise = 0.2

# standard deviation of noise
noise_stddev = 0.1

# noise_mask will be a tensor of floats which are one
# if and only if the corresponding random value falls into the interval
# [0..prob_noise)
noise_mask = K.cast(
    K.less(
        K.random_uniform(shape=inputs.shape, minval=0.0, maxval=1.0),
        prob_noise),
   'float32')

noise = K.random_normal(shape = inputs.shape , mean=0., stddev = noise_stddev)

noised = inputs + noise * noise_mask

print K.eval(noised)

Note that this does not guarantee that for each image exactly prob_noise of the pixels will be smeared with noise, this holds only on average.

Upvotes: 3

Related Questions