使用Tensorflow在2D张量中查找唯一值

时间:2018-07-23 22:28:06

标签: python tensorflow

tf.unique当前仅适用于一维张量。如何在2D张量中找到唯一值。

ip=tf.constant([[1,2,1],[3,4,1],[5,6,1],[1,2,1]])
#op should be  = [[1,2,1],[3,4,1],[5,6,1]]

3 个答案:

答案 0 :(得分:1)

以下功能将2D张量作为IP并返回唯一2D张量

def tf_unique_2d(x):
    x_shape=x.get_shape() #(3,2)
    x1=tf.tile(x,[1,x_shape[0]]) #[[1,2],[1,2],[1,2],[3,4],[3,4],[3,4]..]
    x2=tf.tile(x,[x_shape[0],1]) #[[1,2],[1,2],[1,2],[3,4],[3,4],[3,4]..]

    x1_2=tf.reshape(x1,[x_shape[0]*x_shape[0],x_shape[1]])
    x2_2=tf.reshape(x2,[x_shape[0]*x_shape[0],x_shape[1]])
    cond=tf.reduce_all(tf.equal(x1_2,x2_2),axis=1)
    cond=tf.reshape(cond,[x_shape[0],x_shape[0]]) #reshaping cond to match x1_2 & x2_2
    cond_shape=cond.get_shape()
    cond_cast=tf.cast(cond,tf.int32) #convertin condition boolean to int
    cond_zeros=tf.zeros(cond_shape,tf.int32) #replicating condition tensor into all 0's

    #CREATING RANGE TENSOR
    r=tf.range(x_shape[0])
    r=tf.add(tf.tile(r,[x_shape[0]]),1)
    r=tf.reshape(r,[x_shape[0],x_shape[0]])

    #converting TRUE=1 FALSE=MAX(index)+1 (which is invalid by default) so when we take min it wont get selected & in end we will only take values <max(indx).
    f1 = tf.multiply(tf.ones(cond_shape,tf.int32),x_shape[0]+1)
    f2 =tf.ones(cond_shape,tf.int32)
    cond_cast2 = tf.where(tf.equal(cond_cast,cond_zeros),f1,f2) #if false make it max_index+1 else keep it 1

    #multiply range with new int boolean mask
    r_cond_mul=tf.multiply(r,cond_cast2)
    r_cond_mul2=tf.reduce_min(r_cond_mul,axis=1)
    r_cond_mul3,unique_idx=tf.unique(r_cond_mul2)
    r_cond_mul4=tf.subtract(r_cond_mul3,1)

    #get actual values from unique indexes
    op=tf.gather(x,r_cond_mul4)

    sess=tf.Session()
    return (op)

您可以将任何2D张量传递给上面的函数,它将返回唯一的2D张量,如下所示:

import tensorflow as tf
ip=tf.constant([[1,2,1],[3,4,1],[5,6,1],[1,2,1]])
op=tf_unique_2d(ip)
print(sess.run(op))
#op = [[1,2,1],[3,4,1],[5,6,1]]

答案 1 :(得分:1)

最简单的方法是先将张量整形为一维张量,然后使用tf.unique(目前仅接受一维张量,不确定为什么!)或tf.unique_with_counts(取决于是否还需要唯一元素的计数),然后,如果还需要唯一值的索引以具有与原始张量相同的形状,则还可以对索引进行整形。以下 TensorFlow 2.1 程序对此进行了说明。

import tensorflow as tf # TF 2.1


def get_uniques(t):
    t1d = tf.reshape(t, shape=(-1,))
    # or tf.unique, if you don't need counts
    uniques, idx, counts = tf.unique_with_counts(t1d) 
    return uniques, tf.reshape(idx, shape=tf.shape(t)), counts


if __name__ == '__main__':
    my_tensor = tf.constant([[1, 2, 1], [3, 4, 1], [5, 6, 1], [1, 2, 1]])

    uniques, idx, counts = get_uniques(my_tensor)

    tf.print("tf.shape(uniques) =", tf.shape(uniques))
    tf.print("tf.shape(idx) =", tf.shape(idx))
    tf.print("tf.shape(counts) =", tf.shape(counts))
    tf.print("uniques =", uniques)

答案 2 :(得分:0)

import numpy as np
import tensorflow as tf

ip = tf.constant([[1,2,1],[3,4,1],[5,6,1],[1,2,1]])

def unique_row(x):
    return np.unique(x, axis=0)

unique = tf.py_func(unique_row, [ip], tf.int32)