keras-team / keras

Deep Learning for humans
http://keras.io/
Apache License 2.0
61.89k stars 19.45k forks source link

How to apply a threshold filter to a layer? #20359

Open nassimus26 opened 4 days ago

nassimus26 commented 4 days ago

Having an array like this :

input = np.array([[0.04, -0.8, -1.2, 1.3, 0.85, 0.09, -0.08, 0.2]]) I want to change all the values (of the last dimension) between -0.1 and 0.1 to zero and change the rest to 1

filtred = [[0, 1, 1, 1, 1, 0, 0, 1]] Using the lamnda layer is not my favor choice (I would prefer to find a solution with a native layer which could be easily converted to TfLite without activating the SELECT_TF_OPS or the TFLITE_BUILTINS options) but I tried it anyway :

layer = tf.keras.layers.Lambda(lambda x: 0 if x <0.1 and x>-0.1 else 1)
layer(input)

I am getting :

ValueError: Exception encountered when calling Lambda.call().

The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Arguments received by Lambda.call():
  • inputs=tf.Tensor(shape=(6,), dtype=float32)
  • mask=None
  • training=None
nassimus26 commented 4 days ago

I reached this solution for the moment

def func(x):
    abs = tf.keras.backend.abs(x)
    greater = tf.keras.backend.greater(abs, 0.1) 
    return tf.keras.backend.cast(greater, dtype=tf.keras.backend.floatx()) #will return boolean values

layer = tf.keras.layers.Lambda(func)
input = np.array([[0.04, -0.8, -1.2, 1.3, 0.85, 0.09, -0.08, 0.2]])
layer(input)
mehtamansi29 commented 3 days ago

Hi @nassimus26 -

Thanks for reporting the issue. Here you can use tf.math.logical_and for checking range value from x and then pass it to lambda layer with input.

layer= keras.layers.Lambda(lambda x: tf.cast(tf.math.logical_and(x < 0.1, x > -0.1), dtype=tf.float32))
layer(input)

And you can also use lambda function bound with np.vectorize and then pass it to lambda layer with input.

lambda_func = np.vectorize(lambda x: 0 if x < 0.1 and x > -0.1 else 1)
layer= keras.layers.Lambda(lambda_func)
layer(input)