0

Just like the question says, I'm trying to remove all zeros vectors (i.e [0, 0, 0, 0]) from a tensor.

Given:

array([[ 0.        ,  0.        ,  0.        ,  0.        ],
   [ 0.19999981,  0.5       ,  0.        ,  0.        ],
   [ 0.4000001 ,  0.29999995,  0.10000002,  0.        ],
   ..., 
   [-0.5999999 ,  0.        , -0.0999999 , -0.20000005],
   [-0.29999971, -0.4000001 , -0.30000019, -0.5       ],
   [ 0.        ,  0.        ,  0.        ,  0.        ]], dtype=float32)

I had tried the following code (inspired by this SO):

x = tf.placeholder(tf.float32, shape=(10000, 4))

zeros_vector = tf.zeros(shape=(1, 4), dtype=tf.float32)
bool_mask = tf.not_equal(x, zero_vector)

omit_zeros = tf.boolean_mask(x, bool_mask)

But bool_mask seem also to be of shape (10000, 4), like it was comparing every element in the x tensor to zero, and not rows.

I thought about using tf.reduce_sum where an entire row is zero, but that will omit also rows like [1, -1, 0, 0] and I don't want that.

Ideas?

Community
  • 1
  • 1
bluesummers
  • 11,365
  • 8
  • 72
  • 108

3 Answers3

4

One possible way would be to sum over the absolute values of the row, in this way it will not omit rows like [1, -1, 0, 0] and then compare it with a zero vector. You can do something like this:

intermediate_tensor = reduce_sum(tf.abs(x), 1)
zero_vector = tf.zeros(shape=(1,1), dtype=tf.float32)
bool_mask = tf.not_equal(intermediate_tensor, zero_vector)
omit_zeros = tf.boolean_mask(x, bool_mask)
Rudresh Panchal
  • 980
  • 4
  • 16
  • can't believe I figured out `reduce_sum` and didn't think of using `abs`. seems like a legit solution, I will try to make sure it works and upvote + accept if applicable – bluesummers Jun 25 '17 at 09:12
1

I tried solution by Rudresh Panchal and it doesn't work for me. Maybe due versions change. I found tipo in the first row: reduce_sum(tf.abs(x), 1) -> tf.reduce_sum(tf.abs(x), 1).

Also, bool_mask has rank 2 instead of rank 1, which is required: tensor: N-D tensor. mask: K-D boolean tensor, K <= N and K must be known statically. In other words, the shape of bool_mask must be for example [6] not [1,6]. tf.squeeze works well to reduce dimension.

Corrected code which works for me:

intermediate_tensor = tf.reduce_sum(tf.abs(x), 1)
zero_vector = tf.zeros(shape=(1,1), dtype=tf.float32)
bool_mask = tf.squeeze(tf.not_equal(intermediate_tensor, zero_vector))
omit_zeros = tf.boolean_mask(x, bool_mask)
Tommy
  • 159
  • 1
  • 11
1

Just cast the tensor to tf.bool and use it as a boolean mask:

boolean_mask = tf.cast(x, dtype=tf.bool)              
no_zeros = tf.boolean_mask(x, boolean_mask, axis=0)
Keotic
  • 11
  • 3