Summary
I am looking for a function is_unique
that for each element in a tensorflow tf.Tensor
returns a boolean value whether its value is unique within the tensor.
Example input / output:
In [7]: idx = tf.constant([162, 223, 276, 162, 261, 215, 0, 0, 0], dtype=tf.int64)
In [8]: is_unique(idx)
Out[8]: <tf.*Tensor*: shape=(9,), dtype=bool, numpy=array([False, True, True, False, True, True, False, False, False])>
Adding another example on request for a tensor with higher rank: For a rank-2 tensor
tf.constant([[1, 2], [1, 3]], dtype=tf.int32)
the function would yield
<tf.Tensor: shape=(2, 2), dtype=bool, numpy=
array([[False, True],
[False, True]])>
This seems to be rather basic, but I believe there is no such function in tensorflow, or is there?
My code:
I haven't found a simple way to achieve this with tf.unique
et al., so my current implementation looks like this:
def is_unique(t):
return tf.equal(
tf.reduce_sum(
tf.cast(
t[:,tf.newaxis] == t,
tf.int64,
),
axis = 1
),
1
)
(Basically, this creates a matrix of comparisons of every element with every other, counts the number of positive outcomes per row and compares this with 1.)
This won't work with tensors of rank > 1 and needs quadratic memory in the tensor size, so feel free to propose better solutions.
CodePudding user response:
Rank 1 solution, although very similar to yours:
import tensorflow as tf
x = tf.constant([162, 223, 276, 162, 261, 215, 0, 0, 0], dtype=tf.int64)
y, _, count = tf.unique_with_counts(x)
x = tf.reduce_all(tf.where(x == tf.gather(y, tf.where(count > 1)), False, True), axis=0)
tf.Tensor([False True True False True True False False False], shape=(9,), dtype=bool)
Rank 2 solution (see improved version @I'mahdi)
CodePudding user response:
You can use tensorflow.unique_with_counts
and tf.math.reduce_any
For rank==1
:
import tensorflow as tf
x = tf.constant([162, 223, 276, 162, 261, 215, 0, 0, 0], dtype=tf.int64)
y, _, count = tf.unique_with_counts(x)
res = tf.reduce_any(x[:, None] == y[count < 2], axis=1)
print(res)
# tf.Tensor([False True True False True True False False False], shape=(9,), dtype=bool)
For rank==2
:
x = tf.constant([[1, 2],
[1, 3],
[4, 3]], dtype=tf.int32) # 2 & 4 are unique
y, _, count = tf.unique_with_counts(tf.experimental.numpy.ravel(x))
res = tf.reduce_any(x[..., None] == y[count < 2], axis=2)
print(res)
# tf.Tensor(
# [[False True]
# [False False]
# [ True False]], shape=(3, 2), dtype=bool)
For another Input:
x = tf.constant([[1, 2],
[1, 3],
[3, 1]], dtype=tf.int32) # 2 is unique
y, _, count = tf.unique_with_counts(tf.experimental.numpy.ravel(x))
res = tf.reduce_any(x[..., None] == y[count < 2], axis=2)
print(res)
# tf.Tensor(
# [[False True]
# [False False]
# [False False]], shape=(3, 2), dtype=bool)