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.
