Home > Software engineering >  Equivalent of np.convolve in keras backend
Equivalent of np.convolve in keras backend

Time:01-13

I have following function

def pad_ones(arr):
    return np.convolve(arr, [1, 1, 1], "same") 

# for example:
# >>> pad_ones([0, 0, 0, 1, 0, 0])
# array([0, 0, 1, 1, 1, 0])

which I want to use to process one_hot encoded arrays. This currently throws an error in tensorflow:

NotImplementedError: Cannot convert a symbolic Tensor to a numpy array. This error may indicate that you're trying to pass a Tensor to a NumPy call, which is not supported

So I tried implementing it using keras.backend, but couldn't find the proper solution. What is the keras backend equivalent of np.convolve? I have found articles that state that keras convolution is the same as np.correlate, but I haven't found any articles explaining what the equivalent of np.convolve is in keras.backend.

I tried using K.conv1d like so:

K.conv1d(K.constant([0, 0, 1, 0, 0, 0]), K.constant([1, 1, 1]), "same")

But I get the following error:

ValueError: "num_spatial_dims" must be 1, 2, or 3. Received: num_spatial_dims=-1.

Final Solution (special thanks to @AloneTogether):

def keras_pad_ones(one_hot_2d_matrix):
    kernel = K.constant([1, 1, 1], shape=(3, 1, 1))
    x = K.expand_dims(one_hot_2d_matrix)
    x = K.conv1d(x, kernel, padding='same')
    x = K.squeeze(x, axis=-1)
    return x

# Example:
# >>> arr_1d = K.constant([0, 0, 0, 1, 0, 0])
# >>> keras_pad_ones(K.expand_dims(arr_1d, axis=0))
# output: [[0., 0., 1., 1., 1., 0.]]

# >>> arr_2d = K.constant([[0, 0, 0, 1, 0, 0], [1, 0, 0, 0, 0, 0]])
# >>> keras_pad_ones(arr_2d)
# output: [[0., 0., 1., 1., 1., 0.], [1., 1., 0., 0., 0., 0.]]

CodePudding user response:

A simple way to replicate np.convolve with Tensorflow is using tf.nn.conv1d:

import tensorflow as tf

original = tf.constant([0, 0, 0, 1, 0, 0], dtype=tf.float32)
x = tf.reshape(original, (1, tf.shape(original)[0],  1))
kernel = tf.constant([1, 1, 1], dtype=tf.float32)
kernel = tf.reshape(kernel, [tf.shape(kernel)[0], 1, 1])

x = tf.nn.conv1d(x, kernel, padding='SAME', stride=1)
x = tf.reshape(x, (tf.shape(x)[1]))

print(original)
print(x)
tf.Tensor([0. 0. 0. 1. 0. 0.], shape=(6,), dtype=float32)
tf.Tensor([0. 0. 1. 1. 1. 0.], shape=(6,), dtype=float32)

or with tf.keras.backend.conv1d like this:

x = tf.keras.backend.conv1d(x, kernel, padding='same', strides=1)

The rest of the code remains the same.

  •  Tags:  
  • Related