我有两个跟随张量(注意它们都 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
但是无法利用它来执行我上面描述的操作。
非常感谢。
- 坚持
答案 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的参数/索引)
tf.range(tf.shape(indices)[0])
。对于提供的示例,索引具有形状(64,784)。上面最后一点的另外两个张量需要具有相同的形状才能与tf.range(tf.shape(indices)[1])
tf.stack
为这两个序列中的每一个添加一个额外的维度/轴。可以通过示例显示tf.expand_dims
和tf.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