Reputation: 1821
Lets say I have a tensor y
with shape (batch_size, n)
which contains integers. I am seeking a tensorflow function that creates two new tensors from input y
.
The first return value w1
should have shape (batch_size, n)
and contain at position b,i
, one over the number of times the integer in y[b,i]
occurs in y[b]
. If y[b,i]
is zero, then also w1[b,i]=0
. Example:
The second return value w2
should simply contain one over the number of different integers (except for 0) in each batch (or row) of y
.
y=np.array([[ 0, 0, 10, 10, 24, 24], [99, 0, 0, 12, 12, 12]])
w1,w2= get_w(y)
#w1=[[0 , 0 , 0.5, 0.5, 0.5, 0.5], [1, 0, 0, 0.33333333, 0.33333333, 0.33333333]]
#w2=[0.5,0.5]
So, how can I get tensorflow to do this?
Upvotes: 2
Views: 1327
Reputation: 17191
You can use tf.unique_with_counts
:
y = tf.constant([[0,0,10,10,24,24],[99,0,0,12,12,12]], tf.int32)
out_g = []
out_c = []
#for each row
for w in tf.unstack(y,axis=0):
# out gives unique elements in w
# idx gives index to the input w
# count gives the count of each element of out in w
out,idx, count = tf.unique_with_counts(w)
#inverse of total non zero elements in w
non_zero_count = 1/tf.count_nonzero(out)
# gather the inverse of non zero unique counts
g = tf.cast(tf.gather(1/count,idx), tf.float32) * tf.cast(tf.sign(w), tf.float32)
out_g.append(g)
out_c.append(non_zero_count)
out_g = tf.stack(out_g)
out_c = tf.stack(out_c)
with tf.Session() as sess:
print(sess.run(out_g))
print(sess.run(out_c))
#Output:
#[[0. 0. 0.5 0.5 0.5 0.5 ]
#[1. 0. 0. 0.33333334 0.33333334 0.33333334]]
# [0.5 0.5]
Upvotes: 3