在Tensorflow中用索引张量切片张量

时间:2017-03-04 15:07:02

标签: tensorflow

我有两个跟随张量(注意它们 Tensorflow张量,这意味着在我启动之前构建下面的切片操作时它们仍然是虚拟符号tf.Session()):

  • params:有形状(64,784,256)
  • indices:有形状(64,784)

我想构造一个返回以下张量的op:

  • output:有形状(64,784)

output[i,j] = params_tensor[i,j, indices[i,j] ]

Tensorflow中最有效的方法是什么?

ps:我试过tf.gather但是无法利用它来执行我上面描述的操作。

非常感谢。
- 坚持

2 个答案:

答案 0 :(得分:5)

您可以使用tf.gather_nd准确地获得所需内容。最后的表达是:

tf.gather_nd(params, tf.stack([tf.tile(tf.expand_dims(tf.range(tf.shape(indices)[0]), 1), [1, tf.shape(indices)[1]]), tf.transpose(tf.tile(tf.expand_dims(tf.range(tf.shape(indices)[1]), 1), [1, tf.shape(indices)[0]])), indices], 2))

此表达式有以下说明:

  • tf.gather_nd执行您的预期并使用索引来收集params的输出
  • tf.stack结合了三个独立的张量,最后一个是索引。前两个张量指定前两个维度的顺序(轴0和轴1的参数/索引)

    • 对于提供的示例,对于轴0,此排序仅为0,1,2,...,63,对于轴1,此顺序为0,1,2,... 783。这些序列是使用{{1分别和tf.range(tf.shape(indices)[0])
    • 对于提供的示例,索引具有形状(64,784)。上面最后一点的另外两个张量需要具有相同的形状才能与tf.range(tf.shape(indices)[1])

      结合使用
      • 首先,使用tf.stack为这两个序列中的每一个添加一个额外的维度/轴。
      • 可以通过示例显示tf.expand_dimstf.tile的使用:假设params和index的前两个轴具有形状(5,3)。我们希望第一个张量为:

        tf.transpose

        我们希望第二张量为:

        [[0, 0, 0], [1, 1, 1], [2, 2, 2], [3, 3, 3], [4, 4, 4]]
        

        这两个张量几乎就像为相关索引指定网格中的坐标一样。

  • [[0, 1, 2], [0, 1, 2], [0, 1, 2], [0, 1, 2], [0, 1, 2]] 的最后一部分将三个张量组合在一个新的第三轴上,因此结果与params具有相同的3个轴。

请记住,如果您的轴数多于或少于问题中的轴,则需要相应地修改tf.stack中指定坐标的张量的数量。

答案 1 :(得分:1)

您想要的就像自定义缩小功能。如果您在indices保留最大值索引之类的内容,那么我建议您使用tf.reduce_max

max_params = tf.reduce_max(params_tensor, reduction_indices=[2])

否则,这是获得所需内容的一种方法(Tensor对象不可分配,因此我们创建了一个张量的张量列表并使用tf.pack打包):

import tensorflow as tf
import numpy as np
with tf.Graph().as_default():

    params_tensor = tf.pack(np.random.randint(1,256, [5,5,10]).astype(np.int32))

    indices = tf.pack(np.random.randint(1,10,[5,5]).astype(np.int32))

    output = [ [None for j in range(params_tensor.get_shape()[1])] for i in range(params_tensor.get_shape()[0])]  
    for i in range(params_tensor.get_shape()[0]):
        for j in range(params_tensor.get_shape()[1]):
            output[i][j] = params_tensor[i,j,indices[i,j]]
    output = tf.pack(output)

    with tf.Session() as sess:
        params_tensor,indices,output = sess.run([params_tensor,indices,output])

        print params_tensor
        print indices
        print output