如何遍历tf.unqiue的结果?

时间:2017-10-30 04:34:55

标签: tensorflow

调用tf.unqiue后,张量的形状将是未知的,但我想遍历tf.unqiue的结果

假设tensor = tf.unqiue(...)

我试过了:

  • for t in tf.range(tf.shape(tensor)[0])
  • tf.unstack(张量,num = tf.shape(张量)[0])
  • tf.split(张量,num_or_size_splits = tf.shape(张量)[0])

所有这些功能都无法正常工作,因为这些功能都需要静态形状或num / num_or_size_splits = integer?那么我该如何遍历tensor

更新

实施例

我有两个具有相同形状的1-D张量

x=[1,3,2,1,3] y=[3,6,5,8,9]

我想这样做:

x_u = unique(x) # [1,3,2]

获取bool_mask,并切片y

for i in x_u: y[x == i]

  • 当i = 1,y [x == i] = y [[True,False,False,True,False]],我可以得到y [0]和y [3]
  • 当i = 3时,我可以得到y [1]和y [4]
  • 当i = 2时,我可以得到y [2]

解决方案

经过一些试验,这可能是一种解决方案。

尝试使用tf.while_loop

import tensorflow as tf
import numpy as np

x = tf.constant(np.array([1,3,2,1,3]), dtype='int32')
y = tf.constant(np.array([3,6,5,8,9]), dtype='int32')

x_u, _ = tf.unique(x)
n = tf.shape(x_u)[0]
for_i = tf.constant(0)
re = tf.constant([], dtype=tf.int32)
cond = lambda i, res: i<n

def body(i, res):
    x_0 = tf.slice(x_u, [i], [1])
    selected = tf.boolean_mask(y, tf.equal(x_0, x))
    return i+1, tf.concat([res, selected], axis=0)

op = tf.while_loop(cond, body, [for_i, re], shape_invariants=[for_i.get_shape(), tf.TensorShape([None])])
print(op[1].shape)

with tf.Session() as sess:
    print(sess.run(op[1]))

1 个答案:

答案 0 :(得分:0)

我刚试过这个:

import tensorflow as tf
import numpy as np

a = tf.constant(np.random.randn(200), dtype='float32')
b = tf.unique(a)
print b[0] #Tensor("Unique:0", shape=(?,), dtype=float32)

c = tf.map_fn(lambda x: x*x, b[0])

init  = tf.global_variables_initializer()

sess = tf.Session()
sess.run(init)
d = sess.run(c)

print d

它在不知道'b'的形状的情况下工作。小心,tf.unique返回一个元组(Tensor,Tensor),其中包含值及其指标。

<强>更新

这是我发现这样做的唯一方法,你的结果在Tensorflow中不会有不一致的形状。

import tensorflow as tf
import numpy as np

x = tf.constant(np.array([1,3,2,1,3]), dtype='int32')
y = tf.constant(np.array([3,6,5,8,9]), dtype='int32')

x_u = tf.unique(x)

eq = tf.equal(x, tf.expand_dims(x_u[0],1)) 

y_masked = y*tf.cast(eq, tf.int32)

init = tf.global_variables_initializer()

sess = tf.Session()
sess.run(init)
e = sess.run(y_masked)

print e

tf.boolean_mask也可以使用,但你会获得平坦的输出。

上次更新

这就是你想要的,比你提出的要快,而且已经解释了上面的那条线。

import tensorflow as tf
import numpy as np

x = tf.constant(np.array([1,3,2,1,3]), dtype='int32')
y = tf.constant(np.array([3,6,5,8,9]), dtype='int32')

x_u, _ = tf.unique(x)

eq = tf.equal(x, tf.expand_dims(x_u,1)) 

y_tiled = tf.tile(tf.expand_dims(y, 0), [tf.shape(x_u)[0], 1])
y_masked = tf.boolean_mask(y_tiled, eq)

init = tf.global_variables_initializer()

sess = tf.Session()
sess.run(init)
e = sess.run(y_masked)

print e