由张量流中的索引张量指定的切片二维张量

Posted

技术标签:

【中文标题】由张量流中的索引张量指定的切片二维张量【英文标题】:slice 2d tensor specified by index tensor in tensorflow 【发布时间】:2019-05-30 23:24:22 【问题描述】:

我有一个二维张量,我想从每一行中提取几个起始元素。 我有必须捕获的元素的列索引(对于每一行)。 请注意,不同行的列索引不同。 以下示例使其创建: 二维张量是:

[[4 2 4 4 1 1 1 1 1 1 1 1 1 1 1 1]  
 [4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1]  
 [4 4 4 5 4 4 4 1 1 1 1 1 1 1 1 1]  
 [4 4 1 4 4 4 4 1 1 1 1 1 1 1 1 1]  
 [4 4 4 4 6 4 4 8 8 1 1 1 1 1 1 1]  
 [3 9 9 9 9 9 9 1 1 1 1 1 1 1 1 1]  
 [3 9 9 9 9 9 9 1 1 1 1 1 1 1 1 1]  
 [1 9 9 9 9 9 9 1 1 1 1 1 1 1 1 1]  
 [3 9 4 9 9 9 9 1 1 1 1 1 1 1 1 1]  
 [3 9 9 6 9 9 9 1 1 1 1 1 1 1 1 1]]  

索引数组为:

[4 7 7 7 9 7 7 7 7 7]

如何从上面的索引数组中得到下面的数组:

[[4 2 4 4 ]  
 [4 4 4 4 4 4 4 ]  
 [4 4 4 5 4 4 4]  
 [4 4 1 4 4 4 4]  
 [4 4 4 4 6 4 4 8 8]  
 [3 9 9 9 9 9 9 ]  
 [3 9 9 9 9 9 9 ]  
 [1 9 9 9 9 9 9 ]  
 [3 9 4 9 9 9 9 ]  
 [3 9 9 6 9 9 9 ]]  

【问题讨论】:

问题是你描述的输出不能是一个数组,因为每个切片都有不同的大小。你到底想得到什么?你可以有一个list 的数组或一个tf.TensorArray,但它们不如正确的tf.Tensor 有用。你打算如何使用输出? 我想将此张量转换为稀疏张量,但我不能这样做,因为行中的一些结束元素也存在于行中间。所以我想提取索引数组指定的起始元素并将结果张量转换为稀疏张量。 【参考方案1】:

这是一种将其作为稀疏张量的方法:

import tensorflow as tf

# Example data
data = [[4, 2, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
        [4, 4, 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1],
        [4, 4, 4, 5, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1],
        [4, 4, 1, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1],
        [4, 4, 4, 4, 6, 4, 4, 8, 8, 1, 1, 1, 1, 1, 1, 1],
        [3, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1],
        [3, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1],
        [1, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1],
        [3, 9, 4, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1],
        [3, 9, 9, 6, 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
sizes = [4, 7, 7, 7, 9, 7, 7, 7, 7, 7]

with tf.Graph().as_default():
    # Input data
    data_ph = tf.placeholder(tf.int32, [None, None])
    sizes_ph = tf.placeholder(tf.int32, [None])
    shape = tf.shape(data_ph)
    # Make coordinates grid
    ii, jj = tf.meshgrid(tf.range(shape[0]), tf.range(shape[1]), indexing='ij')
    # Make mask for values
    mask = jj < tf.expand_dims(sizes_ph, 1)
    # Take values and coordinates
    sp_values = tf.boolean_mask(data_ph, mask)
    sp_ii = tf.boolean_mask(ii, mask)
    sp_jj = tf.boolean_mask(jj, mask)
    # Make sparse index
    sp_idx = tf.cast(tf.stack([sp_ii, sp_jj], axis=1), tf.int64)
    # Make sparse tensor
    sp_tensor = tf.sparse.SparseTensor(sp_idx, sp_values, tf.cast(shape, tf.int64))
    # Convert back to dense for testing
    sp_to_dense = tf.sparse.to_dense(sp_tensor)
    # Test
    with tf.Session() as sess:
        sp_to_dense_value = sess.run(sp_to_dense, feed_dict=data_ph: data, sizes_ph: sizes)
        print(sp_to_dense_value)

输出:

[[4 2 4 4 0 0 0 0 0 0 0 0 0 0 0 0]
 [4 4 4 4 4 4 4 0 0 0 0 0 0 0 0 0]
 [4 4 4 5 4 4 4 0 0 0 0 0 0 0 0 0]
 [4 4 1 4 4 4 4 0 0 0 0 0 0 0 0 0]
 [4 4 4 4 6 4 4 8 8 0 0 0 0 0 0 0]
 [3 9 9 9 9 9 9 0 0 0 0 0 0 0 0 0]
 [3 9 9 9 9 9 9 0 0 0 0 0 0 0 0 0]
 [1 9 9 9 9 9 9 0 0 0 0 0 0 0 0 0]
 [3 9 4 9 9 9 9 0 0 0 0 0 0 0 0 0]
 [3 9 9 6 9 9 9 0 0 0 0 0 0 0 0 0]]

这不是绝对理想的,因为它需要使用完整的坐标网格进行操作。在 NumPy 中,您可能能够先生成索引,然后从密集张量中仅选择您想要的值,但我不确定 TensorFlow 是否可以。

【讨论】:

只需澄清一件事。 tensorflow 是否支持在以下场景中训练神经网络的这些操作:“data”张量是 network1 的输出,“sp_tensor”用于计算 network2 的损失以及 network2 的输出。由于这些操作不可微分,我怀疑 network1 和 network2 的训练是否会正确进行。

以上是关于由张量流中的索引张量指定的切片二维张量的主要内容,如果未能解决你的问题,请参考以下文章

在 Tensorflow 中使用索引对张量进行切片

当切片本身是张量流中的张量时如何进行切片分配

Pytorch 张量操作 Python切片操作

如何根据张量流中的列条件获取张量值的索引

如何在张量流中张量的某些索引处插入某些值?

[TensorFlow系列-17]:TensorFlow基础 - 张量的索引与切片